2012-11-29 127 views
1

對於我試圖解析的標記語言,我決定給解析器生成一個嘗試ANTLR。我是這個領域的新手,我正在搞點東西。標記解析器失敗

我的語法是

grammar Test; 
DIGIT : ('0'..'9'); 
LETTER : ('A'..'Z'); 
SLASH : '/'; 
restriction 
    : ('E' ap) 
    | ('L' ap) 
    | 'N'; 
ap : LETTER LETTER LETTER; 
car : LETTER LETTER; 
fnum : DIGIT DIGIT DIGIT DIGIT? LETTER?; 
flt : car fnum?; 
message : 'A' (SLASH flt)? (SLASH restriction)?; 

這不正是我想要的東西,當我給它輸入字符串A/KK543/EPOS。然而,當我給它A/KL543/EPOS時,它失敗(MismatchedTokenException(9!=5))。這似乎是某種衝突;它想在第一個L上生成restriction,所以看起來我在語言定義中做了錯誤的事情,但我無法正確地找出什麼。

回答

3

對於輸入"A/KK543/EPOS",下列令牌創建:

'A'  'A' 
SLASH  '/' 
LETTER  'K' 
LETTER  'K' 
DIGIT  '5' 
DIGIT  '4' 
DIGIT  '3' 
SLASH  '/' 
'E'  'E' 
LETTER  'P' 
LETTER  'O' 
LETTER  'S'

但對於輸入"A/KL543/EPOS",這些都是創建:

'A'  'A' 
SLASH  '/' 
LETTER  'K' 
'L'  'L' 
DIGIT  '5' 
DIGIT  '4' 
DIGIT  '3' 
SLASH  '/' 
'E'  'E' 
LETTER  'P' 
LETTER  'O' 
LETTER  'S'

正如你可以看到,焦炭'L'得到標記爲LETTER。對於解析器規則中的文字標記'A','E','L''N',ANTLR(自動)創建位於所有其他詞法分析器規則之前的單獨詞法分析器規則。這將導致你的詞法分析器看起來像這一幕後:

A  : 'A'; 
E  : 'E'; 
L  : 'L'; 
N  : 'N'; 
DIGIT : '0'..'9'; 
LETTER : 'A'..'Z'; 
SLASH : '/'; 

爲此,任何單一'A''E''L''N'永遠不會成爲LETTER令牌。這就是ANTLR的工作原理。如果您想將它們匹配爲字母,則需要創建一個解析器規則letter,並讓匹配。事情是這樣的:

message 
: A (SLASH flt)? (SLASH restriction)? 
; 

flt 
: car fnum? 
; 

fnum 
: DIGIT DIGIT DIGIT DIGIT? letter? 
; 

restriction 
: E ap 
| L ap 
| N 
; 

ap 
: letter letter letter 
; 

car 
: letter letter 
; 

letter 
: A 
| E 
| L 
| N 
| LETTER 
; 

A  : 'A'; 
E  : 'E'; 
L  : 'L'; 
N  : 'N'; 
DIGIT : '0'..'9'; 
LETTER : 'A'..'Z'; 
SLASH : '/'; 

將解析輸入"A/KL543/EPOS"這樣的:

enter image description here