我尝试使用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,我希望lexer退出此规则,忽略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在运行时在词法分析器中获取特定路径?
答案 0 :(得分:2)
使用门控语义谓词而不是验证语义谓词 1 。如果表达式验证为false
,验证谓词将引发异常。让“Nothing alternative”成为最后匹配的。
此外,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"
开头,它就不会一直匹配到行尾。