如何根据Antlr 3(或4)中的谓词制作词法分析器回溯?

时间:2013-12-11 01:36:59

标签: antlr antlr3 antlr4

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

现在假设例如isSpecial仅对字符串“foo”返回true。如果我正在查看“'foo''bar''123'”,那么词法分析器应为foo生成1个特殊字符串标记,然后生成2个常规字符串标记。

我正在尝试做这样的事情:

SpecialLiteral : { isSpecial(getText()) }?=> '\'' (Letter)+ '\'' ;
StringLiteral : '\'' ( ~('\') )* '\'' ;

这不起作用,因为getText()尚未在门控谓词中填充,因此空字符串传递给isSpecial,“'foo'”变为StringLiteral。

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

有可能解决这个问题吗?如果我只是手动编辑词法分析器,它似乎应该是可行的。我们知道mSpecialLiteral之前的位置,所以我们可以回到那里然后像门控谓词一样行动。 如何使用语法/传递给isSpecial?

1 个答案:

答案 0 :(得分:0)

您可以在同一规则中匹配两者,然后在文字匹配的类型后进行检查,并在SpecialLiteral为真时将类型更改为isSpecial(getText())

grammar T;

...

tokens {
  SpecialLiteral;
}

...

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