Introducción a Yacc - GIAA
Introducción a Yacc - GIAA
Introducción a Yacc - GIAA
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Yacc</strong><br />
Gramática<br />
BNF<br />
plan.y<br />
YACC<br />
plan.tab.c<br />
Compilador<br />
+<br />
Enlazador<br />
Ejecutable<br />
Otros<br />
módulos
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Estructura de <strong>Yacc</strong><br />
Yet Another Compiler-Compiler<br />
• Bison: versión GNU<br />
Herramienta para generar analizadores sintácticos<br />
para gramáticas LALR<br />
YACC programa fuente<br />
{definición}<br />
%%<br />
{reglas}<br />
%%<br />
{subrutinas de usuario}<br />
Reglas: acción<br />
producciones pertenecen a una gramática G2 en BNF<br />
Acción: fragmentos de código C que especifican que<br />
hacer cuando se reduce una producción
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Estructura de <strong>Yacc</strong><br />
La forma natural de trabajar es conjuntamente con<br />
LEX:<br />
• yylex(): petición de siguiente token<br />
El analizador está contenido en la función<br />
yyparse()<br />
home\> yacc ejemplo.y<br />
home\> ls *.c<br />
home\> ejemplo.tab.c<br />
home\> flex patrones.lex<br />
home\> ls *.c<br />
home\> lex.yy.c ejemplo.tab.c<br />
home\> gcc -o sint lex.yy.c ejemplo.tab.c
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Principio de <strong>Yacc</strong><br />
Análisis previo de la gramática para construir<br />
el analizador LALR: notifica incidencias<br />
Funcionamiento general del analizador: pide<br />
tokens definidos al analizador léxico (yylex)<br />
• Como es LALR(1), pide un token de pre-análisis<br />
• Cuando realiza desplazamiento pide el siguiente<br />
token<br />
• Cuando realiza reducciones de producciones,<br />
ejecuta el código en sus acciones
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Formato de <strong>Yacc</strong><br />
Tres partes separadas por una línea con<br />
“%%”<br />
Declaraciones<br />
%%<br />
Reglas<br />
%%<br />
Código de usuario<br />
Previas al uso del scanner<br />
Reglas sintácticas y lo que hay<br />
que hacer cuando se activan<br />
Funciones C que se copian al<br />
fichero de salida
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Sección de Declaraciones<br />
Declaraciones:<br />
• Código de usuario<br />
• Se copia a la salida<br />
• %{....%}<br />
• Declaraciones<br />
• Terminales y no terminales (opt):<br />
• %token símbolo<br />
• %type símbolo<br />
• Precedencia y asociatividad<br />
de operadores<br />
• %noassoc símbolos<br />
• %left símbolos<br />
• %right símbolos<br />
• Símbolo de arranque de la gramática<br />
• %start símbolo<br />
• Directivas de comportamiento<br />
%{<br />
%}<br />
%%<br />
%%<br />
Código de usuario<br />
#include
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Sección de Declaraciones<br />
Terminales<br />
• Es lo que devuelve la función yylex() (llamada<br />
automáticamente desde yyparse()<br />
• Se convierten en #define en el fichero de salida<br />
• Se les asocia un número comenzando por 257<br />
• Se puede obligar a que tenga uno en concreto<br />
• %token T_LLAVE 345<br />
• Los terminales de un carácter no hace falta<br />
declararlos (están implícitos)<br />
• En yacc se podrá utilizar directamente el terminal ‘(‘<br />
• Son tokens con valores numéricos el código ASCII<br />
(
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Declaraciones de terminales<br />
Ejemplo definición terminales<br />
• Lenguaje de expresiones aritméticas con enteros<br />
%{<br />
#include <br />
%}<br />
%token NUMERO, MAS, MENOS, POR, DIV, PAR_I, PAR_D<br />
%start expr /* simbolo axioma sentencial */<br />
…<br />
Declaración en YACC de terminales<br />
(expresiones.y)
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Declaraciones de terminales<br />
Ejemplo definición terminales<br />
%{<br />
#include "expresiones_tab.h"<br />
%}<br />
digito [0-9]<br />
%%<br />
[ \t]+ ;<br />
{digito}+ {yylval=atoi(yytext); return NUMERO;}<br />
"+" return MAS;<br />
"-" return MENOS;<br />
"*" return POR;<br />
"/" return DIV;<br />
"(" return PAR_I;<br />
")" return PAR_D;<br />
. {printf("token erroneo\n");}<br />
Definición en Lex de patrones
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Comunicación Flex-<strong>Yacc</strong><br />
fich.l<br />
header<br />
fich.y<br />
lex fich.l<br />
yacc -d fich.y<br />
lex.yy.c<br />
fich.tab.h<br />
fich.tab.c<br />
cc lex.yy.c -c<br />
cc fich.tab.c -c<br />
lex.yy.o<br />
fich.tab.o<br />
gcc lex.yy.o fich.tab.o -o an_sintactico<br />
calc
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Reglas en YACC<br />
Formato BNF simplificado<br />
LI: LD acción;<br />
• LI: es un símbolo no-terminal del lenguaje<br />
• LD: secuencia de símbolos no-terminales y terminales<br />
Agrupar varias reglas del mismo no terminal :<br />
expr: expr ´+´ expr {....}<br />
| expr ´-´ expr {....}<br />
;<br />
Si se deja vacía es el regla de la palabra vacía<br />
sentencias : sentencias ´;´ sentencia {....}<br />
|<br />
;<br />
acción: { sentencias en C } (puede ser vacío)
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Declaraciones de reglas<br />
%token NUMERO, MAS, MENOS, POR, DIV, PAR_I, PAR_D<br />
%start expr /* simbolo axioma sentencial */<br />
%%<br />
expr: expr MAS term<br />
{printf("expr --> expr MAS term\n");}<br />
|expr MENOS term {printf("expr --> expr MENOS term\n");}<br />
|term<br />
{printf("expr --> term\n");}<br />
;<br />
term: term POR factor {printf("term --> term POR factor\n");}<br />
|term DIV factor {printf("term --> term DIV factor\n");}<br />
|factor<br />
{printf("term --> factor\n");}<br />
;<br />
factor: NUMERO<br />
{printf("factor--> NUMERO(%d)\n",$1);}<br />
|PAR_I expr PAR_D{printf("factor--> ( expr )\n");}<br />
;<br />
%%<br />
. . .
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo de análisis<br />
Gramática<br />
exprexpr + term<br />
exprterm<br />
termterm * factor<br />
termfactor<br />
factorNUMERO<br />
factor(expr)<br />
Ejemplo de ejecución<br />
• 5*(6+1)+3<br />
factor--> NUMERO (5)<br />
term --> factor<br />
factor--> NUMERO (6)<br />
term --> factor<br />
expr --> term<br />
factor--> NUMERO (1)<br />
term --> factor<br />
expr --> expr MAS term<br />
factor--> ( expr )<br />
term --> term POR factor<br />
expr --> term<br />
factor--> NUMERO (3)<br />
term --> factor<br />
expr --> expr MAS term
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Resolución de ambigüedad<br />
Por defecto, después de avisar, yacc resuelve<br />
• D/R: Desplazar prioridad sobre reducir<br />
• R/R: Reducir por la producción primera<br />
Preferible resolver los conflictos explícitamente<br />
• Criterios de prioridad
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Precedencia<br />
Especificación de precedencia<br />
• Asociatividad izquierda<br />
• %left op: x op y op z (x op y) op z<br />
• Asociatividad derecha<br />
• %right op: x op y op z x op (y op z)<br />
• No asociatividad<br />
• %nonassoc op: x op y op z INCORRECTO<br />
• Con otros operadores: los declarados en líneas posteriores<br />
más precedencia<br />
Ejemplo de asociación:<br />
% left ‘+’ ‘-’<br />
% left ‘*’ ‘/’<br />
• El último declarado es el que tiene más precedencia
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Gramática expresiones con prioridad<br />
%token NUMERO, MAS, POR, '(', ')'<br />
%left MAS<br />
%left POR<br />
%start S /* simbolo axioma sentencial */<br />
%%<br />
S: expr {printf("resultado: %d\n", $$); }<br />
expr: expr MAS expr<br />
|expr POR expr<br />
|'(' expr ')'<br />
| NUMERO<br />
%%
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Reglas: valores semánticos<br />
El valor semántico que proporciona yylex() se utiliza<br />
con los operadores $n<br />
expr: NAT ´+´ NAT {$$=$1+$3};<br />
• $$ identifica a la parte izquierda de la regla de producción<br />
• $n se corresponde con el n-ésimo símbolo de la parte<br />
derecha<br />
En la parte derecha cada componente se identifica<br />
por el orden que ocupa<br />
Por defecto se suponen valores enteros<br />
• Pueden declararse tipos complejos para los atributos
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo transporte atributos<br />
%%<br />
%token NUMERO, MAS, MENOS, POR, DIV, PAR_I, PAR_D<br />
%start S /* simbolo axioma sentencial */<br />
%%<br />
S: expr {printf("resultado: %d\n", $$); }<br />
expr: expr MAS term {$$=$1+$3;}<br />
|expr MENOS term {$$=$1-$3;}<br />
|term {$$=$1;}<br />
;<br />
term: term POR factor {$$=$1*$3;}<br />
| term DIV factor {$$=$1/$3;;}<br />
| factor {$$=$1;}<br />
;<br />
factor: NUMERO {$$=$1;}<br />
| PAR_I expr PAR_D {$$=$1;}<br />
;<br />
. . .<br />
Se agrega<br />
automáticamente
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Reglas: valores semánticos<br />
Los atributos de los tokens se obtienen en el<br />
análisis léxico: variable yylval<br />
• Es la comunicación lex-yacc<br />
• Representa el atributo del último token en el<br />
patrón reconocido<br />
• Por defecto es un atributo de tipo entero (int)<br />
• Ej.: …<br />
digito [0-9]<br />
%%<br />
Plantilla<br />
Lex:<br />
[ \t]+ ;<br />
"+" return MAS;<br />
"*“ return POR;<br />
{digito}+ {yylval=atoi(yytext); return NUMERO;}
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Sección de Declaraciones<br />
Directiva %union<br />
• Por defecto todos los terminales tienen un atributo<br />
de tipo entero, yyval, asignado en yylex()<br />
• Los valores semánticos se declaran en %union<br />
%union{<br />
int valent;<br />
char *cadena;<br />
tblPos *ptr;<br />
}
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Sección de Declaraciones<br />
Por defecto todos los terminales tienen un atributo<br />
de tipo entero, yyval, asignado en yylex()<br />
• Para utilizar otro tipo de atributo puede usarse la variable<br />
YYSTYPE<br />
#define YYSTYPE double<br />
Directiva %union<br />
• Da mayor flexibilidad, permitiendo definir varios atributos<br />
por símbolo y atributos alternativos<br />
• Declara los tipos posibles como una “unión” de C<br />
%union{<br />
int valent;<br />
char *cadena;<br />
tblPos *ptr;<br />
}
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Sección de Declaraciones<br />
Uso de un tipo declarado en %union<br />
• Se puede asociar a un terminal en su declaración<br />
%token NATURAL<br />
• Para un no terminal en su declaración<br />
%type NO_TERMINAL<br />
• En una producción específica<br />
expr: NAT ´+´ NAT {$$=$1+$3};<br />
En un símbolo terminal (análisis léxico)<br />
[-+]?{digito}+ { yyval.valent=atoi(yytext);<br />
return ENTERO;}
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Sección de Declaraciones<br />
%union{<br />
int valent;<br />
char *cadena;<br />
tblPos *ptr;<br />
}<br />
Uso de los tipos declarados en %union<br />
• Se puede asociar a un terminal en su declaración<br />
%token NATURAL<br />
• Para un no terminal en su declaración<br />
%type NO_TERMINAL<br />
• En una producción específica<br />
expr: NAT ´+´ NAT {$$=$1+$3};<br />
En un símbolo terminal (análisis léxico): hay que<br />
especificar<br />
[-+]?{digito}+ { yyval.valent=atoi(yytext);<br />
return NUMERO;}
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Almacenamiento de Atributos<br />
cima<br />
cima -1<br />
cima-2<br />
Técnica frecuente en analizadores ascendentes (LALR:yacc/bison,<br />
cup)<br />
Los atributos sintetizados se almacenan en una pila, y se evalúan<br />
al efectuar las reducciones: “pila semántica”:<br />
• Correspondencia con la pila de estados LR, asociados a los símbolos<br />
gramaticales<br />
Producción<br />
A::= XYZ<br />
Pila LR<br />
val<br />
... ...<br />
Z<br />
Y<br />
X<br />
Acciones<br />
semánticas<br />
A.s=f(X.x,Y.y,Z.z)<br />
Z.z<br />
Y.y<br />
X.x<br />
val [cima]<br />
val [cima –1]<br />
val [cima-2]<br />
int<br />
char<br />
%union{<br />
int val1;<br />
char val2;}<br />
%typeX<br />
%typeY
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Implementación en YACC<br />
Acciones embebidas:<br />
Las acciones pueden aparecer en el medio de una regla,<br />
ejecutándose antes de que la regla sea completamente<br />
evaluada.<br />
X: Y {acción} Z;<br />
Por ejemplo:<br />
X: Y {$$ := 2*$1;} z {$$ := $2+$3;}<br />
Establece el valor de x como 2*(valor de Y) + (valor de z)<br />
Pueden introducir conflictos en la resolución<br />
de la gramática!!!
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Infija-Postfija<br />
Traductor infija->postfija<br />
E<br />
E::=T E’<br />
E’::= op T {escribe op.lex} E’<br />
E’::=λ<br />
T::= num {escribe num.lex}<br />
¡No hay atributos!<br />
Acc. sem.: escribir código<br />
(esquema de traducción)<br />
Sentencia: 9-5+2<br />
Resultado: 9 5 – 2 +<br />
T E’<br />
num 1. e(‘9’) 3. e(‘-’)<br />
9<br />
operador T E’<br />
- 2. e(‘5’)<br />
num<br />
5. e(‘+’)<br />
5<br />
operador T E’<br />
+ 4. e(‘2’)<br />
num λ<br />
2
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Infija-Postfija<br />
digito [0-9]<br />
letra [a-zA-Z]<br />
%option noyywrap<br />
%%<br />
[ \t]+ ;<br />
"(" return PAR_I;<br />
")" return PAR_D;<br />
[-+] {strcpy(yylval.lex, yytext); return OP;}<br />
{letra}({digito}|{letra})*<br />
{strcpy(yylval.lex, yytext); return VAR;}<br />
{digito}+ {strcpy(yylval.lex, yytext); return NUMERO;}<br />
. {printf("token erroneo\n");}<br />
%%
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Infija-Postfija<br />
%union<br />
{<br />
char lex[50];<br />
}<br />
%token NUMERO, OP, PAR_I, PAR_D ASIG VAR<br />
%start E /* simbolo axioma sentencial */<br />
%%<br />
E: T E1 {}<br />
E1: OP T {printf("%s ",$1);} E1<br />
| {}<br />
;<br />
T: NUMERO {printf("%s ",$1);}<br />
| VAR {printf("%s ",$1);}<br />
|PAR_I E PAR_D {}<br />
%%
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Ejecución lex-yacc<br />
7-a+C-(4-b) 7 a - C + 4 b - -
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Declaración Tipos<br />
digito [0-9]<br />
letra [a-zA-Z]<br />
%%<br />
[ \t]+ ;<br />
"," return COMA;<br />
";" return PCOMA;<br />
"=“ return ASIG;<br />
[-+*/] return OP;<br />
"float" return FLOAT;<br />
"int" return INT;<br />
{letra}({digito}|{letra})* {strcpy(yylval.nombre,<br />
yytext); return VAR;}<br />
{digito}+ {yylval.valor=atoi(yytext);<br />
return NUMEROENT;}<br />
{digito}+(.{digito}+)<br />
{yylval.valor=atof(yytext);<br />
return NUMEROREAL;}<br />
. {printf("token erroneo\n");}
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Declaración Tipos<br />
%union<br />
{<br />
int valor;<br />
char nombre[50];<br />
char tipo[50];<br />
}<br />
%token VAR<br />
%token NUMEROENT, NUMEROREAL<br />
%token OP, ASIG, COMA, PCOMA FLOAT, INT<br />
%left MAS OP<br />
%type T L S E<br />
%start P /* simbolo axioma sentencial */<br />
...
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Declaración Tipos<br />
...<br />
P: T L PCOMA S {}<br />
;<br />
L: L COMA VAR {printf("ponerTS(%s,%s)\n",$3,$0);}<br />
|VAR<br />
{printf("ponerTS(%s,%s)\n",$1,$0);}<br />
;<br />
T: FLOAT {sprintf($$, "float");}<br />
|INT<br />
{sprintf($$, "int");}<br />
;<br />
S: VAR ASIG E {printf("comprobar tipo var %s\n", $1);}<br />
| {}<br />
;<br />
E: E OP E {/*reglas combinacion de tipos (promocion)*/}<br />
|VAR<br />
{printf("buscarTS(%s)\n", $1);/*asignar tipo<br />
de VAR a E0*/}<br />
|NUMEROENT {strcpy($$, "int");}<br />
|NUMEROREAL {strcpy($$, "real");}<br />
;
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Herencia de atributos, declaración tipos<br />
En la pila sólo hay atributos sintetizados<br />
Todos los atributos heredados están en posiciones predecibles en<br />
la pila (incluyendo el de la parte izquierda)<br />
cima<br />
cima -1<br />
cima -2<br />
cima -3<br />
símbolo val<br />
... ...<br />
VAR VAR.s<br />
COMA -<br />
L M 1 .s<br />
T T.s<br />
L->L COMA ID<br />
val [cima] $3<br />
val [cima–1] $2<br />
…<br />
val [cima-2] $1<br />
val [cima–3] $0
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Ejecución lex-yacc<br />
float a,b,c,d,e,f;<br />
a=4*c-2.0<br />
ponerTS(a,float)<br />
ponerTS(b,float)<br />
ponerTS(c,float)<br />
ponerTS(d,float)<br />
ponerTS(e,float)<br />
ponerTS(f,float)<br />
buscarTS(c)<br />
comprobar tipo var a
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Algunas opciones útiles<br />
Depuración del analizador: directiva<br />
YYDEBUG. Describe:<br />
• Cada una de las acciones realizadas<br />
(desplazamiento/reducción)<br />
• Tokens leídos<br />
• Estados visitados durante el análisis<br />
• Situación de la pila
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Algunas opciones útiles<br />
Ejemplo de<br />
depuración:<br />
((a))
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo salida depuración<br />
Ejemplo de depuración: ((a))<br />
Starting parse<br />
Entering state 0<br />
Reading a token: Next token is 40 ('(')<br />
Shifting token 40 ('('), Entering state 2<br />
Reading a token: Next token is 40 ('(')<br />
Shifting token 40 ('('), Entering state 2<br />
Reading a token: Next token is 97 ('a')<br />
Shifting token 97 ('a'), Entering state 1<br />
Reducing via rule 2 (line 12), 'a' -> S<br />
state stack now 0 2 2<br />
Entering state 3<br />
Reading a token: Next token is 41 (')')<br />
Shifting token 41 (')'), Entering state 4<br />
Reducing via rule 1 (line 11), '(' S ')' -> S<br />
state stack now 0 2<br />
Entering state 3
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo salida depuración<br />
Ejemplo de depuración: ((a))<br />
state stack now 0 2<br />
Entering state 3<br />
Reading a token: Next token is 41 (')')<br />
Shifting token 41 (')'), Entering state 4<br />
Reducing via rule 1 (line 11), '(' S ')' -> S<br />
state stack now 0<br />
Entering state 5<br />
Reading a token: Now at end of input.<br />
Shifting token 0 ($), Entering state 6<br />
Now at end of input.
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo activación depuración<br />
%{<br />
#include <br />
#define YYDEBUG 1<br />
%}<br />
%token NUMERO, MAS, MENOS, POR, DIV, PAR_I, PAR_D<br />
%start S /* simbolo axioma sentencial */<br />
%%<br />
... producciones<br />
%%<br />
main(int argc, char *argv[])<br />
{<br />
yydebug=1;<br />
...<br />
}<br />
Cuando yydebug no<br />
es 0: depuración
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Gramática expresiones ambigua<br />
%token NUMERO, MAS, POR, '(', ')'<br />
%start S /* simbolo axioma sentencial */<br />
%%<br />
S: expr {printf("resultado: %d\n", $$); }<br />
expr: expr MAS expr<br />
|expr POR expr<br />
|'(' expr ')'<br />
| NUMERO<br />
%%
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Información del analizador<br />
Opción “verbose” –v (descriptivo)<br />
• Descripción detallada de la tabla de análisis<br />
sintáctico LALR(1), y del autómata de<br />
reconocimiento<br />
• Características de la gramática: terminales no<br />
utilizados, símbolos no generativos, etc.<br />
• Notifica si hay conflictos desp/red y red/red<br />
home\> yacc –d –v ejemplo.y<br />
home\> ls<br />
home\> ejemplo.y ejemplo.tab.h<br />
ejemplo.tab.c ejemplo.output
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Gramática Sencilla<br />
Ejemplo: Lenguaje: {( n a ) n }, n≥0<br />
Gramática:<br />
Σ T ={(, a, )}, Σ T ={S}, S, P}<br />
P: S(S)<br />
Sa
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Salida yacc -v<br />
Grammar<br />
rule 1 S -> '(' S ')'<br />
rule 2 S -> 'a'<br />
Terminals, with rules where they appear<br />
$ (-1)<br />
'(' (40) 1<br />
')' (41) 1<br />
'a' (97) 2<br />
error (256)<br />
Nonterminals, with rules where they appear<br />
S (6)<br />
on left: 1 2, on right: 1
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ejemplo Salida yacc -v<br />
state 0<br />
'a' shift, and go to state 1<br />
'(' shift, and go to state 2<br />
S go to state 5<br />
state 1<br />
S -> 'a' . (rule 2)<br />
$default reduce using rule 2 (S)<br />
state 2<br />
S -> '(' . S ')' (rule 1)<br />
'a' shift, and go to state 1<br />
'(' shift, and go to state 2<br />
S go to state 3
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Análisis de ambigüedad con yacc<br />
Opción -v<br />
home\> yacc –v expresiones.y<br />
home\> expresiones.y contains 4<br />
shift/reduce conflicts<br />
home\> ls<br />
home\> expresiones.y expresiones_tab.c<br />
expresiones.output
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ambigüedad con yacc<br />
State 8 contains 2 shift/reduce conflicts.<br />
State 9 contains 2 shift/reduce conflicts.<br />
Grammar<br />
rule 1 S -> expr<br />
rule 2 expr -> expr MAS expr<br />
rule 3 expr -> expr POR expr<br />
rule 4 expr -> '(' expr ')'<br />
rule 5 expr -> NUMERO<br />
Terminals, with rules where they appear<br />
$ (-1)<br />
'(' (40) 4<br />
')' (41) 4<br />
NUMERO (258) 5<br />
MAS (259) 2<br />
POR (260) 3
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ambigüedad con yacc<br />
state 8<br />
expr -> expr . MAS expr (rule 2)<br />
expr -> expr MAS expr . (rule 2)<br />
expr -> expr . POR expr (rule 3)<br />
MAS shift, and go to state 5<br />
POR shift, and go to state 6<br />
MAS<br />
POR<br />
$default<br />
[reduce using rule 2 (expr)]<br />
[reduce using rule 2 (expr)]<br />
reduce using rule 2 (expr)
<strong>Yacc</strong>. Procesadores de Lenguaje II<br />
Ambigüedad con yacc<br />
state 9<br />
expr -> expr . MAS expr (rule 2)<br />
expr -> expr . POR expr (rule 3)<br />
expr -> expr POR expr . (rule 3)<br />
MAS shift, and go to state 5<br />
POR shift, and go to state 6<br />
MAS<br />
POR<br />
$default<br />
[reduce using rule 3 (expr)]<br />
[reduce using rule 3 (expr)]<br />
reduce using rule 3 (expr)