2012-07-09 90 views
1

雖然我有點關心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,修復了此問題。

回答

1
IDENTIFIER : DIGIT | LETTER (LETTER | DIGIT | HYPHEN | UNDERSCORE)*; 

相當於:

IDENTIFIER 
: DIGIT 
| LETTER (LETTER | DIGIT | HYPHEN | UNDERSCORE)* 
; 

所以,一個IDENTIFIER是eiter單個DIGIT,或具有LETTER隨後(LETTER | DIGIT | HYPHEN | UNDERSCORE)*開始。

你大概的意思是:

IDENTIFIER 
: (DIGIT | LETTER | UNDERSCORE) (LETTER | DIGIT | HYPHEN | UNDERSCORE)* 
; 

不過,這還允許3---3爲有效IDENTIFIER,是正確的?

+1

他指出'_foo-bar3'是一個有效的標識符,所以下劃線需要被添加爲允許的第一個字符。此外,儘管ANTLR 4在將規則分割成片段時不存在任何性能問題,但如果僅僅使用''''而不是'HYPHEN','0','9',則ANTLR 3將表現得更好。 'DIGIT'等 – 2012-07-09 14:50:45

+0

@ 280Z28,是的,你是對的。我只看了OP提到的一個gUnit測試用例。我在「IDENTIFIER」規則的開頭添加了「UNDERSCORE」。 – 2012-07-09 15:23:27

+0

Hi @Bart @ 280Z28,我將語法改爲: 'IDENTIFIER :('0'''9'|'a'..'z'|'A'..'Z'|'_' |' - ')('_'|' - '|'a'..'z'|'A'..'Z'|'0'..'9')*;' 現在它可以正確匹配,但是它打破了「端口= 8080」,那些測試現在失敗了。我將編輯該問題以反映。 – user1512122 2012-07-09 16:02:41