2015-01-16 28 views
0

我的語法看起來像這樣(簡化,以顯示這個問題):如何共享值不同的令牌 - 不匹配的輸入「COMMAND1」期待FUNCTIONNAME2" -

parse 
    : block EOF 
    ; 

block 
    : TYPE1 OPAR STRING CPAR type1_statement_block  
    | TYPE2 OPAR STRING CPAR type2_statement_block   
    ; 

type1_statement_block 
    : OBRACE function1+ CBRACE     
    ; 

function1 
    : FUNCTIONNAME1 OPAR (parameter (',' parameter)*)? CPAR  
    ; 

FUNCTIONNAME1 : 'COMMAND1'; 

type2_statement_block 
    : OBRACE function2+ CBRACE     
    ; 

function2 
    : FUNCTIONNAME2 OPAR (parameter (',' parameter)*)? CPAR  
    ; 

FUNCTIONNAME2 : 'COMMAND1' | 'COMMAND2' 

parameter 
    : INT        
    ; 

OPAR : '('; 
CPAR : ')'; 
OBRACE : '{'; 
CBRACE : '}'; 
TYPE1 : 'TYPE1'; 
TYPE2 : 'TYPE2'; 

INT 
    : [0-9]+ 
    ; 

STRING 
: '"' (~["\r\n] | '""')* '"' 
; 

SPACE 
: [ \t\r\n] -> skip 
; 

ErrChar 
    : . 
    ; 

解析以下字符串正常工作:

TYPE1 ("abc") { COMMAND1(0) } 
TYPE2 ("abc") { COMMAND2(0) } 

但是在解析錯誤下面的字符串結果

TYPE2 ("abc") { COMMAND1(0) } 

我得到「不匹配的輸入'COMMAND1'expect FUNCTIONNAME2「

我該如何得到這個場景的工作?即這兩個代碼塊可以包含相同的函數名稱?

回答

0

基本問題是詞法分析器將始終將「COMMAND1」分配給FUNCTIONNAME1標記,因爲該規則首先出現,而相對於規則FUNCTIONNAME2的所有其他詞法要求相等。你可以合併FUNCTIONNAME1/2規則,但這會導致語法的第二個問題。按照書面的說法,語法試圖在'語法1'和'類型2'語句之間進行語義上的區別,否則這些語句在語法上是相同的。更好的做法是使用語法來進行句法分析並推遲樹行走的語義分析。關注的分離將使兩者更容易。

block 
    : (cmd OPAR STRING CPAR statement_block)+ 
    ; 

statement_block 
    : OBRACE function+ CBRACE 
    ; 

function 
    : FUNCTIONNAME OPAR (parameter (',' parameter)*)? CPAR  
    ; 

cmd : 'TYPE1' | 'TYPE2' ; 
FUNCTIONNAME : 'COMMAND1' | 'COMMAND2' ;