diff options
| author | vvvv <[email protected]> | 2024-12-18 21:57:17 +0300 |
|---|---|---|
| committer | vvvv <[email protected]> | 2024-12-18 22:58:34 +0300 |
| commit | f7f8a1dcd4b4b4a1af7acc6d8127d285c3850795 (patch) | |
| tree | c22ca71d9eb197030fbd946452f4aadf613df95c /yql/essentials/minikql/jsonpath/parser/parser.cpp | |
| parent | 9690d79e797ada85de4a648fbc1e386ea4621efe (diff) | |
Extracted parser from jsonpath lib
init
commit_hash:8c6dd46ee72034f0480757612dcceb524d19a1d1
Diffstat (limited to 'yql/essentials/minikql/jsonpath/parser/parser.cpp')
| -rw-r--r-- | yql/essentials/minikql/jsonpath/parser/parser.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/yql/essentials/minikql/jsonpath/parser/parser.cpp b/yql/essentials/minikql/jsonpath/parser/parser.cpp new file mode 100644 index 00000000000..105305ea3c5 --- /dev/null +++ b/yql/essentials/minikql/jsonpath/parser/parser.cpp @@ -0,0 +1,104 @@ +#include "parser.h" + +#include "ast_builder.h" +#include "type_check.h" + +#include <yql/essentials/core/issue/protos/issue_id.pb.h> +#include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathLexer.h> +#include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathParser.h> +#include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathParser.pb.h> +#include <yql/essentials/parser/proto_ast/antlr3/proto_ast_antlr3.h> + +#include <google/protobuf/message.h> + +#if defined(_tsan_enabled_) +#include <util/system/mutex.h> +#endif + +#include <util/string/strip.h> + +namespace { + +using namespace NYql; + +#if defined(_tsan_enabled_) +TMutex SanitizerJsonPathTranslationMutex; +#endif + +class TParseErrorsCollector : public NProtoAST::IErrorCollector { +public: + TParseErrorsCollector(TIssues& issues, size_t maxErrors) + : IErrorCollector(maxErrors) + , Issues(issues) + { + } + +private: + void AddError(ui32 line, ui32 column, const TString& message) override { + Issues.AddIssue(TPosition(column, line, "jsonpath"), StripString(message)); + Issues.back().SetCode(TIssuesIds::JSONPATH_PARSE_ERROR, TSeverityIds::S_ERROR); + } + + TIssues& Issues; +}; + +} + +namespace NYql::NJsonPath { + +const TAstNodePtr ParseJsonPathAst(const TStringBuf path, TIssues& issues, size_t maxParseErrors) { + if (!IsUtf(path)) { + issues.AddIssue(TPosition(1, 1, "jsonpath"), "JsonPath must be UTF-8 encoded string"); + issues.back().SetCode(TIssuesIds::JSONPATH_PARSE_ERROR, TSeverityIds::S_ERROR); + return {}; + } + + google::protobuf::Arena arena; + const google::protobuf::Message* rawAst = nullptr; + { + #if defined(_tsan_enabled_) + TGuard<TMutex> guard(SanitizerJsonPathTranslationMutex); + #endif + NProtoAST::TProtoASTBuilder3<NALP::JsonPathParser, NALP::JsonPathLexer> builder(path, "JsonPath", &arena); + TParseErrorsCollector collector(issues, maxParseErrors); + rawAst = builder.BuildAST(collector); + } + + if (rawAst == nullptr) { + return nullptr; + } + + const google::protobuf::Descriptor* descriptor = rawAst->GetDescriptor(); + if (descriptor && descriptor->name() != "TJsonPathParserAST") { + return nullptr; + } + + const auto* protoAst = static_cast<const NJsonPathGenerated::TJsonPathParserAST*>(rawAst); + TAstBuilder astBuilder(issues); + TAstNodePtr ast = astBuilder.Build(*protoAst); + if (!issues.Empty()) { + return nullptr; + } + + // At this point AST is guaranteed to be valid. We return it even if + // type checker finds some logical errors. + TJsonPathTypeChecker checker(issues); + ast->Accept(checker); + return ast; +} + +const TJsonPathPtr PackBinaryJsonPath(const TAstNodePtr ast) { + TJsonPathBuilder builder; + ast->Accept(builder); + return builder.ShrinkAndGetResult(); +} + +const TJsonPathPtr ParseJsonPath(const TStringBuf path, TIssues& issues, size_t maxParseErrors) { + const auto ast = ParseJsonPathAst(path, issues, maxParseErrors); + if (!issues.Empty()) { + return {}; + } + return PackBinaryJsonPath(ast); +} + +} |
