Presentación guía sencilla en Microsoft Excel.pptx
Yacc: generador de analizadores sintácticos LALR
1. Yacc
García Vélez María Azucena
Ortega Piña Efraín
UASLP-FI-Área de Computación e Informática-Compiladores e Interpretes A
2. Generalidades
• Yacc es un programa para generar analizadores
sintácticos LALR. Las siglas del nombre
significan Yet Another Compiler-Compiler, es
decir, "Otro generador de compiladores más".
Genera un analizador sintáctico (la parte de
un compilador que comprueba que la estructura
del
código
fuente
se
ajusta
a
la
especificación sintáctica del lenguaje).
• Yacc genera el código para el analizador
sintáctico en el Lenguaje de programación C.
3. • Fue
desarrollado
por
Stephen
C.
Johnson
en
AT&T
para
el
sistema
operativo Unix. Después se escribieron
programas compatibles, por ejemplo Berkeley
Yacc, GNU bison, MKS yacc y Abraxas yacc (una
versión actualizada de la versión original de
AT&T que también es software libre como parte
del proyecto de OpenSolaris de Sun).
• Puesto que el analizador sintáctico generado por
Yacc requiere un analizador léxico, se utiliza a
menudo conjuntamente con un generador de
analizador léxico, en la mayoría de los
casos lex o Flex, alternativa del software libre.
4. Funcionamiento de Yacc
• Igual que sucedía con lex, yacc no es directamente un
analizador sino un generador de analizadores. A partir
de un fichero fuente en yacc, se genera un fichero fuente
en C que contiene el analizador sintáctico. Sin embargo,
un analizador sintáctico de yacc no puede funcionar por
sí solo, sino que necesita un analizador léxico externo
para funcionar. Dicho de otra manera, el fuente en C que
genera yacc contiene llamadas a una función yylex() que
debe estar definida y debe devolver el tipo de lexema
encontrado. Además, es necesario incorporar también
una función yyerror(), que será invocada cuando el
analizador sintáctico encuentre un símbolo que no
encaja en la gramática.
5.
6. Estructura de un programa en Yacc
• Declaraciones o Definiciones
%%
• Reglas de Traduccion
%%
• Soporte de las rutinas en C
7. • De estas tres secciones, sólo la segunda es
obligatoria, y no debe estar vacía (nótese que en
lex, las tres secciones pueden estar vacías). Esto
quiere decir que el mínimo programa en yacc es:
%%
regla gramatical acción en C
8. Declaraciones o definiciones
• Esta parte se toma por dos secciones en la primera
sección se declaran las primeras secciones
ordinarias en c delimitadas por %{ y %}, la segunda
sección a la declaración de tokens %Token TOKEN
%. En esta seccion se pueden emplear la definicion
de la asociatividad y precedencia de los tokens
empleando, e incluso se pueden definir los tipos de
datos %type es importante en esta seccion definir los
tipos de datos para la pila de Yacc mediante la
definicion YYSTYPE o bien mediante una estructura
de union.
9. • La sección de declaraciones puede incluir varias
cosas, tal y como ocurría en lex, pero ahora su
función principal no es definir expresiones
regulares, sino declarar los símbolos terminales
de la gramática mediante la directriz %token.
Todo lo que no sea un terminal, será
considerado un símbolo no terminal, y por tanto
debe haber un a regla para él:
• %token IF,ELSE,LLAVE_AB,LLAVE_CE,IDENT
10. • En algunos de los casos es conveniente indicarle
a yacc cual es el simbolo NT de inicio mediante
el cual se realiza por ejemplo % start SIMBOLO.
11. Reglas de traducción
• En esta seccion se colocan las reglas de
traduccion empleando el siguiente formato.
• <encabezados>:<cuerpo>1<accion semantica>1}
| <cuerpo>2<accion semantica>2}
:
| <cuerpo>n<accion semantica>n}
12. • La sección de reglas contiene la gramática en sí.
Componentes es una combinación de terminales
y no terminales que describe al no terminal de la
izquierda de la regla:
• no_terminal: componentes {acciones en C}
13. Rutinas en C
• En esta sección se incluyen todas las rutinas a
incrustarse en el código final. Es importante
tener un analizador léxico mediante el nombre
yylex, de tal manera que si no se realiza el enlace
entre lex y yacc se deberá de implementar dicha
función en esta parte.
14. Asociatividad y Precedencia
• Por defecto Yacc es asociativo a la derecha pero
esto puede modificarse en la sección de
definiciones utilizando las siguientes directivas:
▫ %left asocia a la izquierda
▫ %right asocia a la derecha
• Supongamos el siguiente fragmento de
programa Yacc para una gramática que reconoce
expresiones de sumas de números:
15. • La sección de rutinas tiene la misma función que
la de lex, pero yacc (dependiendo de su variante)
no define por defecto las funciones main(),
yylex() e yyerror(), así que hay que incluirlas
aquí, o bien en otro fichero que se enlazará en la
fase final de la compilación.
16. • Yacc genera una función llamada yyparse() que
contiene el analizador sintáctico. Esta función se
comporta como una máquina de estados cuya
misión es intentar reducir todo el fichero de
entrada al símbolo inicial de la gramática (el
primero que se haya definido). Si yacc lo
consigue, el analizador sintáctico volverá sin
error, y en caso contrario, se invocará a la
función yyerror(), que debe estar definida
también en algún sitio.
17.
18. • Si la entrada fuese 5+6+8 por defecto se
resolvería como 5+(6+8) (asociación por la
derecha),pero al haber definido %left al símbolo
‘+’ en la sección de definiciones el resultado es
(5+6)+8 (asociación por la izquierda).
19.
20. • %left, %right y %nonassoc Además de indicar
asociatividad se utilizan en la sección de
definiciones para indicar precedencia de los
operadores teniendo mayor precedencia cuanto más
alejados estén del principio del fichero. La última de
las tres directivas no indica asociatividad solo
precedencia.
• %pred Se utiliza en una regla para dar distinta
prioridad al primer símbolo de esa regla, solo para la
aplicación de esa regla. Se usa cuando un mismo
símbolo puede tener significados distintos con
prioridades diferentes. Por ejemplo el símbolo ‘-‘
puede ser unario y binario, cuando es binario tiene
la misma prioridad que ‘+’, pero cuando es unario
tiene mayor prioridad. En este caso se le puede
asignar la misma prioridad que a ‘*’, tal y como se
muestra en el ejemplo siguiente.
21.
22. Conflictos y Ambigüedad
• Cuando la gramática de entrada no es LALR(1),
Yacc informará de que ha encontrado
“conflictos”. Los conflictos se producen cuando
el algoritmo de construcción de las tablas no ha
permitido, en un momento dado, que se sepa si
la acción adecuada es desplazar o reducir
(conflicto shift/reduce), o bien cuando haya
varias posibilidades de reducción (conflicto
reduce/reduce). Se podrá encontrar cuales son
los conflictos aparecidos examinando el
contenido de y.output.
23. • Aveces es conveniente conocer cuales son los
conflictos que provoca nuestra gramática y
tratar de evitarlos, para ello puede ser útil
utilizar la opción –v de Yacc para examinar el
autómata descrito en el fichero y.output.
Independientemente de la información
mostrada Yacc continua el proceso, generando
un programa que resuelve sistemáticamente los
conflictos aplicando las siguientes normas:
▫ Entre desplazar y reducir, elige desplazar.
▫ Entre dos reducciones distintas, elige la
correspondiente a la regla que aparezca en primer
lugar.