Está en la página 1de 29

Introduccón a

Flex - Bison
Objetivos 1ª parte


¿Qué son Flex y Bison?

Instalación.

Compilación.

Compilación - ejemplo.

Conceptos de lenguajes - PU5


¿Qué son Flex y Bison? Flex


Flex: “Fast Lexical Analyzer”.


Es un generador de analizadores léxicos (scanners).


Genera código fuente en C.


Distribuido bajo licencia BSD.


Disponible en: https://github.com/westes/flex/releases

Conceptos de lenguajes - PU5


¿Qué son Flex y Bison? Bison


Bison.


Es un generador de analizadores sintácticos (parsers).


Compatible con YACC (Yet Another Compiler-Compiler).


Genera código fuente en C, C++, Java.


Distribuido bajo licencia GPL.


Disponible en: https://www.gnu.org/software/bison/

Conceptos de lenguajes - PU5


Instalación


Requisito: se requiere un compilador de C (GCC por ejemplo).


Ambos son de instalación sencilla. Sólo hay que descargar el código fuente y
seguir los pasos de instalación.


Linux: se puede instalar desde los repositorios.

Conceptos de lenguajes - PU5


Compilación

Compilar un procesador de lenguajes utilizando [Flex+Bison]:

1. Escribir la especificación léxica (Flex) en un archivo con extensión “.l”.

2. Escribir la especificación sintáctica (Bison) en un archivo con extensión “.y”.

3. Compilar la especificación léxica utilizando Flex.

4. Compilar la especificación sintáctica utilizando Bison.

5. Compilar todo el código generado por 3 y 4 con el compilador de C.

6. Ejecutar el analizador léxico-sintáctico.

Conceptos de lenguajes - PU5


Compilación

Compilar un procesador de lenguajes utilizando [Flex+Bison]

Especificación Compilar con


Flex lex.yy.c
Flex (ER*)

Compilador a.out
de C

<file.tab.c>
Especificación Compilar con
Bison Y
Bison (GLC*) <file.tab.h>

*ER: expresiones regulares.


*GLC: gramática libre de contexto (BNF).

Conceptos de lenguajes - PU5


Compilación - ejemplo

Conceptos de lenguajes - PU5


Objetivos 2ª parte Flex


Más sobre Flex.

Analizador léxico.

Ejemplo.

ER (expresiones regulares).

El scanner como corutina.

Conceptos de lenguajes - PU5


Flex Más sobre Flex


Es un generador de analizadores léxicos (scanners).

Genera código fuente en C.

Especificación Compilar con


Flex lex.yy.c
Flex (ER)

Compiolador a.out
de C

<file.tab.c>
Especificación Compilar con
Bison Y
Bison (GLC) <file.tab.h>

Conceptos de lenguajes - PU5


Flex Más sobre Flex

¿Cómo está compuesto un archivo de Flex (“.l”)?

Un archivo Flex se compone de 3 partes:

Definiciones y opciones
%{
%}

Reglas: patrones (ER) y acciones


%%

%%

Código C: es el código C que se copia al escáner generado, por lo general pequeñas


rutinas relacionadas con el código en las acciones

main(int argc, char **argv)


{
...
}

Conceptos de lenguajes - PU5


Flex Analizador léxico

[Utilizando sólo la sección de reglas]


%%
"hola" { printf("SALUDO"); }
[0-9]+ { printf("NUMERO"); } “soloReglas.l”
%%

[Compilar y probar]
>> flex soloReglas.l
>> gcc lex.yy.c -lfl
>> ./a.out

Cuando se utiliza sólo la parte de las reglas, se llama plain Flex.

Conceptos de lenguajes - PU5


Flex Analizador léxico

[Utilizando sólo la sección de reglas]


%%
"hola" { printf("SALUDO"); }
[0-9]+ { printf("NUMERO"); } “soloReglas.l”
%%

Patrón Acción

Regla

Sintaxis de las reglas: <patrón> <acción>

Donde:

<patrón>: expresión regular.


<acción>: código C que se ejecuta.

Conceptos de lenguajes - PU5


Flex Analizador léxico

Utilizando las 3 secciones de Flex...

[Contador de caracteres]
/*DEFINICIONES*/
%{
int caracteres = 0;
%}

/*REGLAS*/
%% IMPORTANTE:
[a-zA-Z]+ { caracteres += strlen(yytext); }
\n { caracteres++; }
. { caracteres++; } Bloque reglas: SIN COMENTARIOS
%% yytext: patrón actual.
/*CODIGO C*/
yylex(): analizador léxico creado por Flex.
main(int argc, char **argv) Utilizar GCC + “lfl”.
{
yylex();
printf("%8d\n", caracteres);
}

^D (Ctrl+d) para mostrar resultado.


^D → end of file character (EOF) in Unix/Linux.

Conceptos de lenguajes - PU5


Flex Expresiones regulares

Algunos patrones (ER) válidos para las reglas de Flex:

Patrón Descripción
“x” Coincide únicamente con “x”.
. (punto) Coincide con cualquier carácter excepto nueva línea.
Coincide con “x” con “y” o con “z” (sólo una de las
[xyz]
tres).
Coincide con una “a” o con una “b” o con cualquier
[abj-o]
letra entre la “j” y la “o”.
Clase de caracteres negados. Coincide con cualquier
[^A-Z]
carácter menos excepto una letra mayúscula.
Cero o más ocurrencias de la expresión regular r (por
r*
ej: [0-9]*).
Una o más ocurrencias de la expresión regular r (por
r+
ej: [0-9]+).
r|s r o s (unión).
r? Cero o una ocurrencia de r.
r{3-6} De 3 a 6 ocurrencias de r.

Con “x” carácter de escape de ANSI-C (n, r, v, t, b,


\x
etc.).

Conceptos de lenguajes - PU5


Flex El scanner como corutina

%%
"+" { printf("MAS\n"); }
[0-9]+ { printf("NUMERO %s\n", yytext); }
\n { printf("SALTO LINEA\n"); }
[ \t] { }
. { printf("CARACTER DESCONOCIDO %s\n", yytext); }
%%

Ahora vamos a modificar nuestro escáner para que devuelva tokens para que un analizador
sintáctico los pueda utilizar...

%%
"+" { return SUMA; }
[0-9]+ { return NUMERO; }
[ \t] { /*ignorar espacios en blanco*/ }
%%

¿Qué significa esto?

Conceptos de lenguajes - PU5


Flex El scanner como corutina

Tokens y valores
Cuando un escáner de Flex devuelve un flujo de tokens, cada token tiene dos
partes: el token y el valor del token. Es decir, un token es representado por un
entero pequeño. La cantidad de los tokens es arbitraria, excepto que el token cero
siempre significa fin de archivo. Cuando Bison crea un analizador sintáctico
(parser), este asigna automáticamente los números de token a partir de 258 (esto
evita colisiones con tokens de caracteres literales -ASCII) y crea un archivo con
extensión “.h” con definiciones de los números de tokens.

Token en sí

Token

Valor del token

Haremos un analizador léxico y lo utilizaremos como corutina, “simulando”


lo que luego hará Bison.

Conceptos de lenguajes - PU5


Flex El scanner como corutina
%{
enum yytokentype
{
NUMERO = 258,
SUMA = 259,
EOL = 260
};
int yylval;
%}
%%
"+" { return SUMA; }
[0-9]+ { yylval = atoi(yytext); return NUMERO; }
\n { return EOL; }
[ \t] { }
. { printf("Carácter desconocido %c\n", *yytext); }
¿Qué hace este programa?
%%
main(int argc, char **argv)
{
int token;
while(token = yylex())
{
printf("%d", token);
if(token == NUMERO)
{
printf(" = %d\n", yylval);
}
else
{
printf("\n");
}
}
}

Definimos los números de los tokens en un enum C (“yytokentype”). Luego en la


variable entera “yylval”, se almacena el valor del token, un entero.

Conceptos de lenguajes - PU5


Objetivos 2ª parte Bison


Más sobre Bison.

Especificaciones.

Ejemplo (combinando Flex y Bison).

Conceptos de lenguajes - PU5


Bison Más sobre Bison


Es un generador de analizadores sintácticos (parsers).

Genera código fuente en C, C++, Java.

Especificación Compilar con


Flex lex.yy.c
Flex (ER)

Compiolador a.out
de C

<file.tab.c>
Especificación Compilar con
Bison Y
Bison (GLC) <file.tab.h>

Conceptos de lenguajes - PU5


Bison Más sobre Bison

¿Cómo está compuesto un archivo de Bison (“.y”)?

Un archivo Bison TIENE LAS MISMAS PARTES que un archivo de Flex:

Definiciones y opciones
%{
%}

Reglas: GLC* y acciones


%%

%%

Código C: es el código C que se copia al escáner generado, por lo general pequeñas


rutinas relacionadas con el código en las acciones

main(int argc, char **argv)


{
...
}

*GLC: gramática libre de contexto.

Conceptos de lenguajes - PU5


Bison Especificaciones

Descripción de las 3 partes de Bison:



Definiciones y opciones: se definen los símbolos léxicos que se utilizarán en la parte sintáctica.
Sintaxis: %token <nombre_del_terminal>
Son los mismos tokens que se definieron en el analizador léxico.

Por ejemplo: %token NUMERO


Reglas: gramática libre de contexto (BNF) y acciones.

Sintaxis basada en BNF:


<auxiliar> : <lado_derecho> { <accion> }
| <lado_derecho> { <accion> }
|…
;

Donde:
<lado_derecho>: cadena de terminales (devueltos por el analizador léxico) y auxiliares (o no terminales).
<accion>: código C que se ejecuta.

Por ejemplo:
expresion : expresion OPSUMA expresion
| CTE
;


Código C: es el código C que se copia al escáner generado, por lo general pequeñas rutinas relacionadas con el
código en las acciones

main(int argc, char **argv)


{
yyparse()
}

Conceptos de lenguajes - PU5


Bison Ejemplos

Problema: realizar un analizador sintáctico que reconozca la suma de dos enteros.

Utilizando BNF se tiene :

⟨expresion⟩::=NUMERO+ NUMERO

Luego la producción anterior en Bison :

expresion: /*cadena vacía*/


∣NUMERO OPSUMA NUMERO { $$ = $1 + $3; }
;

¿Qué representa esto?

Conceptos de lenguajes - PU5


Bison Ejemplos

Problema: realizar un analizador sintáctico que reconozca la suma de dos enteros.

expresion: /*cadena vacía*/


∣NUMERO OPSUMA NUMERO { $$ = $1 + $3; printf(''\n resultado = %d'', $$);}
;

¿Qué representan los símbolos: “$$”, “$1” y “$3”?

Cada símbolo en una regla de Bison tiene un valor. El valor del símbolo de la parte
izquierda (target) de la producción se representa por $$ en el código, mientras que
los símbolos del lado derecho de la producción están numerados $1, $2, $3, …
El valor de los tokens viene de la variable yylval (“NUMERO” y “OPSUMA”) y el
valor de los otros símbolos (“expresion” en nuestro caso) están determinados por
las reglas en el parser.

Conceptos de lenguajes - PU5


Bison Ejemplos

Problema: realizar un analizador sintáctico que reconozca la suma de dos enteros.

[Quedando el archivo “.y” → bisonReglasSumaSimple.y]


%{
int yylex();
int yyerror(char *);
#include <stdio.h>
%}
/* declare tokens */
%token NUMERO Recordar que cuando se
%token SUMA
%% compila un archivo Bison,
expresion: /* nada */
| NUMERO SUMA NUMERO { $$ = $1 + $3; printf("\n resultado = %d", $$);}
este arroja como resultado
; dos archivos: <file.tab.c>
%%
int main() y <file.tab.h>
{
yyparse();
}
int yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}

[Y el archivo “.l”]
/*flexReglasParaSumaEnteros.l*/
%{
#include "bisonReglasSumaSimple.tab.h" Ya no hace falta declarar los
%}
%% tokens, pues lo hace Bison y los
"+" { return SUMA; } almacena en el archivo
[0-9]+ { yylval = atoi(yytext); return NUMERO; } <file.tab.c>
[ \t] { }
. { printf("Carácter desconocido %c\n", *yytext); }
%%

Conceptos de lenguajes - PU5


Bison Ejemplos

Problema: realizar un analizador sintáctico que reconozca la suma de cualquier cantidad de


enteros.

Utilizando BNF se tiene:

⟨expresion⟩::=⟨expresion⟩+ NUMERO ∣ NUMERO

Luego BNF en Bison :

calcular : /*cadena vacía*/


∣ calcular expresion EOL { printf (' ' \n resultado=%d ' ' , $ 2); }
;

expresion:termino
∣ expresion OPSUMA termino { $$ = $1 + $3; }
;

termino : NUMERO ;

Conceptos de lenguajes - PU5


Bison Ejemplos

Problema: realizar un analizador sintáctico que reconozca la suma de dos enteros.

[Quedando el archivo “.y” → bisonReglasVariasSumas.y]


%{
int yylex();
int yyerror(char *);
#include <stdio.h>
%}
/* declare tokens */
%token NUMERO [Y el archivo “.l”]
%token SUMA
%token EOL %{
#include "bisonReglasVariasSuma.tab.h"
%% %}
calcular: /* nada */ %%
| calcular expresion EOL { printf(" = %d \n", $2); } "+" { return SUMA; }
; [0-9]+ { yylval = atoi(yytext); return NUMERO; }
[ \t] { }
expresion: termino \n {return EOL;}
| expresion SUMA termino { $$ = $1 + $3; } . { printf("Carácter desconocido %c\n", *yytext); }
; %%>

termino: NUMERO
;
%%
int main()
{
yyparse();
}
int yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}

Conceptos de lenguajes - PU5


Bison Ejemplos

¿Se puede ejecutar un archivo utilizando solamente Bison y no Flex?

Sí, si se puede. Aquí un ejemplo de código y de ejecución:

%{
int yylex();
int yyerror(char *);
#include <stdio.h>
%}

%% [Compilar y probar]
e: 'x'|
'y'|
'(' e '+' e ')'| >> bison soloReglas.y
'(' e '*' e ')' >> gcc soloReglas.tab.c -ly
%%
>> ./a.out
int yylex()
{char c = getchar();
if(c == '\n') return 0;
else
return c;}

void main()
{
printf("%i\n", yyparse());
}

Conceptos de lenguajes - PU5


Bibliografía


“flex & bison”; John R. Levine; O'REILLY – 2009.

Universitat Politècnica de València – UPV - Canal oficial de la UPV en
el que se publican vídeos institucionales, informativos y docentes
producidos por la Universitat Politècnica de València.
URL: https://www.youtube.com/user/valenciaupv

Conceptos de lenguajes - PU5

También podría gustarte