0
Índice
Introducción ............................................................................................................................ 1
Contenido ................................................................................................................................ 2
Lex........................................................................................................................................ 2
Yacc .................................................................................................................................. 2
Instalación .............................................................................................................................. 3
Error con Bison...................................................................................................................... 3
Formato del fichero de entrada en Flex .................................................................................... 4
Zona de definiciones ............................................................................................................. 4
Zona de reglas................................................................................................................... 4
Procedimientos del programador .................................................................................... 4
Creación de un analizador léxico ............................................................................................... 5
Formato de un programa Yacc................................................................................................... 6
Funcionamiento de Yacc........................................................................................................... 7
Un ejemplo sencillo en Bison..................................................................................................... 8
Ejemplo sencillo en Flex...........................................................................................................10
Compilación ............................................................................................................................11
Ejecución ................................................................................................................................12
1
Introducción
Al momento de hacer un compilador se investiga diferentes formas para hacerlo
desde la programación normal, y con normal me refiero a los diferentes lenguajes
de programación ya sea orientados a objetos o estructurados pero existen
herramienta que nos ayuda o nos facilita el trabajo de programar tantas líneas de
código, y unas de esas herramientas es Flex y Yacc, estas herramienta que se
mostrara en este documento desde su instalación, su uso y hasta un ejemplo.
2
Contenido
LEX
o Lex es un programa que permite generar analizadores léxicos (en inglés
scanners o lexers). Lex se utiliza comúnmente con el programa Yacc que se
utiliza para generar análisis sintáctico. Lex, escrito originalmente por Eric
Schmidt y Mike Lesk, es el analizador léxico estándar en los sistemas Unix,
y se incluye en el estándar de POSIX. Lex toma como entrada una
especificación de analizador léxico y devuelve como salida el código fuente
implementando el analizador léxico en C.
link para descargar Flex para Windows
http://gnuwin32.sourceforge.net/packages/flex.htm
YACC
o Yacc permite generar analizadores sintácticos. 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 intenta darle sentido a la entrada) basado en una gramática
analítica escrita en una notación similar a la BNF. Yacc genera el código
para el analizador sintáctico en el Lenguaje de programación C.
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. Link para descargar Bison para Windows
http://gnuwin32.sourceforge.net/packages/bison.htm
3
Instalación
La instalación de los dos programas se hace normalmente pero a la hora de
escoger el directorio donde se instalara por defecto es C:Program Files
(x86)GnuWin32 pero es recomendable hacerlo en el directorio c:, quedando en
C:GnuWin32 como en la siguiente figura, esto lo hacemos con los dos programas
para que estén juntos.
Error con Bison
Con Flex y Bison la instalación por defecto no da problema, pero con Bison al
momento de ejecutar un programa el error es:
El problema es que Bison no reconoce o no acepta los espacios en la dirección
donde se instaló que es la ruta por defecto, en la imagen se logra observar que no
encontró es el nombre ‘Files’ cuando el nombre de nuestra dirección es ‘program
files’, tomo el espacio como dos direcciones diferentes. Pero todo se soluciona
instalando en un directorio sin espacio.
4
Formato del fichero de entrada en Flex
El fichero de entrada de flex está compuesto de tres secciones, separadas por una
línea donde aparece únicamente un ‘%%’ en esta:
zona de definiciones
%%
zona de reglas
%%
procedimientos del programador
Zona de definiciones En esta parte del programa se pueden definir expresiones
regulares que se utilizaran posteriormente. También se pueden incluir todas las
definiciones en C que sean necesarias. Las definiciones en C, deberán ir
encerradas entre los delimitadores%{ y %}. Por ejemplo:
%{
#include "stdlib.h"
int x,y;
%}
Zona de reglas Cada regla está formada por una expresión regular seguida por
una serie de acciones (codificadas en C) que serán las que el analizador léxico
ejecute cuando encuentre una cadena de caracteres que encaje con la expresión
regular. Por ejemplo:
ab* {printf("hola");}
Procedimientos del programador En esta parte del programa se incluye el
programa C que el usuario haya diseñado. En el caso más sencillo, en el que solo
se desee generar un analizador léxico, el programa principal deberá incluir al
menos una llamada al procedimiento yylex. Es decir:
void main() {
yylex();
}
yylex es el procedimiento que actúa como analizador léxico y cuyo código C es
generado a partir de las especificaciones que aparecen en la zona de reglas. El
programa principal puede ser mucho más complejo e incluir todos los
procedimientos que se deseen.
5
Creación de un analizador léxico
Flex tiene su propio lenguaje, al que llamaremos Lex y que permite especificar la
estructura abstracta de un analizador léxico, tanto en lo que respecta a las
expresiones regulares como a la acción a tomar al encontrar un lexema que
encaje en cada una de ellas.
Los pasos para crear un analizador léxico con esta herramienta son:
1. Construir un fichero de texto en lenguaje Lex que contiene la estructura
abstracta del analizador.
2. Metacompilar el fichero anterior con Flex. Así se obtendrá un fichero fuente
en C estándar. Algunas veces hay que efectuar modificaciones directas en
este código, aunque las últimas versiones de Flex han disminuido al
máximo estas situaciones.
3. Compilar el fuente en C generado por Flex con un compilador C, con lo que
obtendremos un ejecutable.
Si ejecutamos prog.exe la aplicación se quedará esperando a que se le introduzca
la cadena de entrada por teclado para proceder a su partición en lexemas; el fin de
fichero se introduce pulsando las teclas Ctrl y Z.
Expresiones
regulares y
acciones
Flex Compilador de c
Analizador
léxico fuente
en C
Analizador
léxico
ejecutable
Prog.l Prog.exelex.yy.c
6
Formato de un programa Yacc
Un programa para YACC tiene la misma estructura que un programa para LEX.
Es decir, tiene tres partes, con el mismo significado que en el caso anterior. La
diferencia principal está en la sección de reglas, que en vez de expresiones
regulares contiene las reglas de la gramática:
<Sección de definiciones>
%%
<Sección de reglas>
%%
<Sección de rutinas>
1. En la primera parte, la sección de definiciones, se pueden incluir declaraciones
en C, de la misma forma que se hacıa con LEX.
Además, es necesario realizar algunas definiciones que necesita conocer el
parser, para ello se utilizan palabras reservadas (todas comienzan por %).
 La definición del símbolo inicial de la gramática se realiza utilizando la
palabra reservada %start. Por ejemplo:
%start programa
 La definición de los símbolos terminales de la gramática se realiza
utilizando la palabra reservada %token. Por ejemplo:
%token NUMERO IDENTIFICADOR
2. En la segunda parte, la zona de las reglas, se describe la G.I.C. (Gramáticas
Independientes del Contexto) siguiendo la siguiente notación:
 El símbolo: se utiliza para separar la parte izquierda de una producción de
la parte derecha.
 Todas las reglas que tienen la misma parte izquierda se pueden separar
con el símbolo |, sin necesidad de repetir la parte izquierda. Una colección
de producciones con la misma parte izquierda debe acabar con ;. Por
ejemplo, las siguientes definiciones son equivalentes:
lista var: lista var var lista var: lista var var
lista var: var | var
; ;
Los símbolos de la gramática que no hayan sido declarados como tokens, se
consideraran símbolos no terminales, excepto los caracteres simples, encerrados
entre comillas que también se consideran símbolos terminales. Por ejemplo: ’+’,’*’.
3. En la tercera parte del programa, procedimientos del programador es necesario,
como mínimo llamar al procedimiento yyparse(). También es necesario que el
programador defina la rutina yyerror. Esta rutina ser´ a llamada por el analizador
7
cada vez que encuentre un error sintáctico. Un ejemplo de definición de yyerror
puede ser:
void yyerror(char *s) {
printf("%s"n,s);
}
Funcionamiento de Yacc
Programa fuente
enYacc (.y)
y.tab.cCompiladorde Yacc
(Yacc, Bison)
y.tab.c a.outCompiladorde C
(gcc)
Ficherode
entrada
Accionesa.out
yylex()
yyerror()
8
Un ejemplo sencillo Bison
Vamos a ver un ejemplo sencillo en Bison para una gramática como la que sigue:
instrucciones -> instrucciones NL instrucción | instrucción
instrucción -> IDENTIFICADOR OPAS expresión
expresión -> término | expresión MÁS término
término -> IDENTIFICADOR | CONSTENTERA | APAR expresión CPAR
dónde:
IDENTIFICADOR: típico identificador en
cualquier lenguaje de programación
CONSTENTERA: entero sin signo
OPAS: :=
MÁS: +
APAR: (
CPAR: )
NL: n
9
Abrimos un bloc de notas y pegamos el siguiente código.
Guardamos el archivo con el nombre lex2.l y cambiarle donde dice tipo a “Todos
los archivos (*.*)”
#include <stdio.h>
%}
%tokenIDENTIFICADOROPASCONSTENTERA NLMASAPARCPAR
%start instrucciones
%%
instrucciones:instruccionesinstruccion
| instruccion
;
instruccion:IDENTIFICADOROPASexpresionNL
;
expresion:termino
| expresionMAStermino
;
termino:IDENTIFICADOR
| CONSTENTERA
| APARexpresionCPAR
;
%%
yyerror(s)
char *s;
{
printf ("%sn",s);
}
main()
{
yyparse();
}
10
Ejemplo sencillo Flex
Abrimos un bloc de notas y pegamos el siguiente código.
Guardamos el archivo con el nombre sin2.y y cambiarle donde dice tipo a “Todos
los archivos (*.*)”.
%{
#include <stdio.h>
#include "sin2.tab.h"
%}
separador ([ t""])+
letra [a-zA-Z]
digito [0-9]
identificador {letra}({letra}|{digito})*
constEntera {digito}({digito})*
%%
{separador} {/* omitir */}
{constEntera} {return (CONSTENTERA);}
":=" {return (OPAS);}
"+" {return (MAS);}
{identificador} {return (IDENTIFICADOR);}
"(" {return (APAR);}
")" {return (CPAR);}
n {return (NL);}
. ECHO;
%%
11
Compilación
Estos archivos estarán en la ruta de instalación de Bison o Flex en la carpeta bin.
C:GnuWin32bin
Para compilar el ejemplo sin2.y necesitamos abrir el cmd en modo administrador y
llegar a la ruta donde está el bin. Situado ahí escribimos el siguiente comando.
>bison –d sin2.y
El parámetro –d, crea el fichero t.tab.h, que contiene los identificadores de los
tokens de bison usados por flex
El fichero sin2.tab.h es creado automáticamente por Bison, si usamos la opción –d
al ejecutarlo, y contiene básicamente macros para definir como números los
identificadores de tokens de la gramática de Bison que se van a leer en Flex (los
CONSTENTERA, OPAS, MAS etc.).
Estando ahí hacemos escribimos el siguiente comando para compilar lex2.l
>flex lex2.l
Estos comandos nos generan los 3 archivos que utilizaremos.
12
Ejecución
Para la ejecución necesitaremos el Dev-Cpp pero antes copiaremos el archivo
libfl.a que se encuentra en la dirección C:GnuWin32lib y pegarlo en C:Dev-
Cpplib
Copiamos los 3 archivos generados anteriormente y lo pegamos C:Dev-Cppbin,
pero también necesitaremos llegar con el cmd en modo administrador para
ejecutar el siguiente comando
C:Dev-Cppbin>gcc sin2.tab.c lex.yy.c -lfl -o programa
En la siguiente figura se observa todos los pasos de la compilación de los archivos
sin2.y y lex2.l hasta el ejecutable.
Estos pasos generan un ejecutable llamado programa que nos permite comprobar
qué palabras pertenecen al lenguaje generado por la gramática descrita en el
fichero Bison. Si se compilan los ejemplos dados en la sección anterior y se
ejecuta el fichero salida, podemos escribir una expresión válida:
var1 := var2 + 5
y cuando pulsemos enter Bison no dará ningún error, señal de que la palabra
pertenece al lenguaje de las expresiones correctas, sin embargo si escribimos
algo que no es una expresión válida:
var1 := var2 ++ 34
al pulsar enter Bison nos da un “parse error” (o un error de sintaxis) que nos dice
que la palabra no pertenece al lenguaje.

Procedimiento Para Utilizar Flex Y Bison

  • 1.
    0 Índice Introducción ............................................................................................................................ 1 Contenido................................................................................................................................ 2 Lex........................................................................................................................................ 2 Yacc .................................................................................................................................. 2 Instalación .............................................................................................................................. 3 Error con Bison...................................................................................................................... 3 Formato del fichero de entrada en Flex .................................................................................... 4 Zona de definiciones ............................................................................................................. 4 Zona de reglas................................................................................................................... 4 Procedimientos del programador .................................................................................... 4 Creación de un analizador léxico ............................................................................................... 5 Formato de un programa Yacc................................................................................................... 6 Funcionamiento de Yacc........................................................................................................... 7 Un ejemplo sencillo en Bison..................................................................................................... 8 Ejemplo sencillo en Flex...........................................................................................................10 Compilación ............................................................................................................................11 Ejecución ................................................................................................................................12
  • 2.
    1 Introducción Al momento dehacer un compilador se investiga diferentes formas para hacerlo desde la programación normal, y con normal me refiero a los diferentes lenguajes de programación ya sea orientados a objetos o estructurados pero existen herramienta que nos ayuda o nos facilita el trabajo de programar tantas líneas de código, y unas de esas herramientas es Flex y Yacc, estas herramienta que se mostrara en este documento desde su instalación, su uso y hasta un ejemplo.
  • 3.
    2 Contenido LEX o Lex esun programa que permite generar analizadores léxicos (en inglés scanners o lexers). Lex se utiliza comúnmente con el programa Yacc que se utiliza para generar análisis sintáctico. Lex, escrito originalmente por Eric Schmidt y Mike Lesk, es el analizador léxico estándar en los sistemas Unix, y se incluye en el estándar de POSIX. Lex toma como entrada una especificación de analizador léxico y devuelve como salida el código fuente implementando el analizador léxico en C. link para descargar Flex para Windows http://gnuwin32.sourceforge.net/packages/flex.htm YACC o Yacc permite generar analizadores sintácticos. 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 intenta darle sentido a la entrada) basado en una gramática analítica escrita en una notación similar a la BNF. Yacc genera el código para el analizador sintáctico en el Lenguaje de programación C. 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. Link para descargar Bison para Windows http://gnuwin32.sourceforge.net/packages/bison.htm
  • 4.
    3 Instalación La instalación delos dos programas se hace normalmente pero a la hora de escoger el directorio donde se instalara por defecto es C:Program Files (x86)GnuWin32 pero es recomendable hacerlo en el directorio c:, quedando en C:GnuWin32 como en la siguiente figura, esto lo hacemos con los dos programas para que estén juntos. Error con Bison Con Flex y Bison la instalación por defecto no da problema, pero con Bison al momento de ejecutar un programa el error es: El problema es que Bison no reconoce o no acepta los espacios en la dirección donde se instaló que es la ruta por defecto, en la imagen se logra observar que no encontró es el nombre ‘Files’ cuando el nombre de nuestra dirección es ‘program files’, tomo el espacio como dos direcciones diferentes. Pero todo se soluciona instalando en un directorio sin espacio.
  • 5.
    4 Formato del ficherode entrada en Flex El fichero de entrada de flex está compuesto de tres secciones, separadas por una línea donde aparece únicamente un ‘%%’ en esta: zona de definiciones %% zona de reglas %% procedimientos del programador Zona de definiciones En esta parte del programa se pueden definir expresiones regulares que se utilizaran posteriormente. También se pueden incluir todas las definiciones en C que sean necesarias. Las definiciones en C, deberán ir encerradas entre los delimitadores%{ y %}. Por ejemplo: %{ #include "stdlib.h" int x,y; %} Zona de reglas Cada regla está formada por una expresión regular seguida por una serie de acciones (codificadas en C) que serán las que el analizador léxico ejecute cuando encuentre una cadena de caracteres que encaje con la expresión regular. Por ejemplo: ab* {printf("hola");} Procedimientos del programador En esta parte del programa se incluye el programa C que el usuario haya diseñado. En el caso más sencillo, en el que solo se desee generar un analizador léxico, el programa principal deberá incluir al menos una llamada al procedimiento yylex. Es decir: void main() { yylex(); } yylex es el procedimiento que actúa como analizador léxico y cuyo código C es generado a partir de las especificaciones que aparecen en la zona de reglas. El programa principal puede ser mucho más complejo e incluir todos los procedimientos que se deseen.
  • 6.
    5 Creación de unanalizador léxico Flex tiene su propio lenguaje, al que llamaremos Lex y que permite especificar la estructura abstracta de un analizador léxico, tanto en lo que respecta a las expresiones regulares como a la acción a tomar al encontrar un lexema que encaje en cada una de ellas. Los pasos para crear un analizador léxico con esta herramienta son: 1. Construir un fichero de texto en lenguaje Lex que contiene la estructura abstracta del analizador. 2. Metacompilar el fichero anterior con Flex. Así se obtendrá un fichero fuente en C estándar. Algunas veces hay que efectuar modificaciones directas en este código, aunque las últimas versiones de Flex han disminuido al máximo estas situaciones. 3. Compilar el fuente en C generado por Flex con un compilador C, con lo que obtendremos un ejecutable. Si ejecutamos prog.exe la aplicación se quedará esperando a que se le introduzca la cadena de entrada por teclado para proceder a su partición en lexemas; el fin de fichero se introduce pulsando las teclas Ctrl y Z. Expresiones regulares y acciones Flex Compilador de c Analizador léxico fuente en C Analizador léxico ejecutable Prog.l Prog.exelex.yy.c
  • 7.
    6 Formato de unprograma Yacc Un programa para YACC tiene la misma estructura que un programa para LEX. Es decir, tiene tres partes, con el mismo significado que en el caso anterior. La diferencia principal está en la sección de reglas, que en vez de expresiones regulares contiene las reglas de la gramática: <Sección de definiciones> %% <Sección de reglas> %% <Sección de rutinas> 1. En la primera parte, la sección de definiciones, se pueden incluir declaraciones en C, de la misma forma que se hacıa con LEX. Además, es necesario realizar algunas definiciones que necesita conocer el parser, para ello se utilizan palabras reservadas (todas comienzan por %).  La definición del símbolo inicial de la gramática se realiza utilizando la palabra reservada %start. Por ejemplo: %start programa  La definición de los símbolos terminales de la gramática se realiza utilizando la palabra reservada %token. Por ejemplo: %token NUMERO IDENTIFICADOR 2. En la segunda parte, la zona de las reglas, se describe la G.I.C. (Gramáticas Independientes del Contexto) siguiendo la siguiente notación:  El símbolo: se utiliza para separar la parte izquierda de una producción de la parte derecha.  Todas las reglas que tienen la misma parte izquierda se pueden separar con el símbolo |, sin necesidad de repetir la parte izquierda. Una colección de producciones con la misma parte izquierda debe acabar con ;. Por ejemplo, las siguientes definiciones son equivalentes: lista var: lista var var lista var: lista var var lista var: var | var ; ; Los símbolos de la gramática que no hayan sido declarados como tokens, se consideraran símbolos no terminales, excepto los caracteres simples, encerrados entre comillas que también se consideran símbolos terminales. Por ejemplo: ’+’,’*’. 3. En la tercera parte del programa, procedimientos del programador es necesario, como mínimo llamar al procedimiento yyparse(). También es necesario que el programador defina la rutina yyerror. Esta rutina ser´ a llamada por el analizador
  • 8.
    7 cada vez queencuentre un error sintáctico. Un ejemplo de definición de yyerror puede ser: void yyerror(char *s) { printf("%s"n,s); } Funcionamiento de Yacc Programa fuente enYacc (.y) y.tab.cCompiladorde Yacc (Yacc, Bison) y.tab.c a.outCompiladorde C (gcc) Ficherode entrada Accionesa.out yylex() yyerror()
  • 9.
    8 Un ejemplo sencilloBison Vamos a ver un ejemplo sencillo en Bison para una gramática como la que sigue: instrucciones -> instrucciones NL instrucción | instrucción instrucción -> IDENTIFICADOR OPAS expresión expresión -> término | expresión MÁS término término -> IDENTIFICADOR | CONSTENTERA | APAR expresión CPAR dónde: IDENTIFICADOR: típico identificador en cualquier lenguaje de programación CONSTENTERA: entero sin signo OPAS: := MÁS: + APAR: ( CPAR: ) NL: n
  • 10.
    9 Abrimos un blocde notas y pegamos el siguiente código. Guardamos el archivo con el nombre lex2.l y cambiarle donde dice tipo a “Todos los archivos (*.*)” #include <stdio.h> %} %tokenIDENTIFICADOROPASCONSTENTERA NLMASAPARCPAR %start instrucciones %% instrucciones:instruccionesinstruccion | instruccion ; instruccion:IDENTIFICADOROPASexpresionNL ; expresion:termino | expresionMAStermino ; termino:IDENTIFICADOR | CONSTENTERA | APARexpresionCPAR ; %% yyerror(s) char *s; { printf ("%sn",s); } main() { yyparse(); }
  • 11.
    10 Ejemplo sencillo Flex Abrimosun bloc de notas y pegamos el siguiente código. Guardamos el archivo con el nombre sin2.y y cambiarle donde dice tipo a “Todos los archivos (*.*)”. %{ #include <stdio.h> #include "sin2.tab.h" %} separador ([ t""])+ letra [a-zA-Z] digito [0-9] identificador {letra}({letra}|{digito})* constEntera {digito}({digito})* %% {separador} {/* omitir */} {constEntera} {return (CONSTENTERA);} ":=" {return (OPAS);} "+" {return (MAS);} {identificador} {return (IDENTIFICADOR);} "(" {return (APAR);} ")" {return (CPAR);} n {return (NL);} . ECHO; %%
  • 12.
    11 Compilación Estos archivos estaránen la ruta de instalación de Bison o Flex en la carpeta bin. C:GnuWin32bin Para compilar el ejemplo sin2.y necesitamos abrir el cmd en modo administrador y llegar a la ruta donde está el bin. Situado ahí escribimos el siguiente comando. >bison –d sin2.y El parámetro –d, crea el fichero t.tab.h, que contiene los identificadores de los tokens de bison usados por flex El fichero sin2.tab.h es creado automáticamente por Bison, si usamos la opción –d al ejecutarlo, y contiene básicamente macros para definir como números los identificadores de tokens de la gramática de Bison que se van a leer en Flex (los CONSTENTERA, OPAS, MAS etc.). Estando ahí hacemos escribimos el siguiente comando para compilar lex2.l >flex lex2.l Estos comandos nos generan los 3 archivos que utilizaremos.
  • 13.
    12 Ejecución Para la ejecuciónnecesitaremos el Dev-Cpp pero antes copiaremos el archivo libfl.a que se encuentra en la dirección C:GnuWin32lib y pegarlo en C:Dev- Cpplib Copiamos los 3 archivos generados anteriormente y lo pegamos C:Dev-Cppbin, pero también necesitaremos llegar con el cmd en modo administrador para ejecutar el siguiente comando C:Dev-Cppbin>gcc sin2.tab.c lex.yy.c -lfl -o programa En la siguiente figura se observa todos los pasos de la compilación de los archivos sin2.y y lex2.l hasta el ejecutable. Estos pasos generan un ejecutable llamado programa que nos permite comprobar qué palabras pertenecen al lenguaje generado por la gramática descrita en el fichero Bison. Si se compilan los ejemplos dados en la sección anterior y se ejecuta el fichero salida, podemos escribir una expresión válida: var1 := var2 + 5 y cuando pulsemos enter Bison no dará ningún error, señal de que la palabra pertenece al lenguaje de las expresiones correctas, sin embargo si escribimos algo que no es una expresión válida: var1 := var2 ++ 34 al pulsar enter Bison nos da un “parse error” (o un error de sintaxis) que nos dice que la palabra no pertenece al lenguaje.