1

我正在尝试创建一个非常简单的 antlr 语法文件,它应该解析以下文件:

Report (MyReport)
Begin
End

或没有报告名称:

Report
Begin
End

这是我的语法文件:

grammar RL;

options {
  language = Java;
}

report:
  REPORT ('(' SPACE* STRING_LITERAL SPACE* ')')?
  BEGIN
  END
  ;

REPORT
    :   'Report'
    ;     

BEGIN
    :   'Begin'
    ;

END :   'End';

NAME:   LETTER (LETTER | DIGIT | '_')*;

STRING_LITERAL :    NAME SPACE*;

fragment LETTER: LOWER | UPPER;

fragment LOWER: 'a'..'z';

fragment UPPER: 'A'..'Z';

fragment DIGIT: '0'..'9';

fragment SPACE: ' ' | '\t';

WHITESPACE: SPACE+ { $channel = HIDDEN; };

rule: ;

但是,当我在 ANTLRWorks 中调试时,我总是会收到以下错误:

 root -> report -> MismatchedTokenException(0!=0)

我的语法文件有什么问题?

谢谢,绿

4

1 回答 1

3

几点说明:

  • Java是默认语言,所以可以省略language=Java;
  • 您在SPACE解析器规则中使用,而此SPACE标记是fragment: 这会导致词法分析器永远不会创建此标记:将其从解析器规则中删除;
  • 输入"Report "(“报告”后跟一个空格)被标记为 a STRING_LITERAL,而不是 a REPORT!ANTLR 的词法分析器贪婪地消耗字符,只有当两个或多个规则匹配相同数量的字符时,首先定义的规则才会获得优先权。词法分析器不会产生解析器试图匹配的标记(解析和标记化是独立执行的!)。

请尝试以下操作:

grammar RL;

report
 : REPORT ('(' NAME ')')? BEGIN END
 ;

REPORT : 'Report';     
BEGIN  : 'Begin';
END    : 'End';
NAME   : LETTER (LETTER | DIGIT | '_')*;

fragment LETTER : LOWER | UPPER;
fragment LOWER  : 'a'..'z';
fragment UPPER  : 'A'..'Z';
fragment DIGIT  : '0'..'9';

SPACE  : (' ' | '\t' | '\r' | '\n')+ { $channel = HIDDEN; };

绿色写道:

如果我想在报告名称中允许“SPACE”怎么办?

我仍然会跳过词法分析器中的空格。接受名称之间的空格但在其他上下文中忽略它们会导致一些笨拙的规则。而不是考虑报告名称之间的空格,我会做这样的事情:

report
 : REPORT ('(' report_name ')')? BEGIN END
 ;

report_name
 : NAME+
 ;

产生以下解析树:

在此处输入图像描述

对于输入:

报告(带空格的名称)
开始
结尾

绿色写道:

那么是否可以允许我在名称中使用保留字,例如“报告”?

当然,在report_name规则中明确添加它们:

report_name
 : (NAME | REPORT | BEGIN | END)+
 ;
于 2012-06-25T15:33:11.973 回答