虽然我对有关 Antlr 语法的大量问题感到有些欣慰(不仅仅是我试图剃掉这个牦牛形状的东西),但我还没有找到一个可以帮助解决我的问题的问题/答案。
我将 Antlr3.3 与混合令牌/解析器词法分析器一起使用。
我正在使用 gUnit 来帮助证明语法和一些 jUnit 测试;这就是乐趣的开始。
我有一个要解析的简单配置文件:
identifier foobar {
port=8080
stub plusone.google.com {
status-code = 206
header = []
body = []
}
}
我在解析“标识符”(本例中为 foobar)时遇到问题: 我想允许的有效名称是:
foobar
foo-bar
foo_bar
foobar2
foo-bar2
foo_bar2
3foobar
_foo-bar3
依此类推,因此有效的名称可以使用字符'a..z'|'A..Z', '0..9' '_' and '-'
我得出的语法是这样的(注意这不是完整的语法,只是与这个问题相关的部分):
fragment HYPHEN : '-' ;
fragment UNDERSCORE : '_' ;
fragment DIGIT : '0'..'9' ;
fragment LETTER : 'a'..'z' |'A'..'Z' ;
fragment NUMBER : DIGIT+ ;
fragment WORD : LETTER+ ;
IDENTIFIER : DIGIT | LETTER (LETTER | DIGIT | HYPHEN | UNDERSCORE)*;
和相应的 gUnit 测试
IDENTIFIER:
"foobar" OK
"foo_bar" OK
"foo-bar" OK
"foobar1" OK
"foobar12" OK
"foo-bar2" OK
"foo_bar2" OK
"foo-bar-2" OK
"foo-bar_2" OK
"5foobar" OK
"f_2-a" OK
"aA0_" OK
// no "funny chars"
"foo@bar" FAIL
// not with whitepsace
"foo bar" FAIL
运行 gUnit 测试仅对“5foobar”失败。我已经设法解析了困难的东西,但解析标识符这一看似简单的任务却打败了我。
谁能指出我哪里出错了?我怎样才能匹配而不贪心?
提前谢谢了。
- 更新 -
我根据 Barts 的回答将语法更改为:
IDENTIFIER : ('0'..'9'| 'a'..'z'|'A'..'Z' | '_'|'-') ('_'|'-'|'a'..'z'|'A'..'Z'|'0'..'9')* ;
这修复了失败的 gUnit 测试,但破坏了一个无关的 jUnit 测试,该测试测试“端口”参数。以下语法处理上面配置片段的“port=8080”元素:
configurationStatement[MiddlemanConfiguration config]
: PORT EQ port=NUMBER {
config.setConfigurationPort(Integer.parseInt(port.getText())); }
| def=proxyDefinition { config.add(def); }
;
我得到的信息是:
mismatched input '8080' expecting NUMBER
其中 NUMBER 定义为NUMBER : ('0'..'9')+ ;
将 NUMBER 的规则移到 IDENTIFIER 块上方,解决了这个问题。