2010-04-19 22 views
8

estoy usando GNU Bison 2.4.2 para escribir una gramática para un nuevo idioma en el que estoy trabajando y tengo una pregunta. cuando especifico regla, digamos:Bison: tokens opcionales en una sola regla

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

Si tengo una variación de la regla, por ejemplo

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

Dónde (de reglas analizador de flex):

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

(y T_IDENT_LIST es una regla para identificadores separados por comas).

¿Hay alguna manera de especificar todo esto solo en una regla, estableciendo de alguna manera el "T_EXTENDS T_IDENT_LIST" como opcional? Ya he probado con

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

Pero bisonte me dio un error.

Gracias

Respuesta

9

Para resumir, no. Bison solo trata con gramáticas LALR (1), lo que significa que solo usa un símbolo de búsqueda anticipada. Lo que necesita es algo como esto:

statement: T_CLASS T_IDENT extension_list '{' ... 

extension_list: 
       | T_EXTENDS T_IDENT_LIST 
       ; 

Hay otros generadores de analizadores sintácticos que trabajan con gramáticas más generales sin embargo. Si la memoria le sirve, algunos de ellos admiten elementos opcionales relativamente directamente como lo que está pidiendo.

+0

Esa fue la solución para escribir solo una regla sin | :) ¡Gracias! –

+0

No tiene nada que ver con que sea LALR (1), ya que ambos son LALR (1). Es porque la sintaxis de entrada es BNF no EBNF. –

+1

@ChrisDodd: Lo siento, pero está mal. El problema aquí es que, mientras lo escribía, su analizador tendría que mirar hacia adelante tres símbolos, a través de T_CLASS y T_IDENT para ver si el siguiente símbolo era '{' o T_EXTENDS para ver qué variación de 'declaración' usar. Eso está violando LALR (1). EBNF parece ser un completo hechizo para mí: no veo nada que se parezca al EBNF en ninguna parte de la pregunta. –

0

creo que lo máximo que puede hacer es

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

¿Por qué no sólo les separa usando las opciones (|) del operador?

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

no creo que puede hacerlo sólo porque se trata de una LALR (1) analizador de abajo hacia arriba, se necesitaría algo diferente como un LL (k) (antlr?) Para hacer lo que quiera hacer ...

Cuestiones relacionadas