简单的ANTLR语法有什么问题?

时间:2012-10-29 16:40:40

标签: antlr

我正在编写一个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();} ;   

1 个答案:

答案 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"构造标记时,它会成功创建标记T1FLOAT,但是当它看到 { {1}},它尝试构造": ["令牌。但是当流中的下一个字符是T4而不是"x"时,词法分析器会尝试构造另一个以"y"开头的标记。但由于没有这样的标记,词法分析器会发出错误:

  

[...]不匹配的字符'x'期待'y'

不,lexer不会回溯“放弃”来自": ["的角色"["以匹配令牌": [",也不会在char-stream中向前看看看是否真的可以构造T2令牌。 ANTLR的LL(*)仅适用于解析器规则,而不适用于词法分析器规则!