2012-05-29 29 views
1

我使用ANTLR和下面的語法:的QuickBasic語法使用ANTLR

grammar QuickBasic; 

options 
{ 
    language = 'CSharp2'; 
    output = AST; 
} 

parse 
    : block EOF 
    ; 

block 
    : (labelStatement | labeledStatement | statement)* 
    ; 

labelStatement 
    : label ':' -> ^(label) 
    ; 

labeledStatement 
    : label statement -> ^(label statement) 
    ; 

statement 
    : assignment 
    ; 

assignment 
    : IDENTIFIER '=' value -> ^('=' IDENTIFIER value) 
    ; 

value 
    : (IDENTIFIER | constant) 
    ; 

constant 
    : (STRING | INTEGER | REAL) 
    ; 

label 
    : (ALPHANUMERIC)+ 
    ; 

IDENTIFIER 
    : LETTER (ALPHANUMERIC)* 
    ; 

REAL 
    : (INTEGER '.' NATURAL) 
    ; 

INTEGER 
    : ('-')? NATURAL 
    ; 

SPACE 
    : (' ' | '\t' | '\r' | '\n' | '\u000C') {Skip();} 
    ; 

STRING 
    : '"' ('""' | ~'"')* '"' 
    ; 

fragment NATURAL 
    : (DIGIT)+ 
    ; 

fragment ALPHANUMERIC 
    : (DIGIT | LETTER) 
    ; 

fragment DIGIT 
    : '0'..'9' 
    ; 

fragment LETTER 
    : ('a'..'z' | 'A'..'Z') 
    ; 

有了這個,我試圖解析如下因素文件:

PI = 3.141592 
CALC: 
100 A = 1 

接下來發生的事情是,行'CALC:'應該是一個標籤,但它試圖解析爲一個語句,並給我一個錯誤,說錯誤的輸入':'期待'='。

回答

2

label規則是錯誤的:

label 
    : (ALPHANUMERIC)+ 
    ; 

因爲ALPHANUMERIC是片段 - 詞法分析器規則,它只能被其他詞法分析器規則使用,而不能在解析器規則中使用。您的詞法分析器只會生成以下標記:IDENTIFIER,INTEGER,REALSTRING(在解析器規則中加上文字標記,例如'.'等):使這些是您可以在解析器規則中使用的唯一詞法分析器規則。

此外,您應該只創建具有單個唯一根的AST。您正在嘗試爲labelStatementlabeledStatement創建一個根目錄,該根目錄不會與其他解析器規則區分開來:在遇到此類問題的根時,使樹步行者(ANTLR的樹步行者或您自己的樹步行者)遇到問題AST。最好創建(虛構的)LABELLABELED_STAT令牌的使他們的AST的根:

... 

tokens 
{ 
    LABEL; 
    LABELED_STAT; 
} 

parse 
    : block EOF 
    ; 

... 

labelStatement 
    : label ':' -> ^(LABEL label) 
    ; 

labeledStatement 
    : label statement -> ^(LABELED_STAT label statement) 
    ; 

... 

label 
    : IDENTIFIER 
    | INTEGER 
    ; 

這將創建下列AST:

enter image description here

+0

確切!感謝Bart! –

+0

不客氣@JonathasCosta。 –

0

嘗試使用小寫跳過(),而不是跳過()和這樣的事情,讓多個空格

SPACE 
    : (' ' | '\t' | '\u000C' | '\n' | '\r')+ {skip();} 
    ; 
+0

我想 「跳過()」 爲只是一個基類「Lexer」的java方法...因爲我使用的是c#,所以方法是「Skip()」。那是對的嗎? –

+0

不,'Skip()'而不是'skip()'並且在'SPACE'規則中添加'+'不會有什麼區別。 (@JonathasCosta,是的,你是對的)。 –