2012-05-09 47 views
5

Tôi muốn tạo một ngữ pháp cho phép thực hiện các cuộc gọi chức năng được thực hiện.cách xóa bỏ đệ quy trái

Đó là:

a() /// good 
a()() /// good 
a()()() /// good 
a(a) /// good 
a(a()()) /// good 
/// etc 

đâm đầu tiên của tôi là thế này:

ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*; 

fncall : expr '(' (expr (',' expr)*)? ')'; 

expr : ID|fncall; 

Nhưng điều đó không do đệ quy trái.

Trả lời

3

Giả sử (a)() cũng sẽ có giá trị, đây là một cách để giải quyết việc này:

grammar T; 

options { 
    output=AST; 
} 

tokens { 
    EXPR_LIST; 
    CALL; 
    INDEX; 
    LOOKUP; 
} 

parse 
: expr EOF -> expr 
; 

expr 
: add_expr 
; 

add_expr 
: mul_exp (('+' | '-')^ mul_exp)* 
; 

mul_exp 
: atom (('*' | '/')^ atom)* 
; 

atom 
: fncall 
| NUM 
; 

fncall 
: (fncall_start -> fncall_start) ('(' expr_list ')' -> ^(CALL $fncall expr_list) 
            | '[' expr ']'  -> ^(INDEX $fncall expr) 
            | '.' ID   -> ^(LOOKUP $fncall ID) 
           )* 
; 

fncall_start 
: ID 
| '(' expr ')' -> expr 
; 

expr_list 
: (expr (',' expr)*)? -> ^(EXPR_LIST expr*) 
; 

NUM : '0'..'9'+; 
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*; 

Các phân tích cú pháp được tạo ra từ ngữ pháp trên sẽ phân tích đầu vào:

(foo.bar().array[i*2])(42)(1,2,3) 

và xây dựng AST sau:

enter image description here

Nếu không có quy tắc viết lại cây, ngữ pháp sẽ trông giống như sau:

grammar T; 

parse 
: expr EOF 
; 

expr 
: add_expr 
; 

add_expr 
: mul_exp (('+' | '-') mul_exp)* 
; 

mul_exp 
: atom (('*' | '/') atom)* 
; 

atom 
: fncall 
| NUM 
; 

fncall 
: fncall_start ('(' expr_list ')' | '[' expr ']' | '.' ID)* 
; 

fncall_start 
: ID 
| '(' expr ')' 
; 

expr_list 
: (expr (',' expr)*)? 
; 

NUM : '0'..'9'+; 
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*; 
+0

Bạn có nhớ giải thích cách các biến vị ngữ hoạt động trong ngữ cảnh này không? Nhưng cảm ơn rất nhiều vì mã. –

+0

@ luxun, tôi không sử dụng bất kỳ vị ngữ nào: nó chỉ là một ngữ pháp (thuần túy) tạo ra một AST, vì vậy có một vài quy tắc viết lại. Tôi đã chỉnh sửa câu trả lời của mình để bao gồm cùng một ngữ pháp, nhưng không có quy tắc viết lại (không cần phải nói, ngữ pháp đó sẽ không tạo ra một AST như trong hình ảnh tôi đăng ...). –

+0

Tôi hiểu rồi. Cám ơn rất nhiều. –