Antlr解析器未发生

问题描述

如果我有一个测试语法TestGrammar.g4,

grammar TestGrammar;

startRule : compilationunit EOF;

compilationunit
   : programunit*
   ;

programunit
  : execsqlStatement
  ;

execsqlStatement
  : EXEC sql EXECsqlLINE+ END_EXEC DOT?
  ;

freeText
   //: ~NL*
   : STRING+
   ;

EXECsqlLINE : EXECsqlTAG WS ~('\n' | '\r' | '}')* ('\n' | '\r' | '}');

EXECsqlTAG : '*>EXECsql';

END_EXEC : E N D '-' E X E C;
EXEC : E X E C;
sql : S Q L;

// symbols
STRING  : .+?;
NL      : '\r'? '\n' | '\r';
//NEWLINE : '\r'? '\n' -> channel(HIDDEN);
DOT : '.';
WS : [ \t\f;]+ -> channel(HIDDEN);

在其中输入简单文本,

  const input = `
  EXEC sql
    somethig goes here
  END-EXEC.
`

如果我运行这些数据,我已经获得了Abstract语法树(AST),并且它似乎没有被完全解析,

programunit
          (
            execsqlStatement EXEC   sql   \n s o m e t h i g   g o e s   h e r e \n s o m e t h i g   g o e s   h e r e \n END-EXEC
          )

预期输出

 (
  startRule
  (
    compilationunit
    (
      programunit
      (
         execsqlStatement EXEC sql
  (
    freeText
    (
      something goes here
    )
  )
  (
    END EXEC
  )
      )
    )
  )
)

因为它必须解析execsqlStatement内部的内容,但我无法检索。 预先感谢

解决方法

这里有几件事:

  1. ANTLR4不会产生语法树(AST),但会解析树。 AST由以(或多或少)树状方式匹配的输入符号组成。解析树由解析上下文节点组成,这些上下文节点描述了语法中匹配的路径。它们还包含匹配的符号,因此它们是AST的超集。
  2. 您的语法不完整,例如它错过了规则SQEX等的定义。问题中的示例应该是自包含的,并且可以在不进行额外调整的情况下进行变换。
  3. 您永远不会使用规则freeText。那么它如何对输出做出贡献?
  4. 您已将整个SQL代码编码为单个词法分析器规则EXECSQLLINE。当然,这将在输出中显示为单个词法分析器令牌。如果那是您的意图,那么可以,但是通常人们希望掌握查询的各个部分。