我正在尝试构建一个简单的配置文件阅读器来读取这种格式的文件:
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堆空间”退出。
(如果我使用顶级规则'file'开始我的测试,那么我得到相同的结果 - 附加(重复)输出“第1行:0不匹配的输入''期待CODE”)
这里出了什么问题?我似乎从来没有得到无效输出的“RecognitionException”?
编辑:这是我的语法文件(Fragment),在这里提供建议之后 - 这避免了'Java堆空间'问题。file
: line+ EOF;
line : ID WS* CODE NEWLINE;
ID : ('A'..'Z')('A'..'Z')*
;
CODE : ('-'|'.')('-'|'.')*;
答案 0 :(得分:0)
您的某些词法规则匹配零个字符(空字符串):
ID : ('A'..'Z')*
;
CODE : ('-'|'.')*;
当然,输入中有无限量的空字符串,导致词法分析器继续生成标记,一段时间后会导致堆空间错误。
始终让词法分析器规则至少匹配1个字符。
两个(小)评论:
WS
令牌放在隐藏的频道上,因此您无需在解析器规则中添加它们。因此line
变为line : ID CODE NEWLINE;
('A'..'Z')('A'..'Z')*
之类的内容可以这样写:('A'..'Z')+