我简单的antlr语法有什么问题?

时间:2012-06-25 05:41:10

标签: java antlr

我正在尝试创建一个非常简单的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)

我的语法文件出了什么问题?

感谢, 绿色

1 个答案:

答案 0 :(得分:3)

几句话:

  • Java是默认语言,因此您可以省略language=Java;;
  • 您在解析器规则中使用SPACE,而此SPACE令牌是fragment:这会导致词法分析器永远不会创建此令牌:从解析器规则中删除它(多个);
  • 输入"Report "(“报告”后跟一个空格)被标记为STRING_LITERAL,而不是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; };
  

green写道:

     

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

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

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

report_name
 : NAME+
 ;

导致以下解析树:

enter image description here

输入:

Report (a name with spaces)
Begin
End
  

green写道:

     

是否可以允许我在名称中使用“报告”等保留字?

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

report_name
 : (NAME | REPORT | BEGIN | END)+
 ;