3 - Universidad de La Serena

Anuncio
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
Introducción para los laboratorios y actividades relacionadas.
Flex y Bison son las herramientas desarrolladas en el proyecto GNU (Free Software
Foundation) equivalentes a lex y yacc en el sistema operativo UNIX®. Están asociadas al
lenguaje C, aunque flex puede también generar su salida en el lenguaje C++.
GNU es software libre: no significa que sea gratis o no (normalmente sí), sino que eres libre para
usarlo, modificarlo y distribuirlo, pero bajo ciertas normas, que en este caso, están recogidas
básicamente en la GNU General Public License, que deberían conocerlas.
Equivalencia de la notación vista en teoría y la de Flex
El alfabeto Σ que maneja Flex es el compuesto por los caracteres manejables por el sistema,
p.ej., todos los símbolos del código ASCII. En las prácticas trabajaremos con letras (las
mayúsculas y las minúsculas son distintos símbolos del alfabeto), números y signos de
puntuación.
Diseñar un programa con Flex que elimine los caracteres blancos del final de cada línea del texto
de entrada y reduzca a un solo blanco cualquier grupo de blancos del interior de cada línea (se
entiende por blanco el espacio en blanco y el carácter de tabulación).
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 1
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
Ejemplos:
/*
* Reemplazar la cadena "username" desde la entrada standard
* por el "login" del usuario.
*/
%{
#include <unistd.h>
%}
%%
username
%%
printf("%s\n", getlogin());
main()
{
yylex();
}
int yywrap(){return 1;}
/* encuentra la palabra más larga introducida desde la entrada standard */
%{
#include <strings.h>
int longest = 0;
char longword[60];
%}
%%
[a-zA-Z]+ { if (yyleng > longest) {
longest = yyleng;
strcpy (longword, yytext);
}
}
.
|
\n
;
%%
int main (void) {
yylex ();
printf ("La palabra mas larga es \"%s\", con %d caracteres.\n",
longword, longest);
return 0;
}
yywrap(){return 1;}
/* reconoce dígitos */
DIGITO [0-9]
%%
{DIGITO} {printf("Esto es un digito %s \n", yytext);}
%%
main(){yylex();}
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 2
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
yywrap(){return 1;}
/* reconoce números reales */
DIGITO
[0-9]
NATURAL
{DIGITO}+
DECIMAL
{NATURAL}?\.{NATURAL}
SIGNO
[+-]?
EXPONENTE [eE]{SIGNO}{NATURAL}
MANTISA
{SIGNO}({NATURAL}|{DECIMAL})
%%
{MANTISA}{EXPONENTE} {printf("Esto es un número real %s\n", yytext);}
%%
main(){yylex();}
yywrap(){return 1;}
%{#include <stdio.h>
#include <stdlib.h>
%}
DIGITO [0-9]
%%
{DIGITO}+ return atoi(yytext);
%%
void main()
{
/* calcula la media de los números introducidos por el teclado */
int val, total=0, n=0;
while ((val=yylex())> 0)
{
total += val; n++;
}
if (n>0) printf("La media es %d\n", total/n);
}
yywrap() {return 1;}
/* cifrado de Cesar: reemplaza un caracter con el que le sigue tres */
/* letras después, desplazando la Z (OR z) sobre el inicio del
*/
/* alfabeto[A-Z} (OR [a-z])
*/
%%
[a-z]
{ char ch = yytext[0];
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 3
Teoría de Autómatas y Lenguajes Formales
}
[A-Z]
}
%%
LEX‐ BISON
Dr. Eric Jeltsch F.
ch += 3;
if (ch > 'z') ch -= ('z'+1-'a');
printf ("%c", ch);
{ char ch = yytext[0];
ch += 3;
if (ch > 'Z') ch -= ('Z'+1-'A');
printf ("%c", ch);
main()
{
yylex();
}
int yywrap(){return 1;}
/* cifrado de Cesar: reemplaza un caracter con el que le sigue tres */
/* letras después, desplazando la Z (OR z) sobre el inicio del
*/
/* alfabeto[A-Z} (OR [a-z])
*/
%%
[a-wA-W]
[xyzXYZ]
%%
printf ("%c", yytext[0]+3);
printf ("%c", yytext[0]-23);
main()
{
yylex();
}
int yywrap(){return 1;}
/* L2 es el conjunto de palabras en el alfabeto {a, ..., z} */
/* conteniendo un numero par de a's y de b's.
*/
/* Saca por pantalla las palabras en L2 y reemplaza por
*/
/* puntos las demás.
*/
C [c-z]*
L2 ({C}|a{C}a|b{C}b|(a{C}b|b{C}a)(a{C}a|b{C}b)*(a{C}b|b{C}a))*
%%
{L2}
.
\n
ECHO;
printf(".");
ECHO;
%%
main() {yylex();}
yywrap() {return 1;}
/* En un texto, cuanta el numero de palabras, de frases, calcula */
/* la longitud media de una palabra y el numero medio de palabras */
/* por frase.
*/
int ContadorPalabras=0, ContadorFrase=0, LongitudPalabra=0;
%%
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 4
Teoría de Autómatas y Lenguajes Formales
[A-Za-z]
[.?!]+
.
\n
LEX‐ BISON
Dr. Eric Jeltsch F.
{ContadorPalabras++; LongitudPalabra+= yyleng;}
{ContadorFrase++;}
|
;
%%
main() {yylex();}
yywrap()
{
printf("numero de palabras: %d\n", ContadorPalabras);
if (ContadorPalabras != 0)
printf("longitud media de una palabra: %e\n",
LongitudPalabra/(float)ContadorPalabras);
printf("numero de frases: %d\n", ContadorFrase);
if (ContadorFrase != 0)
printf("numero medio de palabras en una frase: %g\n",
ContadorPalabras/(float)ContadorFrase);
return(1);
}
/* Supresión de comentarios en un programa Pascal. Las delimitadores */
/* son { } y (* *). Si los delimitadores aparecen en el interior de */
/* una cadena delimitada por ' ', no se trata de comentarios.
*/
/* usando condiciones de arranque inclusivas */
%s
COM1 COM2 STRING
%%
<STRING>'
<STRING>.|\n|"(*"|\{
<COM1>\}
<COM1>.|\n|"(*"|\{
<COM2>"*)"
<COM2>.|\n|"(*"|\{
'
\{
"(*"
{BEGIN 0, ECHO;}
ECHO;
BEGIN 0;
;
BEGIN 0;
;
{BEGIN STRING, ECHO;}
BEGIN COM1;
BEGIN COM2;
%%
main() {yylex();}
yywrap() {return 1;}
/* Lee e interpreta números romanos.
*/
/* Fijarse, por ejemplo, que si lee un I, no aplica la acción hasta no
estar seguro de que el siguiente simbolo no es V o X
*/
WS
%%
I
IV
[ \t]+
int total=0;
total += 1;
total += 4;
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 5
Teoría de Autómatas y Lenguajes Formales
V
IX
X
XL
L
XC
C
CD
D
CM
M
total
total
total
total
total
total
total
total
total
total
total
+=
+=
+=
+=
+=
+=
+=
+=
+=
+=
+=
LEX‐ BISON
Dr. Eric Jeltsch F.
5;
9;
10;
40;
50;
90;
100;
400;
500;
900;
1000;
{WS}
|
\n
return total;
%%
int main (void) {
int first, second;
first = yylex ();
second = yylex ();
printf ("%d + %d = %d\n", first, second, first+second);
return 0;
}
yywrap(){return 1;}
/* Supresion de espacios inutiles en el texto, añadiendo un
*/
/* espacio despues de los simbolos de puntuación y restableciendo */
/* las mayúsculas olvidadas.
*/
int ch;
/* es identico a poner %s MAYUSCULA */
%START MAYUSCULA
%%
<MAYUSCULA>[a-z]
}
<MAYUSCULA>[^ \t\n]
{printf("%c", yytext[0] + 'A' - 'a');
BEGIN 0;
{ECHO;
BEGIN 0;
}
^[ \t]+
[ \t]+$
[ \t]+
;
;
printf(" ");
[.?!]+
{ECHO;
BEGIN MAYUSCULA;
}
{ch = yytext[yyleng-1] + 'A' - 'a';
yytext[yyleng-1] = ' ';
printf("%s%c", yytext, ch);
}
{ch = yytext[yyleng-1];
yytext[yyleng-1] = ' ';
printf("%s%c", yytext, ch);
}
printf("%c%c", yytext[0], yytext[1]);
[.?!]+[a-z]
[.?!]+[A-Z]
[,;:]+[A-Za-z]
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 6
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
%%
main (void) {yylex();}
yywrap(){return 1;}
Lenguajes Regulares.
Expresiones simples
c
reconoce el carácter ’c’
.
cualquier carácter excepto salto de linea (’nn’)
[abc]
cualquier carácter del conjunto (’a’, ’b’ ó ’c’)
[ˆabc]
cualquier carácter excepto los del conjunto
[a-z]
cualquier carácter del rango indicado
[ˆa-z]
cualquier carácter excepto los del rango
"xxxx"
reconoce la cadena indicada de forma literal
Operadores (de mayor a menor precedencia)
R* reconoce 0 ó más repeticiones de R
R+ reconoce 1 ó más repeticiones de R
R? reconoce 0 ó 1 ocurrencia de R (opcional)
R{n} reconoce n repeticiones exactas de R
R{n,m} reconoce de n a m repeticiones de R
(R) agrupa expresiones regulares
RS reconoce la concatenación de R y S
R|S reconoce o R o S
ˆR reconoce la expr. R si está al inicio de linea
R$ reconoce la expr. R si está al final de linea
Siendo R y S expr. regulares
FLEX.
Compilar las dos especificaciones FLEX siguientes y comprobar su funcionamiento.
EJEMPLO 1
Cuenta el número de líneas y caracteres que hay en el archivo de entrada.
%{
int num_lineas = 0, num_caracteres = 0;
%}
%%
\n num_lineas++; num_caracteres++;
.
num_caracteres++;
%%
int yywrap()
{
return 1;
}
main()
{
while (yylex());
printf("No. lineas = %d, No. caracteres = %d\n", num_lineas,
num_caracteres);
}
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 7
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
COMPILACIÓN
$ flex prueba1.l
$ gcc -o prueba1 lex.yy.c
EJEMPLO 2
Genera una copia del archivo de entrada, en la que se han eliminado las líneas en blanco, los
espacios al inicio y al final de línea, dejando un único espacio entre palabras.
%{
#include <stdio.h>
/* Incluye el protopipo de la funcion putchar() */
%}
%%
^\n
;
/* Lineas en blanco */
^" "+\n
;
/* Lineas solo con espacios */
^" "+
;
/* Espacios al principio de la linea */
" "+$
;
/* Espacios al final de la linea */
" "+
putchar(' '); /* Sustituir multiples espacios por uno solo */
%%
COMPILACIÓN
$ flex prueba2.l
$ gcc -o prueba2 lex.yy.c -lfl
2. Ejercicio práctico.
Escribir un fuente Flex que lea un archivo de texto, realice las siguientes acciones y presente
los resultados por pantalla.
a)
b)
c)
d)
e)
f)
g)
Contar el número de secuencias de caracteres escritas completamente en mayúsculas.
Contar el número de secuencias de caracteres escritas completamente en minúsculas.
Contar el número de secuencias de caracteres que mezclen mayúsculas y minúsculas.
Contar el número de números enteros.
Contar el número de números reales. (1)
Calcular la suma de todos los números enteros encontrados. (2)
Calcular la suma de todos los números reales encontrados. (2)
BISON.
Bison es una herramienta de gran potencia que, en uso conjunto con Flex, permite construir
compiladores. En esta introducción se vé una pequeña introducción a Bison, haciendo hincapié
en el aspecto que más nos interesa en esta asignatura, que es su capacidad para reconocer palabras
que pertenecen al lenguaje generado por una gramática libre de contexto. Recordar la jerarquía de
Chomsky para entender la forma que tienen este tipo de gramáticas. Un archivo fuente Bison
describe una gramática. El ejecutable correspondiente nos dice si una entrada textual corresponde
o no al lenguaje generado por la gramática. Es importante notar la diferencia con Flex: en este
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 8
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
caso se toma la entrada como una única palabra para la que hay que ver si está o no en el lenguaje
que genera la gramática.
Un archivo fuente Bison es de la forma:
%token α α α ... α
1
2
3
n
%start β
%%
γ;
1
γ;
2
...
γ;
k
Donde {α α α ... α } es el alfabeto (conjunto de terminales de la gramática), β es el símbolo
1
2
3
n
inicial (no terminal de la gramática), y γ
1...
γ son las reglas o producciones de la gramática.
k
Los símbolos terminales se denominan en Bison tokens.
Cada regla (producción) se escribe de la forma:
X : X ... X ; (dos puntos en lugar de la flecha, y termina en punto y coma)
1
2
j
donde X es una variable (no terminal) y X ... X son variables (no terminales) y tokens
1
2
j
(terminales). No es necesario declarar las variables de la gramática (conjunto de no terminales
de la gramática), ya que todo lo que no sean tokens (que si se declaran) se consideran
variables.
Ejemplo: Supongamos que queremos generar las palabras del lenguaje formado por las
expresiones enteras con paréntesis que utilizan + y * (por ejemplo “4”, “4 + 2”,”(4 + 3) * 5”
etc.) :
Para ello podríamos crear una gramática muy sencilla:
S→T|T+T|T*T
T → ENTERO | ( S )
Que traducida a un fuente básico de Bison sería::
Pero además, necesitaríamos un archivo fuente de Flex (fuente.l) que lea la entrada estándar
y genere las ocurrencias de los diferentes tokens de nuestra gramática, es decir:
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 9
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
Añadimos algunas definiciones de funciones necesarias al fuente de Bison (fuente.y) , que
quedaría como sigue:
y compilamos (ojo con el orden):
bison -yd fuente.y (esto genera y.tab.c e y.tab.h)
flex fuente.l (esto genera lex.yy.c)
gcc y.tab.c lex.yy.c -lfl -L/opt/flex/lib -o ejemplo
Nota: cuidado con el nombre que le den a los tokens en Bison. Si los llaman a, b, c etc., se
producen colisiones con algunas variables internas de Flex. Es mejor que los llamen de forma
algo más “complicada” como t_a, t_b etc.
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 10
Teoría de Autómatas y Lenguajes Formales
LEX‐ BISON
Dr. Eric Jeltsch F.
Sugerencia de Actividades o aplicaciones a realizar en el contexto de TALF:
1) El objetivo es entregar una propuesta para verificar la sintaxis, parcialmente, de
documentos XML con Flex y Bison.
a) ver los aspectos básicos del estándar XML y seguir explorando las posibilidades de Flex y
de Bison, no de construir un parser completo y correcto de XML.
b) Estudiar la estructura de los documentos XML
c) Recordar algunos y estudiar otros, el concepto de XML bien formado.
d) Darse ejemplos de documento XML bien formado.
e) Recordar algunos y estudiar otros, el concepto de XML válido.(DTD)
f) Lea un archivo XML con Flex
2) Utilizar Bison para generar ejecutables que reconozcan los siguientes lenguajes. Esto quiere
decir que para las palabras del lenguaje la salida debe ser vacía y para las que no pertenecen al
lenguaje “parse error”.
n
n
j j
i
m
m
a) L = { z a z a b z b z | m, n ≥ 0 }
i
b) L = { a b c d | i,j ≥ 1 }
m
n
c) L = { 0 1 | m > n ≥ 0 }
3) Usar Flex para simular como trabaja un AFD.
Bibliografía
http://ftp.gnu.org/gnu/bison/?C=M;O=D
http://flex.sourceforge.net/manual/
http://www.gnu.org/software/bison/manual/html_mono/bison.html
http://www.medinaweb.com/programas/documents/tutoriales/lex_yacc/index.html
http://dinosaur.compilertools.net/
http://oreilly.com/catalog/9781565920002/
Escuela Ingeniería en Computación, Universidad de La Serena.
Página 11
Descargar