我正在尝试使用 ANTLR 编写上下文相关的词法分析器规则,但无法让它执行我需要的操作。该规则需要根据规则开头找到的字符匹配 2 个备选方案中的 1 个。下面是问题的极大简化版本。
此示例语法:
lexer grammar X;
options
{
language = C;
}
RULE :
SimpleIdent {ctx->someFunction($SimpleIdent);}
(
{ctx->test != true}?
//Nothing
| {ctx->test == true}?
SLSpace+ OtherText
)
;
fragment SimpleIdent : ('a'..'z' | 'A'..'Z' | '_')+;
fragment SLSpace : ' ';
fragment OtherText : (~'\n')* '\n';
如果 ctx->test 为 false,我希望词法分析器退出此规则,忽略 SimpleIdent 之后的任何字符。不幸的是,ANTLR 将在测试谓词之前测试 SimpleIdent 之后的字符,因此如果那里有空格,将始终采用第二种选择。这在 C 代码中清楚地显示出来:
// X.g:10:3: ({...}?|{...}? ( SLSpace )+ OtherText )
{
int alt2=2;
switch ( LA(1) )
{
case '\t':
case ' ':
{
alt2=2;
}
break;
default:
alt2=1;
}
switch (alt2)
{
case 1:
// X.g:11:5: {...}?
{
if ( !((ctx->test != true)) )
{
//Exception
}
}
break;
case 2:
// X.g:13:5: {...}? ( SLSpace )+ OtherText
{
if ( !((ctx->test == true)) )
{
//Exception
}
如何强制 ANTLR 在运行时在词法分析器中采用特定路径?
最佳答案
使用门控语义谓词而不是验证语义谓词1。如果表达式验证为 false
,验证谓词将引发异常。并让“没有替代方案”成为最后一个匹配的内容。
此外,OtherText
也与 SLSpace
匹配,使得 SLSpace+ OtherText
不明确。只需从中删除 SLSpace+
,或者让 OtherText
以 ' '
以外的内容开头即可。
我对 C 目标不太熟悉,但这个 Java 演示应该可以很好地用于 C(当然,在翻译 Java 代码之后):
grammar T;
rules
: RULE+ EOF
;
RULE
: SimpleIdent {boolean flag = $SimpleIdent.text.startsWith("a");}
( {!flag}?=> OtherText
| // Nothing
)
;
Spaces
: (' ' | '\t' | '\r' | '\n')+ {skip();}
;
fragment SimpleIdent : ('a'..'z' | 'A'..'Z' | '_')+;
fragment OtherText : (~'\n')* '\n';
如果您现在解析输入:
abcd efgh ijkl mnop bbb aaa ccc ddd
您将得到以下解析:
即每当RULE
以小写“a”
开头时,它不会一直匹配到行尾。
关于antlr - 在 ANTLR 词法分析器规则中强制采用替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11838662/