我在Antlr3中有以下(简化的)问题。我有一套特殊字符串和常规字符串语法的lexer规则。两者均为单引号。特殊字符串符合一种模式(例如,假设它们只包含字母)。还有一个函数可以确定匹配的字符串是否特殊。空白被忽略。
现在假设isSpecial只对字符串"foo"返回true。如果我看到的是"'fo'bar''123'",lexer应该为foo生成1个特殊字符串标记,然后生成2个常规字符串标记。
我正在尝试做这样的事情:
SpecialLiteral : { isSpecial(getText()) }?=> ''' (Letter)+ ''' ;
StringLiteral : ''' ( ~('') )* ''' ;
这不起作用,因为getText()还没有填充在门控谓词中,所以空字符串被传递给isSpecial,"'o'"变成StringLiteral。
如果我将门控谓词更改为验证谓词,我在isSpecial中有正确的getText,但当它返回false时(例如,对于"'bar'"),lexer不会回溯并使"'bar''"成为StringLiteral,它只是失败了。
有可能解决这个问题吗?如果我只是手动编辑lexer,它似乎是可行的。我们知道mSpecialLiteral之前的位置,所以我们可以回到那里,然后像选通谓词之后那样操作。如何使用语法/传递给isSpecial的内容?
您可以在同一规则中匹配两者,然后在文字匹配了哪种类型后进行检查,并在isSpecial(getText())
为true时将类型更改为SpecialLiteral
:
grammar T;
...
tokens {
SpecialLiteral;
}
...
StringLiteral
: ''' ( ~( ''' ) )* '''
{
if(isSpecial(getText())) {
$type = SpecialLiteral;
}
}
;