2010-04-19 6 views
8

Ich benutze GNU Bison 2.4.2, um eine Grammatik für eine neue Sprache zu schreiben, an der ich arbeite, und ich habe eine Frage. Wenn ich eine Regel angeben, sagen wir mal:Bison: Optionale Tokens in einer einzigen Regel

statement : T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}' { 
      // create a node for the statement ... 
} 

Wenn ich eine Variation der Regel haben, zum Beispiel

statement : T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' { 
      // create a node for the statement ... 
} 

Wo (von flex Scanner-Regeln):

"class"      return T_CLASS; 
"extends"     return T_EXTENDS; 
[a-zA-Z\_][a-zA-Z0-9\_]* return T_IDENT; 

(und T_IDENT_LIST ist eine Regel für durch Kommas getrennte Bezeichner).

Gibt es eine Möglichkeit, all dies nur in einer Regel zu spezifizieren, irgendwie die "T_EXTENDS T_IDENT_LIST" als optional zu setzen? Ich habe schon versucht, mit

T_CLASS T_IDENT (T_EXTENDS T_IDENT_LIST)? '{' T_CLASS_MEMBERS '}' { 
    // create a node for the statement ... 
} 

Aber Bison gab mir einen Fehler.

Danke

Antwort

9

Um eine lange Geschichte kurz zu machen, nein. Bison behandelt nur LALR (1) Grammatiken, was bedeutet, dass es nur ein Symbol von Lookahead verwendet. Was Sie brauchen, ist etwas in der Art:

statement: T_CLASS T_IDENT extension_list '{' ... 

extension_list: 
       | T_EXTENDS T_IDENT_LIST 
       ; 

Es gibt andere Parser-Generatoren, die jedoch mit allgemeineren Grammatiken arbeiten. Wenn Speicher dient, unterstützen einige von ihnen optionale Elemente relativ direkt, wie Sie es wünschen.

+0

Das war die Lösung, nur eine Regel ohne die | zu schreiben :) Vielen Dank! –

+0

Es hat nichts damit zu tun, dass es LALR (1) ist, da beide LALR (1) sind. Weil die Eingabesyntax BNF nicht EBNF ist. –

+1

@ChrisDodd: Sorry, aber falsch. Das Problem hierbei ist, dass sein Parser beim Schreiben drei Symbole über T_CLASS und T_IDENT nach vorne schauen müsste, um zu sehen, ob das nächste Symbol ein '{' oder T_EXTENDS ist, um zu sehen, welche 'Statement'-Variation zu verwenden ist. Das verletzt LALR (1). EBNF sieht für mich wie ein kompletter Red-Hering aus - ich sehe nichts, was EBNF irgendwo in der Frage ähnelt. –

0

ich denke, die meisten Sie tun können,

statement : T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}' 
    | T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' { 
} 
0

ist, warum Sie nicht nur ihnen die Wahl mit Split (|) Operator?

statement: 
    T_CLASS T_IDENT T_EXTENDS T_IDENT_LIST '{' T_CLASS_MEMBERS '}' 
    | T_CLASS T_IDENT '{' T_CLASS_MEMBERS '}' 

Ich glaube nicht, dass Sie es nur tun können, denn dies ist ein LALR (1) von unten nach oben Parser ist, würden Sie etwas anderes wie eine LL (k) (ANTLR?) Müssen tun, was Sie wollen zu tun ..