summaryrefslogtreecommitdiffstats
path: root/yql/essentials/parser/lexer_common/parse_hints_impl.cpp
diff options
context:
space:
mode:
authorvvvv <[email protected]>2024-11-03 01:25:03 +0300
committervvvv <[email protected]>2024-11-03 01:34:36 +0300
commit91ad4d5672563da0f1a92c648414adb27905dafe (patch)
tree81bf246c784cd7a02075a8837d18bf73253ae6ae /yql/essentials/parser/lexer_common/parse_hints_impl.cpp
parentc2859fd279d6f460881911637b04622f7b76b1c2 (diff)
Moved yql/parser (w/o pg_wrapper) & yql/protos YQL-19206
init commit_hash:71603ddfc208bf4ab1691d886ac35f22c107e3ee
Diffstat (limited to 'yql/essentials/parser/lexer_common/parse_hints_impl.cpp')
-rw-r--r--yql/essentials/parser/lexer_common/parse_hints_impl.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/yql/essentials/parser/lexer_common/parse_hints_impl.cpp b/yql/essentials/parser/lexer_common/parse_hints_impl.cpp
new file mode 100644
index 00000000000..10a0257e5df
--- /dev/null
+++ b/yql/essentials/parser/lexer_common/parse_hints_impl.cpp
@@ -0,0 +1,105 @@
+#include "parse_hints_impl.h"
+
+#include <yql/essentials/utils/yql_panic.h>
+
+namespace NSQLTranslation {
+
+namespace NDetail {
+
+enum EParseState {
+ INITIAL,
+ NAME,
+ IN_PARENS,
+ IN_QUOTED_VALUE,
+ IN_VALUE,
+ WANT_WS,
+};
+
+TVector<TSQLHint> ParseSqlHints(NYql::TPosition commentPos, const TStringBuf& comment, bool utf8Aware) {
+ TVector<TSQLHint> result;
+ if (!comment.StartsWith("/*+") && !comment.StartsWith("--+")) {
+ return result;
+ }
+ TSQLHint hint;
+ NYql::TTextWalker commentWalker(commentPos, utf8Aware);
+ const size_t len = comment.size();
+ EParseState state = EParseState::INITIAL;
+ for (size_t i = 0; i < len; ++i) {
+ auto c = comment[i];
+ switch (state) {
+ case EParseState::INITIAL: {
+ if (std::isalpha(c)) {
+ hint.Pos = commentPos;
+ hint.Name.push_back(c);
+ state = EParseState::NAME;
+ }
+ break;
+ }
+ case EParseState::NAME: {
+ if (std::isalnum(c)) {
+ hint.Name.push_back(c);
+ } else if (c == '(') {
+ state = EParseState::IN_PARENS;
+ } else {
+ hint = {};
+ state = std::isspace(c) ? EParseState::INITIAL : EParseState::WANT_WS;
+ }
+ break;
+ }
+ case EParseState::IN_PARENS: {
+ if (c == ')') {
+ result.emplace_back();
+ std::swap(hint, result.back());
+ state = EParseState::WANT_WS;
+ } else if (c == '\'') {
+ hint.Values.emplace_back();
+ state = EParseState::IN_QUOTED_VALUE;
+ } else if (!std::isspace(c)) {
+ hint.Values.emplace_back();
+ hint.Values.back().push_back(c);
+ state = EParseState::IN_VALUE;
+ }
+ break;
+ }
+ case EParseState::IN_QUOTED_VALUE: {
+ YQL_ENSURE(!hint.Values.empty());
+ if (c == '\'') {
+ if (i + 1 < len && comment[i + 1] == '\'') {
+ ++i;
+ commentWalker.Advance(c);
+ hint.Values.back().push_back(c);
+ } else {
+ state = EParseState::IN_PARENS;
+ }
+ } else {
+ hint.Values.back().push_back(c);
+ }
+ break;
+ }
+ case EParseState::IN_VALUE: {
+ if (std::isspace(c)) {
+ state = EParseState::IN_PARENS;
+ } else if (c == ')') {
+ result.emplace_back();
+ std::swap(hint, result.back());
+ state = EParseState::WANT_WS;
+ } else {
+ hint.Values.back().push_back(c);
+ }
+ break;
+ }
+ case EParseState::WANT_WS: {
+ if (std::isspace(c)) {
+ state = EParseState::INITIAL;
+ }
+ break;
+ }
+ }
+ commentWalker.Advance(c);
+ }
+ return result;
+}
+
+}
+
+}