Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Bison
Bison
2008 ccia PL
1. Introduccin o
Traduce la especicacin de una gramtica de contexto libre a un o a programa en C que implementa un analizador LALR(1) para esa gramtica. a
analizador ascendente de desplazamiento-reduccin. o
Esquema de funcionamiento:
fichero.y ---> BISON ---> fichero.tab.c fichero.tab.c + (ficheros .c) ---> GCC | |-- main() |-- yyerror() |-- yylex() ---> ejecutable
Opciones:
bison -d genera "fichero.tab.h" con las deniciones de las constantes asociadas a los tokens, adems de variables y estrucutras de datos necesarias para el analizador a lxico. e bison -v genera "fichero.output" con un resumen legible del autmata LALR(1) o y seala los conictos y/o errores presentes en la gramtica de entrada n a
2008 ccia PL
El chero "XXXX.tab.c" contine las tablas del analizador y la funcin int yyparse(void) o
yyparse() simula el analizador LALR(1) devolver 0 si el anlisis tuvo xito y 1 si el anlisis fallo a a e a deber de ser llamada desde el cdigo del usuario a o
Cada vez que yyparse() necesite un nuevo token, llamar a la a funcin int yylex() o
yylex() devuelve un no entero que identica al siguiente token esas constantes enteras aparecen en el chero "XXXX.tab.h" yylex() devolver el token eof (end of le) cuando alcance el nal del chero a
Para comunicar los atributos de los tokens se usa la variable global yylval
es de tipo yystype y est declarada en "XXXX.tab.h" a yylex() escribe en yylval los valores que despus usar yyparse() e a
Por regla general el cdigo asociado a una regla (acciones semntio a cas) se ejecutar en el momento en que se reduzca la regla a
es posible incluir cdigo en mitad de la parte derecha de las reglas o a cada elemento de la pila se le asocia asociada una variable de tipo yystype el cdigo de las acciones semnticas puede acceder a esas varibles usando las o a pseudo-variables $$, $1, $2, $3, . . .
2008 ccia PL
2. Especicacin de tokens y de sus propiedades (asociatividad, precedencia) o directiva %token: indica el nombre de un token y opcionalmente su tipo (ser uno de los identicadores declarados en %union) a %token BEGIN END IF THEN ELSE %token <entero> CONSTANTE_ENTERA %token <real> CONSTANTE_REAL %token <texto> NOMBRE_VARIABLE NOMBRE_FUNCION
No es necesario declarar tokens compuestos por un unico caracter Cada caracter se identica por el valor numrico de su cdigo ascii e o Los dems tokens tienen constantes numricas empezando en 256 a e
2008 ccia PL 3
directivas %left, %right, %nonasoc: especica un token con su asociatividad (izquierda, derecha, no asociativo) Determina como actuar el analizador sintctico (normalmente son opera a adores) %left - + * / %right ^ =
3. Especicacin de tipo de los no terminales o No es necesario declarar previamente los no terminales (son los que aparecen en lado izquierdo) directiva %type: especica el tipo de un no terminal Slo para los no terminales que tengan asociados valores semnticos o a %type <entero> expresion_entera %type <real> expresion_real 4. Otros: a directiva %start no terminal: identica al axioma de la gramtica Por defecto bison usa como axioma al no terminal del lado izquierdo de la primera regla.
2008 ccia PL
2008 ccia PL
3. En la accin asociada al patrn de cada token: o o (opcional) cargar en el campo que corresponda de la variable yylval los valores de los atributos lxicos que han sido reconocidos (sern utilizados en e a las acciones de bison) (obligatorio) devolver el tipo del token encontrado mediante una orden return TOKEN
%% [0-9]+ "+" . . . . %% { yylval.entero = atoi(yytext[0]); return CONSTANTE_ENTERA; } { return yytext[0]; }
2008 ccia PL
5. Resolucin de conictos o
Tipos de conictos (surgen cuando la gramtica es ambigua) a desplazamiento-reduccin: el analizar se encuentra con que puede desplazar un o nuevo token a la pila o reducir una regla con el contenido actual de la pila reduccin-reduccin: se reconoce una parte derecha de dos reglas distintas (habr 2 o o a posibles reglas a reducir) Nota: suele deberse a problemas graves en el diseo de la gramtica n a Por defecto BISON informa del error mediante un warning y resuelve el conicto de la siguiente manera: desplazamiento-reduccin : Elige el desplazamiento o reduccin-reduccin : Elige reducir la regla que aparezca primero en la denicin o o o de la gramtica a Otras soluciones : rediseo de la gramtica n a uso del mecanismo de precedencias (slo para desplazamiento-reduccin) o o Mecanismo de precedencias A cada token se le puede asociar una precedencia y una asociatividad. A las reglas se les asocia la precedencia del ultimo token de su parte derecha. La asociatividad de un token se especica con las directivas %left, %right y %nonassoc La precedencia de los tokens se determina por el orden en que fueron declarados. (menor precedencia para los tokens declarados primero)
%left + - %left * / %nonassoc MENOS_UNITARIO %right ^
PRECEDENCIA : " +
- "
<
" *
/ "
<
MENOS_UNITARIO
<
" ^ "
2008 ccia PL
Nota: Se puede especicar la precedencia de una regla empleando el modicador %prec Se aade despues de los componentes de la regla con el siguiente formato n %prec nombre_token Asocia a la regla la precedencia del token indicado.
2008 ccia PL
6. Tratamiento de errores
Cuando hay un error sintctico el analizador generado por BISON llama a la funcin a o yyerror(char *s), que debe proporcionar el usuario. Por defecto, el analizador parar el anlisis despues de detectar el error y de llamar a a a yyerror(), y la funcin yyparse() devolver 1. o a En general esta forma de tratar los errores no es aceptable. Es deseable que despues de encontarse con un error, el analizador siga analizando el resto de la entrada para detectar los dems errores que pueden existir. a Simbolo especial error Mecanismo para tratar y recuperar los errores en BISON Funciona como un TOKEN cticio reservado para el manejo de errores. Siempre que se produce un error de sintaxis, el analizador de BISON genera el s mbolo error, que puede ser manejado en la reglas como un TOKEN normal. Si existe una regla donde capturar el s mbolo error en el contexto actual, el analizador podr recuperarse del error y continuar analizando la entrada a Se incluir la macro yyerrok en la accin de esa regla para indicar que el error a o se ha recuperado Ejemplo :
sentencia : error EOL {yyerrok;}
Acepta que durante el anlisis de una sentencia a haya errores, pero slo hasta leer un TOKEN EOL o (indicar que la zona erronea ha terminado). a
2008 ccia PL
Funcionamiento del s mbolo error Si al detectar un error (el analizador no puede continuar) hay alguna regla aplicable en ese contexto que admita el s mbolo error, el analizador la utilizar (ejecutando a la accin asociada si la tiene [normalmente yyerrok]) y continuar al anlisis. o a a En el caso de que no haya reglas que admitan el s mbolo error: El analizador comenzar a sacar s a mbolos de la pila hasta que encuentre un estado que lo admita o hasta que vacie la pila (el anlisis termina). a En caso de encontrar en la pila una conguracin que admita el TOKEN error o continuar el anlisis, a partir de ese contexto. a a El analizador se ha saltado una parte de la entrada que no hab podido a ser analizada, desechando esos TOKENs. Tres modos de funcionamiento del analizador: Normal no hay errores y se avanza en el anlsis usando las reglas a Sincronizacin despues de encontarse con un error, el analizador comienza a quitar o de la pila buscando un estado que admita el s mbolo error. Recuperacin (modo pnico) cuando se encuentra un estado que admita el error, o a se entra en modo recuperacin aceptando TOKENs a la espera de que la entrada o vuelva a ser correcta 8 < se lean 3 TOKENs correctos consecutivos o Permanece en modo pnico hasta que a : se llame a la macro yyerrok Durante modo pnico no se muestran mensajes de error (no se llama a yyerror(char *s)) para evitar una cascada de mensajes de error hacia el usuario. Salida del modo pnico cuando la entrada vuelve a ser analizable a
2008 ccia PL
10
calculadora.y
%{ /* Cdigo C */ o #include <stdio.h> #include "diccionario.h" DICCIONARIO diccionario; /* variable global para el diccionario */ %} /* Declaraciones de BISON */ %union { int valor_entero; double valor_real; char * texto; } %token <valor_real> CONSTANTE_REAL %token <valor_entero> CONSTANTE_ENTERA %token <texto> IDENTIFICADOR %left - + %left * / %type <valor_real> expresion %% /* Gramatica */ lineas: /* cadena vacia */ | lineas linea ; linea: \n | IDENTIFICADOR = expresion \n {insertar_diccionario(&diccionario, $1, $3);} | expresion \n { printf ("resultado: %f\n", $1); } | error \n { yyerrok;} ; expresion: CONSTANTE_REAL { $$ = $1; } | CONSTANTE_ENTERA { $$ = (double) $1; } | IDENTIFICADOR { ENTRADA * entrada = buscar_diccionario(&diccionario,$1); if (entrada != NULL) { /* encontrada */ $$ = entrada->valor; } else { printf("ERROR: variable %s no definida\n", $1); $$ = 0; } } | expresion + expresion { $$ = $1 + $3; } | expresion - expresion { $$ = $1 - $3; } | expresion * expresion { $$ = $1 * $3; } | expresion / expresion { $$ = $1 / $3; } ; %%
2008 ccia PL
11
int main(int argc, char** argv) { inicializar_diccionario(&diccionario); yyparse(); liberar_diccionario(&diccionario); } yyerror (char *s) { printf ("%s\n", s); int yywrap() { return 1; } }
calculadora.l
%{ /* Codigo C */ #include <stdlib.h> #include <malloc.h> #include <string.h> #include "calculadora.tab.h" %} DIGITO [0-9] LETRA [A-Za-z] %% {DIGITO}+
{ yylval.valor_entero = atoi(yytext); return (CONSTANTE_ENTERA); } { yylval.valor_real = atof(yytext); return (CONSTANTE_REAL); } { return (yytext[0]); } { return (yytext[0]); } { yylval.texto = (char *) malloc (strlen(yytext) + 1); strcpy(yylval.texto, yytext); return (IDENTIFICADOR); } ;
{DIGITO}+\.{DIGITO}+
. %%
Compilacin o $ bison -d calculadora.y $ flex calculadora.l $ gcc -o calculador calculadora.tab.c lex.yy.c diccionario.c
2008 ccia PL
12