Вы находитесь на странице: 1из 22

Prcticas de procesadores de lenguajes

1
Yacc/Bison
Introduccin
Uso de Yacc/Bison con Lex/Flex
Construccin del programa objetivo
Flujo de control de las funciones yylex() e yyparse()
Formato del fichero de especificacin de Yacc/Bison
Sstructura del fichero
Seccin de declaraciones C
Seccin de declaraciones Yacc/Bison
Seccin de reglas de la gramtica
Seccin de codigo C
Informacin y recuperacin de errores
Generalidades
Notificacn de errores
Recuperacin de errores
ndice
Marina de la Cruz
Prcticas de procesadores de lenguajes
2
Introduccin
Yacc es un generador de analizadores sintcticos LALR(1).
Bison es la versin GNU de Yacc.
Es totalmente compatible con Yacc.
Mejora algunas de las prestaciones de Yacc.
Habitualmente Yacc/Bison se utiliza conjuntamente con Lex/Flex.
Lex/Flex genera un analizador lxico: yylex()
Yacc/Bison genera un analizador sintctico: yyparse()
Prcticas de procesadores de lenguajes
3
Uso de Yacc/Bison con Lex/Flex (I)
Lex/F|ex
Espec|l|cac|r
Lex/F|ex
yy|ex( }
gcc
Yacc/8|sor
Espec|l|cac|r
Yacc/8|sor
yyparse( }
Programa
Func|ones
de usuar|o
L|brer|as
de| s|stema
*.l *.y
lex.yy.c y.tab.c / *.tab.c
*.c libl.a
liby.a
Construccin del programa objetivo
Prcticas de procesadores de lenguajes
4
Uso de Yacc/Bison con Lex/Flex (II)
yy|ex( }
yyparse( }
ma|n( }
Analizar
entrada
Solicitud del
siguiente token
Entrada
Leer
caracteres
yy|va|
Valor del
token
N del token,
0 si es EOF
0 si anlisis OK,
1 en otro caso
Uso en las
acciones
Flujo de control de las funciones yylex() e yyparse()
Prcticas de procesadores de lenguajes
5
Formato del fichero de especificacin de Yacc/Bison (I)
Un fichero de especificacin de Yacc/Bison tiene cuatro secciones:
Estructura del fichero
%{
Declaraciones C
%}
Declaraciones Yacc/Bison
%%
Reglas de la gramtica
%%
Cdigo C
Las cadenas %{, %} y %%
sirven para delimitar las
secciones.
Se pueden colocar comentarios
del tipo /* ... */ en cualquiera de
las secciones.
Prcticas de procesadores de lenguajes
6
Formato del fichero de especificacin de Yacc/Bison (II)
Seccin de declaraciones C
Contiene:
definiciones de macros
declaraciones de variables
declaraciones de funciones
directivas #include
... que se van a utilizar en las acciones de las reglas gramaticales.
El contenido de esta seccin se copia literalmente al principio del fichero que
genera Yacc/Bison (y.tab.c/*.tab.c).
Prcticas de procesadores de lenguajes
7
Formato del fichero de especificacin de Yacc/Bison (III)
Seccin de declaraciones Yacc/Bison (I)
En esta seccin se puede declarar el tipo de la variable yylval, los smbolos
(terminales y no terminales) de la gramtica, el axioma de la gramtica, y la
asociatividad y precedencia de los operadores.
Declaracin %union
Por defecto, la variable yylval mediante la cual Lex/Flex le pasa a Yacc/Bison los
valores semnticos de los tokens es de tipo int. Pero habitualmente, los valores
semnticos de los tokens son de distintos tipos. Por ejemplo, un token de tipo
identificador (ID) tiene un valor semtico de tipo char*, mientras que un token
de tipo constante numrica (NUM) tiene un valor semntico de tipo int. Con la
declaracin %union se define indirectamente una unin de C con un campo para
cada tipo de valor semntico, por ejemplo:
%union
{
char* cadena;
int numero;
}
Prcticas de procesadores de lenguajes
8
Formato del fichero de especificacin de Yacc/Bison (IV)
Seccin de declaraciones Yacc/Bison (II)
Declaracin %token (i)
Se utiliza para definir los simbolos no terminales (tokens) de la gramtica.
La forma ms sencilla es:
%token NOMBRE_TOKEN
Una forma ms completa es:
%token <campo_union> NOMBRE_TOKEN
Ejemplo:
%token IF
%token THEN
...
%token <cadena> ID
%token <numero> NUM
Desde Lex/Flex, los tokens cualificados se devolvern haciendo, por ejemplo:
[A-Z]+ { yylval.identificador = yytext; return ID; }
[0-9]+ { yylval.numero = atoi(yytext); return NUM; }
Prcticas de procesadores de lenguajes
9
Formato del fichero de especificacin de Yacc/Bison (V)
Seccin de declaraciones Yacc/Bison (III)
Declaracin %token (ii)
Por convenio, los nombres de los tokens se ponen en maysculas.
Se pueden agrupar varios token en una linea si tienen en mismo tipo.
Los tokens de un nico carcter no es necesario declararlos, porque estn
declarados implcitamente.
Desde Lex/Flex, este tipo de tokens se devolvern haciendo, por ejemplo:
+ {return +; }
( {return (; }
; {return ;; }
El nmero 0 est reservado para el fin de fichero. Lex/Flex har lo siguiente:
<<EOF>> {return 0; }
Cuando se compila el fichero de especificacin .y se utiliza la opcin -d, que
fuerza a que Yacc/Bison genere el fichero y.tab.h/*.tab.h que contiene las
definiciones de los tokens. Si este fichero se incluye en la especificacin de
Lex/Flex, se consigue que Yacc/Bison y Lex/Flex compartan las definiciones de
tokens.
Prcticas de procesadores de lenguajes
10
Formato del fichero de especificacin de Yacc/Bison (VI)
Seccin de declaraciones Yacc/Bison (IV)
Ejemplo de fichero y.tab.h
%{
..........................
%}
%union
{
char cadena[20];
int numero;
}
%token IF
%token THEN
%token ELSE
%token <cadena> ID
%token <numero> NUM
..........................
%%
..........................
%%
..........................
ejemplo.y
Yacc/8|sor
-d
typedef union
{
char cadena[20];
int numero;
}YYSTYPE;
extern YYSTYPE yylval;
#define IF 257
#define THEN 258
#define ELSE 259
#define ID 260
#define NUM 261
..........................
..........................
..........................
y.tab.c / ejemplo.tab.c
y.tab.h / ejemplo.tab.h
#include y.tab.h
..........................
ejemplo.l
Prcticas de procesadores de lenguajes
11
Formato del fichero de especificacin de Yacc/Bison (VII)
Seccin de declaraciones Yacc/Bison (V)
Declaracin %type
Se utiliza cuando se ha hecho la declaracin %union para especificar mltiples
tipos de valores.
Permite declarar el tipo de los smbolos no terminales. Lo no terminales a los
que no se les asigna ningn valor a travs de $$ no es necesario declararlos
(ver seccin de reglas de la gramtica)
La declaracin es de la forma
%type <campo_union> nombre_no_terminal
Por convenio, los nombres de los no terminales se ponen en minsculas.
Se pueden agrupar varios no terminales en una linea si tienen en mismo tipo.
Declaracin %start
Declara cual es el axioma de la gramtica.
Si se omite la declaracin, se asume que el axioma de la gramtica es el primer
no terminal de la seccin de reglas de la gramtica.
La declaracin es de la forma
%start axioma
Prcticas de procesadores de lenguajes
12
Formato del fichero de especificacin de Yacc/Bison (VIII)
Seccin de declaraciones Yacc/Bison (VI)
Declaraciones %left y %right
Permiten declarar la asociatividad de los operadores de la gramtica.
La declaracin %left especifica asociativiadad por la izquierda.
La declaracin %right especifica asociativiadad por la derecha.
La precedencia de los operadores queda establecida por el orden de aparicin
de las declaraciones de asociatividad, siendo de menor precedencia en operador
que antes se declara.
Por ejemplo, las declaraciones:
%left + -
%left * /
establecen que los cuatro operadores son asociativos por la izquierda, que + y
- son de la misma precedencia, pero de menor que * y /.
Prcticas de procesadores de lenguajes
13
Es la seccin ms importante del fichero de especificacin.
Contiene las reglas de la gramtica escritas en un formato concreto y con
acciones asociadas a las reglas opcionalmente.
Formato de las reglas:
simboloNoTerminal: simb1 simb2 simbM [accin]
;
si varias reglas tienen la misma parte izquierda se pueden agrupar
simboloNoTerminal: parteDerecha1 [accin1]
| parteDerecha2 [accin2]

;
por claridad, se comentan las reglas lambda:
simboloNoTerminal: /* vaco */ [accin1]
| parteDerecha2 [accin2]
;
Formato del fichero de especificacin de Yacc/Bison (IX)
Seccin de reglas de la gramtica (I)
Prcticas de procesadores de lenguajes
14
Ejemplo de especificacin de reglas (sin acciones):
Formato del fichero de especificacin de Yacc/Bison (X)
Seccin de reglas de la gramtica (II)
..........................
<declaration> ::= <mode> <idlist>
..........................
<mode> ::= bool
| int
| ref <mode>
..........................
<procedures> ::= <procedure><procedures>
|
.......................
Descripcin BNF del lenguaje
..........................
declaration: mode idlist
;
..........................
mode: BOOL
| INT
| REF mode
;
..........................
procedures: procedure procedures
| /* vaco */
;
.......................
Ejemplo.y
Prcticas de procesadores de lenguajes
15
Formato del fichero de especificacin de Yacc/Bison (XI)
Seccin de reglas de la gramtica (III)
Las acciones de las reglas:
las acciones son un conjunto de instrucciones C encerradas entre llaves, y que
se ejecutan cada vez que se reconoce una instancia de la regla.
Normalmente se sitan al final de la regla, aunque tambin se admiten en otras
posiciones de la regla.
La mayora de las acciones trabajan con los valores semnticos de los smbolos
de la parte derecha, accediendo a ellos mediante pseudo-variables del tipo $N,
donde N representa la posicin del smbolo. El valor semntico del smbolo no
terminal de la parte izquierda de la regla se referencia con $$.
El tipo del valor semntico de un smbolo es el que se le haya asociado
mediante una declaracin %token (terminales) o %type (no terminales).
La accin por defecto es:
$$ = $$1
Ejemplo:
exp: ...
| exp + exp {$$ = $1 + $3}
;
Prcticas de procesadores de lenguajes
16
Formato del fichero de especificacin de Yacc/Bison (XII)
Seccin de cdigo C
En esta seccin se ubican todas las funciones de soporte.
Hay tres funciones que siempre tienen que aparecer:
main: funcin principal que invoca a la funcin yyparse que realiza el
anlisis sintactico.
yylex: funcin invocada desde yyparse para obtener un nuevo token de la
entrada.
yyerror: funcin invocada desde yyparse cuando ocurre un error sintctico.
Estas tres funciones se pueden insertar en esta seccin o en un fichero
aparte para ser linkado posteriormente.
Prcticas de procesadores de lenguajes
17
Notificacin y recuperacin de errores (I)
Generalidades
Distinguimos entre notificacin y recuperacin de errores.
Notificacin
informacin al exterior de que ha ocurrido un error en el anlisis.
Recuperacin
mecanismo que permita continuar el anlisis despus de que haya ocurrido un
error.
Ventajas: mejora la productividad del programador porque reduce el tiempo del
ciclo programar-compilar-corregir.
Inconvenientes: puede desencadenar errores en cascada.
La primera tarea que hay que hacer es decidir cules son los errores que el
analizador sintctico tiene que notificar y ante qu errores se podr
recuperar.
Prcticas de procesadores de lenguajes
18
Notificacin y recuperacin de errores (II)
Notificacin de errores (I)
Se produce un error cuando el analizador sintctico, yyparse, recibe del
analizador lxico, yylex, un token que no puede satisfacer ninguna
produccin de la gramtica.
Cuando yyparse detecta un error, para notificarlo, invoca la funcin yyerror
que debe proporcionar el usuario.
La forma ms sencilla de la funcin yyerror es:
void yyerror(char* msg)
{
fprintf(stderr, %s\n, msg);
}
El mensaje con el que se invoca la funcin yyerror es syntax error
(demasiado genrico aunque se acompae con el nmero de lnea donde se
ha producido el error).
Cuando finaliza la funcin yyerror, yyparse intenta la recuperacin del error
(siempre que sea posible, ver apartado de recuperacin de errores). Y si la
recuperacin es imposible, yyparse termina devolviendo un 1.
Prcticas de procesadores de lenguajes
19
yyparse( }
Notificacin y recuperacin de errores (III)
Notificacin de errores (II)
yyerror('syr|ax error)
Recuperac|r
de| error
SI
|o|er esperado ?
Pos|o|e
recuperac|r ?
NO
NO
SI
FlN cor error
contina el
anlisis sintctico

DETECCIN DEL
ERROR
NOTIFICACIN
DEL ERROR
contina el
anlisis sintctico
Prcticas de procesadores de lenguajes
20
Notificacin y recuperacin de errores (IV)
Notificacin de errores (III)
El analizador lxico puede colaborar en la implementacin de una buena
poltica de notificacin de errores.
Ejemplo: si se quiere limitar la longitud de los identificadores, lo natural es
controlar esta longitud en el analizador lxico, por ejemplo, de la siguiente
manera:
[A-Z]+ { yylval.identificador = yytext;
if strlen(yylval.identificador)>MAXID)
return ERROR;
return ID; }
Si analizador sintctico espera recibir un token ID y recibe un token ERROR
llamar a la funcin yyerror que mostrar en mensaje syntax error sin ninguna
indicacin del problema que ha ocurrido. Se puede mejorar la notificacin del
error de la siguiente manera:
[A-Z]+ { yylval.identificador = yytext;
if strlen(yylval.identificador)>MAXID)
fprintf(stderr, ID demasiado largo);
return ID; }
La tcnica de aceptar entradas ilegales y comprobarlas es una tcnica muy
potente para mejorar la notificacin de errores de un compilador.
Prcticas de procesadores de lenguajes
21
Notificacin y recuperacin de errores (V)
Recuperacin de errores (I)
Recuperacin de errores en Yacc/Bison:
Se puede recuperar errores utilizando el token especial error que est siempre
definido y reservado para la gestin de errores.
El token error se utiliza para construir nuevas reglas gramaticales, situndolo
en las posiciones donde se esperan errores.
Por ejemplo:
sentencias: /* vaco */
| sentencias ;
| sentencias exp ;
| sentencias error ;
;
La cuarta regla se puede leer como: un token error seguido de ; es una
construccin vlida despues de sentencias.
Qu ocurre cuando se produce un error en la mitad de exp?. El analizador
saca elementos de la pila de anlisis hasta que llega a un estado en el que el
token error es legal (en este caso sentencias), y avanza la entrada hasta
encontrar un token legal (en este caso ;).
Prcticas de procesadores de lenguajes
22
Notificacin y recuperacin de errores (VI)
Recuperacin de errores (II)
Las reglas que incorporan el token error tambin pueden tener acciones
asociadas.
La recuperacin de errores puede provocar la generacin de errores en cadena,
y para evitar esta situacin, despus de un error, el analizador no muestra
nuevos mensajes de error hasta que tres tokens consecutivos de la entrada
hayan sido desplazados correctamente. Llamando a yyerrok se recuperan los
mensajes de error inmediatamente. La llamada se puede hacer en las acciones
asociadas a la regla.
El token de entrada que provoc el error se puede eliminar de la entrada
llamando a la funcin yyclearin. La llamada se puede hacer en las acciones
asociadas a la regla.

Вам также может понравиться