Parsing ANTLR4-解析语言的子集(例如,仅查询语句)

Parsing ANTLR4-解析语言的子集(例如,仅查询语句),parsing,antlr,antlr4,u-sql,Parsing,Antlr,Antlr4,U Sql,我试图找出如何用ANTLR最好地解析给定语言的子集。例如,假设我正在寻找解析。实际上,我只对解析语言的某些部分感兴趣,例如。我对解析该语言的许多其他特性不感兴趣。我目前的方法是设计我的lexer/parser语法,如下所示: // ... statement : queryStatement | undefinedStatement ; // ... undefinedStatement : (.)+? ; // ... Und

我试图找出如何用ANTLR最好地解析给定语言的子集。例如,假设我正在寻找解析。实际上,我只对解析语言的某些部分感兴趣,例如。我对解析该语言的许多其他特性不感兴趣。我目前的方法是设计我的lexer/parser语法,如下所示:

// ...

statement
    :    queryStatement
    |    undefinedStatement
    ;

// ...

undefinedStatement
    :    (.)+?
    ;

// ...

UndefinedToken
    :    (.)+?
    ;
要点是,我为未定义的结构和标记添加了一个回退解析器规则和lexer规则。我想象稍后,当我走到解析树时,我可以忽略树中未定义的语句,而专注于我感兴趣的语句

这似乎是可行的,但这是最佳策略吗?还有更优雅的选择吗?提前谢谢

这一总体思路——解析输入中有趣的部分而忽略周围大量的标记——通常称为“孤岛解析”。ANTLR参考书中有一个孤岛解析器的例子,尽管我不知道它是否直接适用

岛屿解析的棘手部分是正确地确定岛屿边界。如果您错过了一个边界,或者识别出了一个不存在的边界,那么您的解析将失败。因此,您至少需要充分理解输入,以便能够检测出孤岛的位置。例如,在您的示例中,这可能意味着识别
SELECT
语句。但是,您不能盲目地识别字母字符串
SELECT
,因为该字符串可能出现在字符串常量、注释或其他上下文中,而在这些上下文中,它根本不打算被识别为标记


我猜想,如果要解析查询,基本上需要能够识别任何令牌。因此,不会有大量未经检查的输入字符。您可以将其视为一个已识别但未解析的代币的海洋。在这种情况下,将非查询语句解析为关键字后跟任意标记(而不是
)应该是相当安全的并以
结尾。(但您可能需要识别嵌套块;我真的不知道有什么可能。)

解析语法的子部分非常简单。通常,您有一个顶级规则,您可以调用它来解析整个语法的完整输入

对于子部分,使用只解析子规则的函数,如:

const expression = parser.statement();
当我只想解析存储过程或数据类型时,我经常使用这种方法

但是,请记住,子规则通常不是以EOF标记终止的(顶级规则应该是这样的)。如果令牌流中的子元素多于子元素,则不会导致语法错误(当子规则完全匹配时,解析器将停止)。如果这对您来说是一个问题,那么添加您想要解析的子规则的副本,给它一个专用的名称,并以EOF结束,如下所示:

dataTypeDefinition: // For external use only. Don't reference this in the normal grammar.
    dataType EOF
;

dataType: // type in sql_yacc.yy
    type = (
...
有关更多详细信息,请查看