我正在使用Antlr 3.2而我在编写语法时无法忽略注释行 . 具体来说,如果注释行是输入的最后一行,后面没有换行符,我会收到错误 .
我的输入是有效的汇编语言,其中注释从行开头的任何地方用分号开始,然后转到行尾 . 其他所有内容都被解析为命令 .
我的语法的缩减版本展示了这个问题:
grammar Test;
options {
language = Java;
output = AST;
ASTLabelType = CommonTree;
}
@header {
package test;
}
@lexer::header {
package test;
}
rule
: instruction+ EOF!
;
instruction
: 'SET' NEWLINE!*
;
COMMENT
: ';' .* NEWLINE+ { $channel=HIDDEN; }
;
NEWLINE
: '\r'? '\n'
;
WS
: (' ' | '\r' | '\n' | '\t' | '\f')+ { $channel = HIDDEN; }
;
如果我使用如下输入:
; comment line 1 with blank line after it
SET ; comment after command
; comment line again
解析这个说 line 4:11 required (...)+ loop did not match anything at character '<EOF>'
时出错 .
如果我在输入的最后一行添加换行符,它可以正常工作,因为换行符与换行符相匹配,并且规则结束时EOF匹配 .
我怎样才能更好地写这个,所以它忽略了最后一行的注释,但没有给出错误?我不想在原始输入中添加任何内容来破解它,是否有更简洁的方式来阅读注释行?我已经尝试了NEWLINE | EOF的各种组合,但没有任何东西摆脱错误 .
1 回答
这样的事情应该这样做:
如果你想让
COMMENT
在最后有一个换行符,请执行以下操作:但是,两个规则
NEWLINE
和WS
:是危险的:ANTLR的工作方式如下:它尽可能地匹配,因此匹配最多“胜利”的规则 . 如果两个(或更多)规则匹配相同数量的字符,则首先定义的规则为“wins” .
换句话说,如果词法分析器看到像
"\n"
这样的输入,则会创建NEWLINE
. 但是如果词法分析器看到" \n"
(后跟"\n"
的空格),则会创建一个WS
标记(并放在HIDDEN
通道上) .我不确定换行符是否真的对你的语言很重要(它们不是任何汇编语言,AFAIK),所以只需删除
NEWLINE
规则 . 如果有意义,请从WS
规则中删除字符\r
和\n
.