2012-05-09 19 views
5

Mi piacerebbe creare una grammatica che consenta chiamate di funzione al curry.come rimuovere la ricorsione a sinistra

Cioè:

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

Il mio primo tentativo è stato questo:

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

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

expr : ID|fncall; 

Ma che non riesce a causa di ricorsione sinistra.

risposta

3

Supponendo (a)() sarebbe anche valido, ecco un modo per risolvere questo:

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'|'_')*; 

Il parser generato dalla grammatica sopra sarebbe analizzare l'input:

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

e costruire la seguente AST:

enter image description here

Senza le regole di riscrittura degli alberi, la grammatica sarebbe la seguente:

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

Ti spiace spiegare come funzionano le predicate in questo contesto? Ma grazie mille per il codice. –

+0

@luxun, non ho usato alcun predicato: è solo una (semplice) grammatica che crea un AST, quindi ci sono un paio di regole di riscrittura. Ho modificato la mia risposta per includere la stessa grammatica, ma senza le regole di riscrittura (inutile dire che la grammatica non creerà un AST come nell'immagine che ho postato ...). –

+0

Ah, capisco. Grazie mille. –