我正在尝试为重新解析和重新标记的 kconfig 文件(重新标记以解决一些歧义)编写 ANTLR 语法。语法的简化版本是:
grammar FailureExample;
options {
language = Java;
}
@lexer::header {
package parse.failure.example;
}
reload
: configStatement*
EOF
;
configStatement
: CONFIG IDENT
configOptions
;
configOptions
: (type
| defConfigStatement
| dependsOnStatement
| helpStatement
| rangeStatement
| defaultStatement
| selectStatement
| visibleIfStatement
| prompt
)*
;
type : FAKE1;
dependsOnStatement: FAKE2;
helpStatement: FAKE3;
rangeStatement: FAKE4;
defaultStatement: FAKE5;
selectStatement:FAKE6;
visibleIfStatement:FAKE7;
prompt:FAKE8;
defConfigStatement
: defConfigType expression
;
defConfigType
: DEF_BOOL
;
//expression parsing
primative
: IDENT
| L_PAREN expression R_PAREN
;
negationExpression
: NOT* primative
;
orExpression
: negationExpression (OR negationExpression)*
;
andExpression
: orExpression (AND orExpression)*
;
unequalExpression
: andExpression (NOT_EQUAL andExpression)?
;
equalExpression
: unequalExpression (EQUAL unequalExpression)?
;
expression
: equalExpression (BECOMES equalExpression)?
;
DEF_BOOL: 'def_bool';
CONFIG : 'config';
COMMENT : '#' .* ('\n'|'\r') {$channel = HIDDEN;};
AND : '&&';
OR : '||';
NOT : '!';
L_PAREN : '(';
R_PAREN : ')';
BECOMES : '::=';
EQUAL : '=';
NOT_EQUAL : '!=';
FAKE1 : 'fake1';
FAKE2: 'fake2';
FAKE3: 'fake3';
FAKE4: 'fake4';
FAKE5: 'fake5';
FAKE6: 'fake6';
FAKE7: 'fake7';
FAKE8: 'fake8';
IDENT : (LETTER | DIGIT | '_')*;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
fragment LETTER : ('a'..'z' | 'A'..'Z') ;
fragment DIGIT : '0'..'9';
有输入:
config HAVE_DEBUG_RAM_SETUP
def_bool n
我可以将 antlrworks 设置为仅解析第二行(注释掉第一行),然后我得到正确的 defConfigStatement 令牌,并带有下面的正确表达式。但是,如果我使用 configOptions 规则或 configStatement 规则(第一行未注释),我的 configOptions 会导致一个空集并引发 NoViableAlt 异常。
什么会导致这种行为?我知道 defConfigStatement 规则是准确的并且可以正确解析,但是一旦将它作为潜在选项添加到另一个规则中,它就会失败。我知道我没有冲突的规则,并且我已将 DEF_BOOL 和 DEF_TRISTATE 规则放在我的词法分析器规则列表中,因此它们优先于其他词法分析器规则。
/自编辑后添加/ 为了使问题进一步复杂化,如果我在 configOptions 规则中移动 defConfigStatement 选项,它将起作用,但其他规则将失败。
编辑:使用完整的简化语法。
简而言之,为什么该规则自己起作用,但在 configOptions 中却失败了(尤其是因为 configOptions 是 (A | B | C)* 形式)?