Bison - Ejemplos (I)

3 - Ejemplos (I)

[editar]
Tutorial creado por Charles Donnelly y Richard Stallman. Extraido de: http://es.tldp.org/Manuales-LuCAS/guides/bison-guide/bison-es-1.27.html
01 de Marzo de 2006
Ahora presentaremos y explicaremos tres programas de ejemplo escritos utilizando Bison; una calculadora de notación polaca inversa, una calculadora de notación algebraica (infija), y una calculadora multi-función. Los tres han sido comprobados bajo BSD Unix 4.3; cada uno produce una utilizable, aunque limitada, calculadora de escritorio.

Estos ejemplos son simples, pero las gramáticas de Bison para lenguajes de programación reales se escriben de la misma manera.

Calculadora de Notación Polaca Inversa


El primer ejemplo es el de una simple calculadora de doble precisión de notación polaca inversa (una calculadora que utiliza operadores postfijos). Este ejemplo provee un buen punto de partida, ya que no hay problema con la precedencia de operadores. El segundo ejemplo ilustrará cómo se maneja la precendencia de operadores.

El código fuente para esta calculadora se llama `rpcalc.y'. La extensión `.y' es una convención utilizada para los archivos de entrada de Bison.

Declaraciones para rpcalc


Aqui están las declaraciones de C y Bison para la calculadora de notación polaca inversa. Como en C, los comentarios se colocan entre `/*...*/'.

/* Calculadora de notación polaca inversa. */

%{
#define YYSTYPE double
#include <math.h>
%}

%token NUM



Las agrupaciones del "lenguaje" de rpcalc definidas aquí son la expresión (con el nombre exp), la línea de entrada (line), y la transcripción completa de la entrada (input). Cada uno de estos símbolos no terminales tiene varias reglas alternativas, unidas por el puntuador `|' que se lee como "o". Las siguientes secciones explican lo que significan estas reglas.

La semántica del lenguaje se determina por las acciones que se toman cuando una agrupación es reconocida. Las acciones son el código C que aparecen entre llaves. See section Acciones.

Debe especificar estas acciones en C, pero Bison facilita la forma de pasar valores semánticos entre las reglas. En cada acción, la pseudo-variable $$ representa el valor semántico para la agrupación que la regla va a construir. El trabajo principal de la mayoría de las acciones es la asignación de un valor para $$. Se accede al valor semántico de los componentes de la regla con $1, $2, y así sucesivamente.

Explicación para input


Considere la definición de input:

input: /* vacío */
| input line
;

Esta definición se interpreta así: "Una entrada completa es o una cadena vacía, o una entrada completa seguida por una línea de entrada". Note que "entrada completa" se define en sus propios términos. Se dice que esta definición es recursiva por la izquierda ya que input aparece siempre como el símbolo más a la izquierda en la secuencia. See section Reglas Recursivas.

La primera alternativa está vacía porque no hay símbolos entre los dos puntos y el primer `|'; esto significa que input puede corresponder con una cadena de entrada vacía (sin tokens). Escribimos estas reglas de esa manera porque es legítimo escribir Ctrl-d después de arrancar la calculadora. Es clásico poner una alternativa vacía al principio y escribir en esta el comentario `/* vacío */'.

La segunda alternativa de la regla (input line) maneja toda la entrada no trivial. Esta significa, "Después de leer cualquier número de líneas, leer una más si es posible". La recursividad por la izquierda convierte esta regla en un bucle. Ya que la primera alternativa concuerda con la entrada vacía, el bucle se puede ejecutar cero o más veces.

La función yyparse del analizador continúa con el procesamiento de la entrada hasta que se encuentre con un error gramatical o el analizador diga que no hay más tokens de entrada; convendremos que esto último sucederá al final del fichero.

Explicación para line


Ahora considere la definición de line:

line: '\n'
| exp '\n' { printf ("\t%.10g\n", $1); }
;

La primera alternativa es un token que es un caracter de nueva-línea; esta quiere decir que rpcalc acepta un línea en blanco (y la ignora, ya que no hay ninguna acción). La segunda alternativa es una expresión seguida de una línea nueva. Esta es la alternativa que hace que rpcalc sea útil. El valor semántico de la agrupación exp es el valor de $1 porque la exp en cuestión es el primer símbolo en la alternativa. La acción imprime este valor, que es el resultado del cálculo que solicitó el usuario.

Esta acción es poco común porque no asigna un valor a $$. Como consecuencia, el valor semántico asociado con line está sin inicializar (su valor será impredecible). Se trataría de un error si ese valor se utilizara, pero nosotros no lo utilizaremos: una vez que rpcalc haya imprimido el valor de la línea de entrada del usuario, ese valor no se necesitará más.

Explicación para expr


La agrupación exp tiene varias reglas, una para cada tipo de expresión. La primera regla maneja la expresiones más simples: aquellas que son solamente números. La segunda maneja una expresión de adición, que tiene el aspecto de dos expresiones seguidas de un signo más. La tercera maneja la resta, y así sucesivamente.

exp: NUM
| exp exp '+' { $$ = $1 + $2; }
| exp exp '-' { $$ = $1 - $2; }
...
;

Hemos utilizado `|' para unir las tres reglas de exp, pero igualmente podríamos haberlas escrito por separado:

exp: NUM ;
exp: exp exp '+' { $$ = $1 + $2; } ;
exp: exp exp '-' { $$ = $1 - $2; } ;
...

La mayoría de las reglas tienen acciones que computan el valor de la expresión en términos del valor de sus componentes. Por ejemplo, en la regla de la adición, $1 hace referencia al primer componenete exp y $2 hace referencia al segundo. El tercer componente, '+', no tiene un valor semántico asociado con significado, pero si tuviese alguno podría hacer referencia a este con $3. Cuando yyparse reconoce una expresión de suma usando esta regla, la suma de los valores de las dos subexpresiones producen el valor de toda la expresión. See section Acciones.

Usted no tiene de dar una acción para cada regla. Cuando una regla no tenga acción, por defecto Bison copia el valor de $1 en $$. Esto es lo que sucede en la primera regla (la que usa NUM).

El formato mostrado aquí es la convención recomendada, pero Bison no lo requiere. Puede añadir o cambiar todos los espacios en blanco que desee. Por ejemplo, esto:

exp : NUM | exp exp '+' {$$ = $1 + $2; } | ...

expresa lo mismo que esto:

exp: NUM
| exp exp '+' { $$ = $1 + $2; }
| ...

El último, sin embargo, es mucho más legible.
[editar]

2 opiniones

BISON

HHHH
Bison.

Esta bueno.

Tutoriales relacionados con 'Bison'

Este documento proporciona una información básica sobre el sistema operativo Linux, incluyendo una explicación de... Más »

Autor y licencia de 'Bison'


Tutorial de Charles Donnelly y Richard Stallman. Extraido de: http://es.tldp.org/Manuales-LuCAS/guides/bison-guide/bison-es-1.27.html CopyLeft
Licencia GNU Free Documentation License: http://www.es.gnu.org/licencias/fdles.html
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.