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

El generador de analizadores sintcticos yacc.

Hemos visto cmo el anlisis lxico facilita la tarea de reconocer los elementos de un lenguaje uno a uno. A partir de ahora, vamos a centrarnos en el anlisis sintctico, que nos permitir averiguar si un fichero de entrada cualquiera respeta las reglas de una gramtica concreta. Para el tema del anlisis sintctico vamos a utilizar la herramienta yacc (Yet Another Compiler Compiler).

1. Funcionamiento de yacc
Igual que suceda 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 sintctico. Sin embargo, un analizador sintctico de yacc no puede funcionar por s solo, sino que necesita un analizador lxico externo para funcionar. Dicho de otra manera, el fuente en C que genera yacc contiene llamadas a una funcin yylex() que debe estar definida y debe devolver el tipo de lexema encontrado. Adems, es necesario incorporar tambin una funcin yyerror(), que ser invocada cuando el analizador sintctico encuentre un smbolo que no encaja en la gramtica.

2. El lenguaje Yacc
2.1. Esquema general

Un programa fuente de Yacc se parece bastante a uno de lex. La diferencia principal est en la seccin de reglas, que en vez de expresiones regulares contiene las reglas de la gramtica: De estas tres secciones, slo la segunda es obligatoria, y no debe estar vaca (ntese que en lex, las tres secciones pueden estar vacas). La seccin de declaraciones puede incluir varias cosas, tal y como ocurra en lex, pero ahora su funcin principal no es definir expresiones regulares, sino declarar los smbolos terminales de la gramtica mediante la directriz Todo lo que no sea un terminal, ser considerado un smbolo no terminal, y por tanto debe haber un a regla para l:
%token IF,ELSE,LLAVE_AB,LLAVE_CE,IDENT

La seccin de reglas contiene la gramtica en s. Componentes es una combinacin de terminales y no terminales que describe al no terminal de la izquierda de la regla:
no_terminal: componentes {acciones en C}

La seccin de rutinas tiene la misma funcin 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 compilacin.

<seccin de definiciones>
%%

<seccin de reglas>
%%

<seccin de rutinas> Yacc genera una funcin llamada yyparse() que contiene el analizador sintctico. Esta funcin se comporta como una mquina de estados cuya misin es intentar reducir todo el fichero de entrada al smbolo inicial de la gramtica (el primero que se haya definido). Si yacc lo consigue, el analizador sintctico volver sin error, y en caso contrario, se invocar a la funcin yyerror(), que debe estar definida tambin en algn sitio. 2.2. Seccin de reglas Una regla de yacc es parecida a una de lex, pero en vez de un patrn regular, especifica una regla de la gramtica. Las reglas deben estar dadas de forma que la parte izquierda conste de un nico smbolo no terminal, y la parte derecha indique la combinacin de terminales y no terminales de que puede estar compuesto. Adems, toda regla debe incluir una accin en C que se ejecutar en cuanto yacc consiga encontrar los componentes del smbolo resultado: smbolo_result: componentes accin_en_C El smbolo resultado debe estar situado en la primera posicin de la lnea; es decir, que no puede haber espacios antes del smbolo resultado. Los componentes son una combinacin de terminales y no terminales separados por espacios en blanco. La accin puede ser una sola sentencia de C, o una sentencia compuesta, encerrada entre llaves {}. 2.3. Cdigo C en un programa lex Igual que en lex, muchas veces es til incluir cdigo en C dentro de un programa en yacc. Es normal utilizar esta posibilidad para incluir las funciones main() e yyerror() en el mismo fichero. La funcin yylex(), sin embargo, suele proporcionarse en un mdulo aparte, generado por lex, que se enlaza en la fase final de la compilacin. Normalmente, el cdigo C se introduce en la seccin de declaraciones, o bien en la de rutinas: En la seccin de declaraciones, entre una lnea %{ y una lnea %} (ntese que no es }%). Este cdigo ser externo y se situar antes de la funcin yyparse() en el fichero y.tab.c. En la seccin de rutinas todo lo que haya debe ser cdigo C, que ser externo y posterior a la funcin yyparse().

3. Ejemplo
Construir un analizador sintctico que reconozca la palabra Hola, en maysculas o minsculas, y con un nmero arbitrario de letras o:

%token H,O,L,A %{ #define H 257 #define O 258 #define L 259 #define A 260 int yylex() { char carac=getchar(); switch(carac) { case 'H': case 'h': return H; case 'O': case 'o': return O; case 'L': case 'l': return L; case 'A': case 'a': return A; } return -1; } int yyerror() { printf("La expresin de la entrada NO forma parte del lenguaje reconocido\n"); return 0; } %} %% hola: H letra_o L A {printf("La expresin introducida es parte del lenguaje reconocido\n");}

letra_o: O | letra_o O ; %% int main() { yyparse(); return 0; }

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