parser.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #include "parser.h"
  2. #include "ast_builder.h"
  3. #include "type_check.h"
  4. #include <yql/essentials/core/issue/protos/issue_id.pb.h>
  5. #include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathLexer.h>
  6. #include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathParser.h>
  7. #include <yql/essentials/parser/proto_ast/gen/jsonpath/JsonPathParser.pb.h>
  8. #include <yql/essentials/parser/proto_ast/antlr3/proto_ast_antlr3.h>
  9. #include <google/protobuf/message.h>
  10. #if defined(_tsan_enabled_)
  11. #include <util/system/mutex.h>
  12. #endif
  13. #include <util/string/strip.h>
  14. namespace {
  15. using namespace NYql;
  16. #if defined(_tsan_enabled_)
  17. TMutex SanitizerJsonPathTranslationMutex;
  18. #endif
  19. class TParseErrorsCollector : public NProtoAST::IErrorCollector {
  20. public:
  21. TParseErrorsCollector(TIssues& issues, size_t maxErrors)
  22. : IErrorCollector(maxErrors)
  23. , Issues(issues)
  24. {
  25. }
  26. private:
  27. void AddError(ui32 line, ui32 column, const TString& message) override {
  28. Issues.AddIssue(TPosition(column, line, "jsonpath"), StripString(message));
  29. Issues.back().SetCode(TIssuesIds::JSONPATH_PARSE_ERROR, TSeverityIds::S_ERROR);
  30. }
  31. TIssues& Issues;
  32. };
  33. }
  34. namespace NYql::NJsonPath {
  35. const TAstNodePtr ParseJsonPathAst(const TStringBuf path, TIssues& issues, size_t maxParseErrors) {
  36. if (!IsUtf(path)) {
  37. issues.AddIssue(TPosition(1, 1, "jsonpath"), "JsonPath must be UTF-8 encoded string");
  38. issues.back().SetCode(TIssuesIds::JSONPATH_PARSE_ERROR, TSeverityIds::S_ERROR);
  39. return {};
  40. }
  41. google::protobuf::Arena arena;
  42. const google::protobuf::Message* rawAst = nullptr;
  43. {
  44. #if defined(_tsan_enabled_)
  45. TGuard<TMutex> guard(SanitizerJsonPathTranslationMutex);
  46. #endif
  47. NProtoAST::TProtoASTBuilder3<NALP::JsonPathParser, NALP::JsonPathLexer> builder(path, "JsonPath", &arena);
  48. TParseErrorsCollector collector(issues, maxParseErrors);
  49. rawAst = builder.BuildAST(collector);
  50. }
  51. if (rawAst == nullptr) {
  52. return nullptr;
  53. }
  54. const google::protobuf::Descriptor* descriptor = rawAst->GetDescriptor();
  55. if (descriptor && descriptor->name() != "TJsonPathParserAST") {
  56. return nullptr;
  57. }
  58. const auto* protoAst = static_cast<const NJsonPathGenerated::TJsonPathParserAST*>(rawAst);
  59. TAstBuilder astBuilder(issues);
  60. TAstNodePtr ast = astBuilder.Build(*protoAst);
  61. if (!issues.Empty()) {
  62. return nullptr;
  63. }
  64. // At this point AST is guaranteed to be valid. We return it even if
  65. // type checker finds some logical errors.
  66. TJsonPathTypeChecker checker(issues);
  67. ast->Accept(checker);
  68. return ast;
  69. }
  70. const TJsonPathPtr PackBinaryJsonPath(const TAstNodePtr ast) {
  71. TJsonPathBuilder builder;
  72. ast->Accept(builder);
  73. return builder.ShrinkAndGetResult();
  74. }
  75. const TJsonPathPtr ParseJsonPath(const TStringBuf path, TIssues& issues, size_t maxParseErrors) {
  76. const auto ast = ParseJsonPathAst(path, issues, maxParseErrors);
  77. if (!issues.Empty()) {
  78. return {};
  79. }
  80. return PackBinaryJsonPath(ast);
  81. }
  82. }