雖然我有點關心Antlr語法的問題(這不只是我試圖剃這個犛牛形狀的東西)的問題,我還沒有找到一個問題/答案接近幫助我的問題。簡單的Antlr3令牌解析
我使用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 '-'
語法我在已經到達是這樣(注意這個心不是完整g^rammar,只是相關這個問題的部分):
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"
"[email protected]" FAIL
// not with whitepsace
"foo bar" FAIL
運行gUnit僅測試失敗爲 「5foobar」。我已經設法解析這些困難的東西,但解析標識符看起來很簡單的任務已經打敗了我。
任何人都可以指出我哪裏出錯了嗎?我怎樣才能匹配而不貪婪?
非常感謝提前。
- 更新 -
我改變了語法按照巴茨的回答,這樣的:
IDENTIFIER : ('0'..'9'| 'a'..'z'|'A'..'Z' | '_'|'-') ('_'|'-'|'a'..'z'|'A'..'Z'|'0'..'9')* ;
這種固定失敗gUnit測試,但打破了unreleated JUnit測試,即測試「端口」參數。 的配置片段上方的以下語法涉及的 「端口= 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')+ ;
將規則移動到IDENTIFIER塊上方的NUMBER,修復了此問題。
他指出'_foo-bar3'是一個有效的標識符,所以下劃線需要被添加爲允許的第一個字符。此外,儘管ANTLR 4在將規則分割成片段時不存在任何性能問題,但如果僅僅使用''''而不是'HYPHEN','0','9',則ANTLR 3將表現得更好。 'DIGIT'等 – 2012-07-09 14:50:45
@ 280Z28,是的,你是對的。我只看了OP提到的一個gUnit測試用例。我在「IDENTIFIER」規則的開頭添加了「UNDERSCORE」。 – 2012-07-09 15:23:27
Hi @Bart @ 280Z28,我將語法改爲: 'IDENTIFIER :('0'''9'|'a'..'z'|'A'..'Z'|'_' |' - ')('_'|' - '|'a'..'z'|'A'..'Z'|'0'..'9')*;' 現在它可以正確匹配,但是它打破了「端口= 8080」,那些測試現在失敗了。我將編輯該問題以反映。 – user1512122 2012-07-09 16:02:41