Antlr 错误的AST选择

Antlr 错误的AST选择,antlr,antlr3,Antlr,Antlr3,给定以下ANTLR v3语法: tokens { OPTION; UNKNOWN; } statement : my_statement | UNKNOWN_KEYWORD -> ^(UNKNOWN) ; my_statement : FIRST SECOND type = THIRD? -> ^(OPTION $type?); FIRST : 'my'; SECOND : 'keyword'; THIRD: 'best

给定以下ANTLR v3语法:

tokens
{
   OPTION;
   UNKNOWN;
}

statement : my_statement
          | UNKNOWN_KEYWORD -> ^(UNKNOWN)
          ;

my_statement : FIRST SECOND type = THIRD? -> ^(OPTION $type?);


FIRST : 'my';

SECOND : 'keyword';

THIRD: 'best';

UNKNOWN_KEYWORD : .;

为什么在解析字符串“my keyword this_is_garbage”时,它由my_语句提取,而它本应由UNKNOWN_关键字提取(即返回的AST为^(选项$type?),而它本应为^(未知))?

输入
我的关键字this_is_garbage
将标记如下(假设空间是隐藏的):

即,一个
第一个
令牌,一个
第二个
令牌,然后是15个
未知关键字
令牌

如果您现在尝试匹配
语句
,则规则
my_语句
将乐意使用
第一个
第二个
令牌,将15个
未知关键字
令牌留在令牌流中

但是,如果您重复匹配您的
语句
规则,如下所示:

parse
 : statement+ EOF
 ;
然后,您将得到以下解析树:

或者这个AST:

如果您想将所有
UNKNOWN_关键字
token分组到一个备选方案中,您需要执行以下操作:

statement : my_statement
          | UNKNOWN_KEYWORD+ -> ^(UNKNOWN)
          ;
请注意,不能在lexer中对
未知\u关键字进行分组

UNKNOWN_KEYWORD : .+ ;

因为这将导致lexer将整个字符流吞噬为一个单独的
未知\u关键字
标记。

输入的
我的关键字this\u is\u垃圾
将按如下方式标记(假设空格隐藏):

即,一个
第一个
令牌,一个
第二个
令牌,然后是15个
未知关键字
令牌

如果您现在尝试匹配
语句
,则规则
my_语句
将乐意使用
第一个
第二个
令牌,将15个
未知关键字
令牌留在令牌流中

但是,如果您重复匹配您的
语句
规则,如下所示:

parse
 : statement+ EOF
 ;
然后,您将得到以下解析树:

或者这个AST:

如果您想将所有
UNKNOWN_关键字
token分组到一个备选方案中,您需要执行以下操作:

statement : my_statement
          | UNKNOWN_KEYWORD+ -> ^(UNKNOWN)
          ;
请注意,不能在lexer中对
未知\u关键字进行分组

UNKNOWN_KEYWORD : .+ ;

因为这将导致lexer将整个字符流吞并为一个单独的
未知\u关键字
标记。

第三个
在解析器规则中是可选的,因此该规则匹配
我的关键字
很好,甚至没有前进到
这\u是\u垃圾
。是的,它不会匹配我的\u关键字,但不会重新搜索rn AST^(未知),这是我们所期望的。如何修复语法,使其返回此AST?您看到的行为正是我从该语法中所期望的:)好吧,假设
UNKNOWN\u关键字
是在某个地方定义的(
UNKNOWN
是单个字符)
my_语句
匹配,因此
语句
的第二个分支甚至没有尝试。
第三个
在解析器规则中是可选的,因此该规则匹配了
my关键字
很好,甚至没有前进到
this_is_garbage
。是的,它不会匹配my_关键字,但不会返回AST^(未知),这正是我们所期望的。语法如何被修正以返回此AST?您看到的行为正是我从该语法中所期望的:)好吧,假设
UNKNOWN\u关键字
是在某个地方定义的(
UNKNOWN
是单个字符)
my_语句
匹配,因此,
语句
的第二个分支甚至没有尝试过。您还应该在这里添加未知的_关键字应该是一个。*循环,而不仅仅是一个字符,以匹配预期的行为。是的,但您可能指的是
+
。是的,加号是正确的。但您对该循环的添加不是:-)UNKNOWN_关键字只会在之前没有其他规则匹配的情况下吃掉所有内容。在语法的末尾有一个全包规则是完全可以的。@MikeLischke,不,我说过你不能有一个只有
+
的lexer规则,我不是说你不能有一个lexer规则,它使用(一个)
匹配一个字符。你还应该在这里添加未知的\u关键字应该是一个。*循环,而不仅仅是一个字符,匹配预期行为。是的,但你可能是指
+
。没错,加号是正确的。但您对该循环的添加不是:-)UNKNOWN_关键字只会在之前没有其他规则匹配的情况下吃掉所有内容。在语法的末尾有一个通配符规则是完全可以的。@MikeLischke,不,我说你不能有一个只有
+
的词法规则,我不是说你不能有一个使用(单个)
匹配单个字符的词法规则