INDICE
MANUAL
DE YACC
ENTORNO
DEL YACC
OPCIONES
EN LA LLAMADA DEL YACC
ANALIZADOR
DE LÉXICO
AMBIGÜEDAD
Y CONFLICTOS
ESTRUCTURA
DE LA ESPECIFICACIÓN DEL YACC
DECLARACIÓN
DE SÍMBOLOS
REGLAS
GRAMÁTICALES
INTRODUCCIÓN
DE ACCIONES EN EL YACC
TRATAMIENTO
DE ERRORES
1. Entorno
del YACC
Define una función
yyparse() que devuelve 0 si el análisis es correcto y 1 si existe
un error.
Para el analizador
sintáctico hemos de añadir las funciones:
main(), yylex, yyerror
EJEMPLO
main() { yyparse()
}
void yyerror (char
*s)
{
printf("%s\n",s);
}
2.
Opciones en la llamada del YACC
Para ejecutar el
yacc hay que introducir desde la línea de comandos:
BYACC [opciones] fichero_especificaciones
Las opciones son:
-v |
Genera la tabla de
análisis sintáctico en el fichero y.out |
-b
prefijo |
Permite cambiar el
prefijo y del nombre del fichero de salida por el especificado |
-t |
Permite realizar
un "debugging" del análisis sintácico |
-d |
Genera el fichero
de cabecera y_tab.h, que contiene la definición de los tokens |
-r |
Genera dos ficheros
de salida, y_code.c que contiene el código y y_tab.c
que contiene la tabla de análisis |
3.
Analizador de léxico
Para realizar la función del analizador
de léxico, el Yacc utiliza una función entera llamada
yylex(),
cuyo valor se debe asociar a la variable
yyval
El analizador de
léxico:
-
puede ser la función generada con LEX,
o
-
una función definida por el usuario en
la zona de rutinas de usuario
4.
Ambigüedad y conflictos
Una gramática
se dice ambigua cuando alguna de sus sentencias (conjuntos de símbolos)
puede ser estructurada de distintas formas
Si la gramática es ambigua el YACC
nos informará. Las posibles soluciones son:
-
Introducir asociatividad
y precedencia entre los operadores
-
Estudiar la tabla de análisis
en detalle y modificarla
5.
Estructura de la especificación YACC
La estructura del
fichero de especificaciones para el YACC es:
{ Declaraciones de
los símbolos }
%%
Reglas gramaticales
{+acciones}
%%
{ Rutinas de usuario
}
Se pueden incluir comentarios
con el siguiente formato:
/* cero o más
caracteres */
6.
Declaraciones de símbolos
En esta zona tenemos:
-
Código C, opcional
(por ejemplo, declaraciones de variables e inclusión de ficheros)
%{ Código
}%
Definición del
símbolo (no terminal) inicial de la
gramática.
%start
nombre_del_simbolo_inicial
Declaraciones de
todos los nombres de símbolos terminales
que utiliza el lenguaje. Para ello podemos usar:
a) Para todos
los nombres de los símbolos terminales:
%token
simbolo1 simbolo2 ...
EJEMPLO
Defina el token para
los numeros y para un digito.
Defina el token para
los operadores: +, -, &, %, /.
b) Para nombres de símbolos
que representan operadores:
%left
nombre_operador1 nombre_operador2 ...
%right nombre_operador1
nombre_operador2 ...
%nonassoc
nombre_operador1 nombre_operador2 ...
La precedencia
entre los operadores viene dada por el orden en el que se definen los operadores,
las definiciones más internas tienen mayor precedencia. Para cambiar
la precedencia a lo largo del programa Yacc podemos usar:
%prec
nombre_operador
EJEMPLO
Establezca asociatividad
a la izquierda para los operadores: +, -, &, |, *, /, % a la vez que
establece la precedencia de mayor a menor:
*, /, %
+, -
&, |
7.
Reglas gramaticales
El formato
general de una regla gramatical es:
A: CUERPO;
A es el nombre
de un símbolo no terminal (o estructura sintáctica)
CUERPO es una
secuencia de nombres de símbolos y/o nombres de símbolos
no terminales y/o literales, que indican la estructura sintáctica
del símbolo no terminal A
EJEMPLO
Dadas las siguientes
producciones:
<A> := <B><C><D>
<A> := <E><F>
<A> := <G>
Como serian las reglas
gramaticales correspondientes.
Cuando un mismo símbolo no terminal tiene
varias reglas podemos usar | para separar las distintas alternativas y
representarlas en una sola regla.
EJEMPLO
Dadas las producciones
del ejemplo anterior como las representaria en una sola regla gramatical.
La cadena vacia tendra la siguiente representación:
A : ;
8.
Introducción de acciones en Yacc
A cada regla de la gramática el
usuario puede asociar una serie de acciones (acciones semánticas)
que se ejecutarán cuando sea reconocida la regla sintáctica.
El formato es el siguiente:
A: Cuerpo
{ una o más
sentencias } /*Acción semántica */
;
EJEMPLO
Dada la siguiente
produccion:
<A> := <B><C>
Establezca la regla gramatical
correspondiente a la que debe asociarle las siguientes acciones una vez
la reconozca:
Que imprima la cadena
Un
mensaje
Que le asigne a una
variable por ejemplo a el valor 35
Pseudovariables:
son
variables que utiliza el Yacc por indicación del usuario para pasar
información de una regla sintáctica a otra, y que pueden
aparecer en las acciones semánticas:
$$ es la variable
asociada al símbolo no terminal de la izquierda
$n (donde n
es un número entero mayor que o) es la variable asociada al símbolo
no terminal que ocupa el lugar enésimo dentro del cuerpo.
EJEMPLO
Dadas las siguientes
producciones:
<A> := <B><C><D>
<EXPR> := '('<EXPR>')'
Establezca las reglas
gramaticales correspondientes, a las que debe asociarle las siguientes
acciones usando seudovariables:
Al simbolo A
debe asignarle el valor del producto de las variables asociadas al simbolo
B y D.
Al simbolo EXPR
debe asignarle el valor de la variable asociada al simbolo expr.
El Yacc permite introducir
acciones al final de una regla o entre sus símbolos.
a) A: B C D {accion};
b) A: B {acción1};
C D {acción2};
En este último caso transforma la
regla de producción de la siguiente forma:
$$1: {acción1};
A: B $$1 C D {acción2}
Donde $$1 es un nuevo símbolo no terminal
de la gramática y $$1:; es una nueva regla de producción
EJEMPLO
Dada la siguiente
producción, como seria transformada por el Yacc (usando marcadores).
A : B
{$$=1;}
C {X=$2; y=$3;};
9.
Tratamiento de errores
1.- Tratamiento por
defecto: en una situación de error se produce una llamada
a la función yyerror con el mensaje "Sintax Error" y finaliza la
ejecución del analizador sintáctico
2. Introducción
de producciones de error: en la especificación YACC se introducen
producciones denominadas de error que tienen el siguiente formato:
A ®
error w
donde A es un símbolo no terminal
de la gramática, error una palabra reservada de YACC y w
es un símbolo terminal.
El YACC generará una tabla de análisis
a partir de la especificación dando a las producciones de error
el mismo tratamiento que al resto de las producciones
Actuación del
analizador en una situación de error:
Sea S el estado del tope de la pila:
-
Si para S existe un desplazamiento con el símbolo
error
lo aplicará
Si para S no existe un desplazamiento con
el símbolo error, extrae símbolos de la pla hasta
que encuentra un estado que incluya un ítem de la forma A
® .error w introduce error en
la pila
-
Si w es distinto de la cadena vacía,
eliminará caracteres de la entrada hasta encontrar w. Entonces
pasará a reducir por la producción de error.
Si w es la cadena vacía pasa a reducir
por la producción de error
EJEMPLO
Símbolos terminales:
a b c d e f
Símbolos no
terminales: P Q R S
Símbolo inicial:
P
Producciones:
P : a Q R f
Q : c
R : b S e
S : d f | d f S
Establezca la especificación
YACC introduciendo las producciones de error correspondientes.
MÁS
EJEMPLOS
EJEMPLO
Especificación
BYACC para la gramática:
E ®
E+E | E-E | E*E | E/E | id
El significado de
los símbolos en la especificación es el siguiente:
M +
S –
P *
D /
EJEMPLO
Especificación
BYACC para la gramática:
E ®
E+E | E-E | E*E | E/E | id
Donde:
+ - * / son asociativos
por la izquierda y
el orden de precedencia es de mayor a menor:
* /
+ -