proto_ast_antlr3.h 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #pragma once
  2. #include <yql/essentials/parser/proto_ast/common.h>
  3. #include <contrib/libs/antlr3_cpp_runtime/include/antlr3.hpp>
  4. namespace NProtoAST {
  5. template <typename TParser, typename TLexer>
  6. class TProtoASTBuilder3 {
  7. typedef ANTLR_UINT8 TChar;
  8. public:
  9. TProtoASTBuilder3(TStringBuf data, const TString& queryName = "query", google::protobuf::Arena* arena = nullptr)
  10. : QueryName(queryName)
  11. , InputStream((const TChar*)data.data(), antlr3::ENC_8BIT, data.length(), (TChar*)QueryName.begin()) // Why the hell antlr needs non-const ptr??
  12. , Lexer(&InputStream, static_cast<google::protobuf::Arena*>(nullptr))
  13. , TokenStream(ANTLR_SIZE_HINT, Lexer.get_tokSource())
  14. , Parser(&TokenStream, arena)
  15. {
  16. }
  17. google::protobuf::Message* BuildAST(IErrorCollector& errors) {
  18. // TODO: find a better way to break on lexer errors
  19. try {
  20. Lexer.ReportErrors(&errors);
  21. return Parser.Parse(Lexer, &errors);
  22. } catch (const TTooManyErrors&) {
  23. return nullptr;
  24. } catch (...) {
  25. errors.Error(0, 0, CurrentExceptionMessage());
  26. return nullptr;
  27. }
  28. }
  29. private:
  30. TString QueryName;
  31. typename TLexer::InputStreamType InputStream;
  32. TLexer Lexer;
  33. typename TParser::TokenStreamType TokenStream;
  34. TParser Parser;
  35. };
  36. template <typename TLexer>
  37. class TLexerTokensCollector3 {
  38. typedef ANTLR_UINT8 TChar;
  39. public:
  40. TLexerTokensCollector3(TStringBuf data, const char** tokenNames, const TString& queryName = "query")
  41. : TokenNames(tokenNames)
  42. , QueryName(queryName)
  43. , InputStream((const TChar*)data.data(), antlr3::ENC_8BIT, data.length(), (TChar*)QueryName.begin())
  44. , Lexer(&InputStream, static_cast<google::protobuf::Arena*>(nullptr))
  45. {
  46. }
  47. void CollectTokens(IErrorCollector& errors, const NSQLTranslation::ILexer::TTokenCallback& onNextToken) {
  48. try {
  49. Lexer.ReportErrors(&errors);
  50. auto src = Lexer.get_tokSource();
  51. for (;;) {
  52. auto token = src->nextToken();
  53. auto type = token->getType();
  54. const bool isEOF = type == TLexer::CommonTokenType::TOKEN_EOF;
  55. NSQLTranslation::TParsedToken last;
  56. last.Name = isEOF ? "EOF" : TokenNames[type];
  57. last.Content = token->getText();
  58. last.Line = token->get_line();
  59. last.LinePos = token->get_charPositionInLine();
  60. onNextToken(std::move(last));
  61. if (isEOF) {
  62. break;
  63. }
  64. }
  65. } catch (const TTooManyErrors&) {
  66. } catch (...) {
  67. errors.Error(0, 0, CurrentExceptionMessage());
  68. }
  69. }
  70. private:
  71. const char** TokenNames;
  72. TString QueryName;
  73. typename TLexer::InputStreamType InputStream;
  74. TLexer Lexer;
  75. };
  76. } // namespace NProtoAST