2012-05-09 12 views
5

Ich möchte eine Grammatik, die curried Funktionsaufrufe ermöglichen.Wie zu entfernen Links-Rekursion

Das heißt:

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

Mein erster Stich war:

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

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

expr : ID|fncall; 

Aber das scheitert aufgrund Linksrekursion.

Antwort

3

(a)() Unter der Annahme, wäre auch gültig sein, hier eine Möglichkeit, dieses Problem zu lösen:

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

Der Parser aus der Grammatik erzeugte oben würde die Eingabe analysiert:

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

und baut den folgenden AST:

enter image description here

Ohne die Baumumschreibungsregeln würde die Grammatik wie folgt aussehen:

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

Haben Sie etwas dagegen zu erklären, wie die Prädikat Dinge in diesem Zusammenhang funktionieren? Aber vielen Dank für den Code. –

+0

@luxun, ich habe keine Prädikate benutzt: es ist nur eine (einfache) Grammatik, die einen AST erzeugt, also gibt es ein paar Regeln zum Umschreiben. Ich habe meine Antwort so bearbeitet, dass sie die gleiche Grammatik enthält, aber ohne die Umschreibregeln (ich brauche nicht zu sagen, dass die Grammatik keinen AST wie in dem Bild erstellt, das ich gepostet habe ...). –

+0

Ah ich verstehe. Vielen Dank. –