2014-09-19 63 views
0

我試圖解決一個非常簡單的語法問題(我剛開始學習使用ANTLR開發語法;我有點新,所以只是忍受着我),這是定義一個簽名的偶數使用ANTLRANTLR 3偶數

A '+' or '-'開始令牌是可選的,並且該號碼可以是1或更多數字,但最後一位數字必須是偶數(例如,+4394將是有效的帶符號偶數)。

最好的語法我至今如下:

grammar SignedEvenNumber; 

DIGIT   : '0'..'9'; 
EVEN_DIGIT  : '0' | '2' | '4' | '6' | '8'; 

signedEvenNumber : ('+' | '-' |) NUMBER+ EVEN_NUMBER; 

我的問題是,迫使ANTLR檢查以偶數作爲最後一位數字的方式定義數字;即它總是將最後一個數字看作DIGIT,不管它是偶數還是奇數(因爲在最後的任何數字都可以)。可能有一個非常簡單的解決方案,我只是沒有得到任何幫助,將不勝感激。

回答

0

我有ANTLR 4更多的經驗,但我認爲,首先定義令牌擁有在語法之後定義其他的優先級,這樣定義第一EVEN_DIGIT:

grammar SignedEvenNumber; 

EVEN_DIGIT  : '0' | '2' | '4' | '6' | '8'; 
DIGIT   : '0'..'9'; 

signedEvenNumber : ('+' | '-')? DIGIT+ EVEN_DIGIT; 

在.tokens文件中的令牌:

DIGIT=4 
T__1=1 
EVEN_DIGIT=3 
T__0=2 
'-'=2 
'+'=1 

對於輸入測試:

的令牌是:

[@0,0:0='+',<1>,1:0] 
[@1,1:1='1',<4>,1:1] 
[@2,2:2='2',<3>,1:2] 
[@3,3:3='3',<4>,1:3] 
[@4,4:4='4',<3>,1:4] 

如果優先doen't工作,你可以重新定義你的令牌和改變這樣的規則:

grammar SignedEvenNumber; 

EVEN_DIGIT  : '0' | '2' | '4' | '6' | '8'; 
DIGIT   : '1' | '3' | '5' | '7' | '9'; 

signedEvenNumber : ('+' | '-')? (DIGIT | EVEN_DIGIT)* EVEN_DIGIT; 
+0

第二種解決方案奏效。例如,改變優先級的問題使得它將'567'解釋爲一個有效的語法(當它不應該)時。謝謝您的幫助。 – bgd53 2014-09-20 04:13:25

0

如果你定義偶數和NOT_EVEN不相交你可以擁有的代幣

SignedEvenNumber : ('+' | '-')? (NOT_EVEN* EVEN)+ 

因爲偶數是一種常用語言,你可以想象它作爲DFA。

0

是否有必要通過DFA加以區分?使用規則操作怎麼樣?

tokens { 
    EVEN_NUMBER; 
    ODD_NUMBER; 
}; 

fragment 
NUMBER_FRAG: DIGIT+; 

NUMBER: t = NUMBER_FRAG 
{ 
    if ($t->getText()->lastDigitIsEven()) 
    { $type = EVEN_NUMBER; } 
    else 
    { $type = ODD_NUMBER; } 
};