1

我正在尝试构建一个简单的配置文件阅读器来读取这种格式的文件:

A .-
B -...
C -.-.
D -..
E .

这是我到目前为止的语法:

grammar def;

@header {
    package mypackage.parser;
}
@lexer::header { package mypackage.parser; }
file
    :   line+;

line    :   ID WS* CODE NEWLINE;

ID  :   ('A'..'Z')*
    ;

CODE    :   ('-'|'.')*;

COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

WS  :   ( ' '
        | '\t'
        ) {$channel=HIDDEN;}
    ;
NEWLINE:'\r'? '\n' ;

这是我的测试台(junit4)

@Test
public void BasicGrammarCheckGood() {
       String CorrectlyFormedLine="A .-;\n";
       ANTLRStringStream input;
        defLexer lexer;
        defParser parser;

         input = new ANTLRStringStream(CorrectlyFormedLine);
        lexer = new defLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
         parser = new defParser(tokens);
         try {
        parser.line();
         }
         catch(RecognitionException re) { fail(re.getMessage()); } 
   }

如果我使用正确的格式化字符串运行此测试 - 代码将退出而没有任何异常或输出。

但是,如果向解析器提供这样的无效字符串:“xA .-;\n”,代码会旋转一段时间,然后以“Java 堆空间”退出。

(如果我使用顶级规则“文件”开始测试,那么我会得到相同的结果 - 附加(重复)输出“第 1 行不匹配的输入 '' 期待 CODE”)

这里出了什么问题?我似乎从来没有得到无效输出的“RecognitionException”?

编辑:这是我的语法文件(片段),在这里提供建议后 - 这避免了“Java堆空间”问题。

file
    :   line+ EOF;

line    :   ID WS* CODE NEWLINE;

ID  :   ('A'..'Z')('A'..'Z')*
    ;

CODE    :   ('-'|'.')('-'|'.')*;
4

1 回答 1

0

您的某些词法分析器规则匹配零个字符(空字符串):

ID  :   ('A'..'Z')*
    ;

CODE    :   ('-'|'.')*;

当然,您的输入中有无限数量的空字符串,导致您的词法分析器不断产生标记,一段时间后导致堆空间错误。

始终让词法分析器规则匹配至少 1 个字符。

编辑

两个(小)备注:

  1. 由于您将WS令牌放在隐藏通道上,因此您无需将它们添加到解析器规则中。所以line变成line : ID CODE NEWLINE;
  2. 类似的东西('A'..'Z')('A'..'Z')*可以这样写:('A'..'Z')+
于 2013-01-28T22:35:41.230 回答