我正在编写一个ANTLR语法来解析日志文件,并遇到了问题。 我已经简化了我的语法来重现问题,如下所示:
stmt1:
'[ ' elapse ': ' stmt2
;
stmt2:
'[xxx'
;
stmt3:
': [yyy'
;
elapse :
FLOAT;
FLOAT
: ('0'..'9')+ '.' ('0'..'9')*
;
当我使用以下字符串来测试语法时:
[ 98.9: [xxx
我收到了错误:
E:\work\antlr\output\__Test___input.txt line 1:9 mismatched character 'x' expecting 'y'
E:\work\antlr\output\__Test___input.txt line 1:10 no viable alternative at character 'x'
E:\work\antlr\output\__Test___input.txt line 1:11 no viable alternative at character 'x'
E:\work\antlr\output\__Test___input.txt line 1:12 mismatched input '<EOF>' expecting ': '
但如果我删除了标尺'stmt3',则会接受相同的字符串。
我不确定发生了什么......
感谢您的任何建议!
莱昂
感谢Bart的帮助。我试图纠正语法。 我认为,基线,我必须消除所有令牌的歧义。 我添加WS令牌以简化规则。
stmt1:
'[' elapse ':' stmt2
;
stmt2:
'[' 'xxx'
;
stmt3:
':' '[' 'yyy'
;
elapse :
FLOAT;
FLOAT
: ('0'..'9')+ '.' ('0'..'9')*
;
WS : (' ' |'\t' |'\n' |'\r' )+ {skip();} ;
答案 0 :(得分:4)
ANTLR严格区分词法规则(令牌)和解析器规则。虽然您在解析器规则中定义了一些文字,但它们仍然是令牌。这意味着以下语法与您的示例语法相同(在实践中):
stmt1 : T1 elapse T2 stmt2 ;
stmt2 : T3 ;
stmt3 : T4 ;
elapse : FLOAT;
T1 : '[ ' ;
T2 : ': ' ;
T3 : '[xxx' ;
T4 : ': [yyy' ;
FLOAT : ('0'..'9')+ '.' ('0'..'9')* ;
现在,当词法分析器尝试从输入"[ 98.9: [xxx"
构造标记时,它会成功创建标记T1
和FLOAT
,但是当它看到 { {1}},它尝试构造": ["
令牌。但是当流中的下一个字符是T4
而不是"x"
时,词法分析器会尝试构造另一个以"y"
开头的标记。但由于没有这样的标记,词法分析器会发出错误:
[...]不匹配的字符'x'期待'y'
不,lexer不会回溯“放弃”来自": ["
的角色"["
以匹配令牌": ["
,也不会在char-stream中向前看看看是否真的可以构造T2
令牌。 ANTLR的LL(*)仅适用于解析器规则,而不适用于词法分析器规则!