Antlr4 - 无法获得岛文法吗?

时间:2016-07-26 17:30:13

标签: java parsing antlr antlr4

问题

我使用Antrl4来解析类似Java的语言,其中可以使用专有查询语言在括号内编写表达式。想象一下,在Java方法中,应该允许以下行:

List<MyObject> items = [SELECT Field1,Field2 FROM MyObject];

任何表达式中也应允许使用查询语言,例如

if ([SELECT Field1,Field2 FROM MyObject]!=null) {  }

也应该被允许。我的解析器需要使用两种模式的元素定义规则(当处于类似Java的模式时,处于查询语言模式时)。

我使用岛语法的方法

我正试图将其作为一个孤岛语法来处理,正如最终Antlr4参考文献所描述的那样,但是我无法让它发挥作用。

我正在构建我的词法分析器语法如下

OPEN_QUERY : '['    -> pushMode(INSIDE_QUERY);

JavaIdentifier: JavaLetter JavaLetterOrDigit* ;
// omitting fragments and loads of other lexer tokens for brevity

mode INSIDE_QUERY;

CLOSE_QUERY : ']' -> popMode ;
SELECT : 'select';
FROM : 'from';
QueryIdentifier: QueryLetter QueryLetterOrDigit*;
// omitting fragments definition for brevity

在我的解析器解析器语法中,我试图做这样的事情:

expression: normalExpression | queryExpression;

queryExpression
: '[' SELECT QueryIdentifier FROM  QueryIdentifier']'
;    

但是这会在第一个括号字符上产生令牌识别错误。

这种方法有什么问题吗?谁能指出我正在制造的错误?

1 个答案:

答案 0 :(得分:1)

如果您转储令牌流以查看词法分析器实际执行的操作,则此类问题更容易诊断。在这里,开放括号在词法分析器中被识别为OPEN_QUERY并且关闭为CLOSE_QUERY。因此,作为隐式标记的文字括号即。在解析器中指定为“['和']',不会出现在标记流中。

通过更改为

进行简单修复
queryExpression
    : OPEN_QUERY SELECT QueryIdentifier FROM QueryIdentifier CLOSE_QUERY
    ;