如何基于ANTLR3(或4)中的谓词使lexer回溯?

如何基于ANTLR3(或4)中的谓词使lexer回溯?,antlr,antlr3,antlr4,Antlr,Antlr3,Antlr4,我在Antlr3中有以下(简化的)问题。 对于带有特殊字符串和常规字符串的语法,我有一套lexer规则。两者都是单引号。特殊字符串符合模式(例如,假设它们只包含字母)。还有一个函数可以确定匹配的字符串是否特殊。空白被忽略 现在假设isSpecial仅为字符串“foo”返回true。如果我查看“'foo'”栏“123'”,lexer应该为foo生成1个特殊字符串标记,然后生成2个常规字符串标记 我正在尝试这样做: SpecialLiteral : { isSpecial(getText()) }?

我在Antlr3中有以下(简化的)问题。 对于带有特殊字符串和常规字符串的语法,我有一套lexer规则。两者都是单引号。特殊字符串符合模式(例如,假设它们只包含字母)。还有一个函数可以确定匹配的字符串是否特殊。空白被忽略

现在假设isSpecial仅为字符串“foo”返回true。如果我查看“'foo'”栏“123'”,lexer应该为foo生成1个特殊字符串标记,然后生成2个常规字符串标记

我正在尝试这样做:

SpecialLiteral : { isSpecial(getText()) }?=> '\'' (Letter)+ '\'' ;
StringLiteral : '\'' ( ~('\') )* '\'' ;
这不起作用,因为getText()尚未填充在选通谓词中,所以空字符串被传递给isSpecial,而“'foo'”变为StringLiteral

如果我将选通谓词更改为验证谓词,则在isSpecial中有正确的getText,但当它返回false(例如,对于“'bar')时,lexer不会回溯并使“'bar'”成为StringLiteral,它只是失败

有可能解决这个问题吗?如果我只是手动编辑lexer,它看起来应该是可行的。我们知道MSSpecialLiteral之前的位置,所以我们可以回到那里,然后像选通谓词之后那样行事。
如何使用语法/要传递给isSpecial的内容进行匹配?

您可以在同一规则中匹配这两种内容,然后在文本匹配了它是哪种类型后进行检查,并在
isSpecial(getText())
为true时将类型更改为
SpecialLiteral

grammar T;

...

tokens {
  SpecialLiteral;
}

...

StringLiteral
 : '\'' ( ~( '\'' ) )* '\''
   {
     if(isSpecial(getText())) {
       $type = SpecialLiteral;
     }
   }
 ;