Está en la página 1de 13

Generador de analizadores sintcticos BISON a

PROCESADORES DE LENGUAJES 4o Informtica a http://ccia.ei.uvigo.es/docencia/PL noviembre-2008

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

Permite asociar cdigo C (acciones semnticas) a las reglas de la o a gramtica a


se ejecutar cada vez que se aplique la regla correspondiente a

Esquema de funcionamiento:
fichero.y ---> BISON ---> fichero.tab.c fichero.tab.c + (ficheros .c) ---> GCC | |-- main() |-- yyerror() |-- yylex() ---> ejecutable

Compilacin: o $ bison fichero.y


Compila la especicacin de la gramtica y crea el chero fichero.tab.c con el o a cdigo y las tablas del analizador LALR(1) o

$ gcc fichero.tab.c (ficheros .c)


El usuario debe proporcinar las funciones main(), yyerror() y yylex() . El cdigo de o usuario deber llamar a la funcin yyparse(), desde la cual se llamar a la funcin a o a o yylex() del analizador lxico cada vez que necesite un token. e

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

2. Funcionamiento del analizador

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

La funcin yyparse() realiza un anlisis ascendente salto-reduccin o a o


agrupa tokens y no terminales segn a las reglas de la gramtica u a utiliza una pila donde acumula s mbolos cuando en la cima de la pila se localiza el lado derecho de una regla, se eliminarn de la pila y se meter en ella el no terminal del lado derecho de la a a regla. (REDUCCION)

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

3. Especicacin de gramticas en BISON o a


3 partes separadas por s mbolo "%%" (2 primeras obligatorias, pueden ir vac as)
<seccin de declaraciones> o %% <seccin de reglas y acciones> o %% <seccin de rutinas de usuario> o

(a) Seccin de Declaraciones. o


Cdigo C necesario para las acciones semnticas. o a Ir entre los s a mbolos "%{" y "%}" (se copia tal cual en "XXXX.tab.c") Generalmente sern #includes y/o estructuras y variables a Deniciones de BISON. 1. Especicacin de yystype (tipo de los valores semnticos) o a tipo de datos asociado a los elementos de la pila (tokens y no terminales) se usa la directiva %union XXXX.Y XXXX.TAB.H / XXXX.TAB.C %union { int entero; double real; char * texto; } typedef union { int entero; double real; char * texto; } YYSTYPE;

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

(b) Seccin de reglas o


1. Formato de las reglas: no_terminal : componente1 componenete2 ... componenteN ; Varias reglas con el mismo lado izquierdo pueden abreviarse: no_terminal : lado_derecho_1 | lado_derecho_2 | lado_derecho_3 ; La reglas- tienen su lado derecho vacio 2. Acciones semnticas: a Contienen cdigo C que se ejecutar cada vez que se reconozca una o a instancia de la regla asociada. Formato: sentencias C incluidas entre llaves ("{" y "}") Suelen ir al nal de la regla y se ejecutan cuando se reconoce completamente su parte derecha Tambin se admiten en otras posiciones dentro de las reglas, que se e ejecutarn en cuanto se reconozca esa fraccin de la regla a o 3. Pseudo-variables: Las pseudo-variables $$, $1, $2, . . . permiten acceder a los valores semnticos a asociados a los s a mbolos de la regla. $$: valor semntico asociado al no terminal del lado izquierdo de la regla a $1, $2, ..., $N: valores semnticos asociados a los s a mbolos (tokens y no terminales) del lado derecho El tipo de esas pseudo-variables ser el que fue asignado al a s mbolo correspondiente en la seccin de declaraciones (directio vas %token, %type, %left, ..) Si no hay accin, bison aade la accin por defecto {$$=$1;} (cuando o n o concuerden los tipos)

(c) Seccin de rutinas de usuario o


Esta seccin zona se puede escribir cdigo C adicional o o Suelen ser funciones llamadas desde las acciones de las reglas En programas pequeos, suelen incluirse las funciones main(), yyerror() y/o n yylex() que aporta el usuario

2008 ccia PL

4. Integracin con el analizador lxico o e


En BISON los tokens son constantes numricas que identican una clase de e s mbolos terminales equivalentes. El analizador lxico debe proporcionar una funcin int yylex() e o cada vez que sea llamada identicar el siguiente s a mbolo terminal en la entrada y devolver la constante entera que lo identica a esas constantes enteras estn denidas en el chero de cabecera a "XXXX.tab.h" (generado con la opcin -d) o declaraciones #dene que asocian nombre de token con su valor numrico e Con los caracteres simples no es necesario denir un espec co, dado que ya estn idencados por su cdigo ASCII. a o el analizador lxico simplemente deber devolver su valor ASCII. e a no hay conicto con otros tokens (BISON les asigna valores entreros > 256) Para tokens con atributos se usa la var. global yylval (de tipo yystype) denido mediante la directiva %union. la declaracin de yylval e yystype est en "XXXX.tab.h" o a

Integracin con FLEX o


Pasos para utilizar los analizadores lxicos generados con FLEX: e 1. Generar el chero "XXXX.tab.h" con bison -d 2. Incluirlo en la seccin de declaraciones C de la expecicacin FLEX o o
%{ #include "XXXX.tab.h" %} %%

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]; }

Nota: Para los caracteres simples, basta devolver su valor en ASCII.

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

Resolucin conictos desplazamiento-reduccin o o conito entre token y regla


SI SI SI SI la precedencia no est definida ---.> por defecto, desplazar a token MAYOR PRECEDENCIA que regla ---> desplazar regla MAYOR PRECEDENCIA que {\sc token} ---> reducir IGUAL PRECEDENCIA (Mirar ASOCIATIVIDAD) SI token asociativo por IZQUIERDA ---> reducir SI token asociativo por DERECHA ---> desplazar SI token no asociativo ---> generar WARNING y, por defecto, desplazar

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}+

"+"|"-"|"*"|"/"|"=" "\n" {LETRA}({LETRA}|_)*

. %%

Compilacin o $ bison -d calculadora.y $ flex calculadora.l $ gcc -o calculador calculadora.tab.c lex.yy.c diccionario.c

2008 ccia PL

12

También podría gustarte