LEX

Estructura de un programa en LEX

{ definiciones }
%%
{ reglas }
%%
{ subrutinas del usuario }
Las definiciones y subrutinas son opcionales. El segundo %% es opcional pero el primer %% indica el comienzo de las reglas.

Expresiones Regulares

Las expresiones regulares en LEX son formadas en base a las siguientes reglas:

LEX incluye otros operadores para darle mayor poder a las expresiones regulares y estos son:

[a-z] [^a-z] [\0\n] [\0-\134]

ab?c

^abc

ab/cd

ab$ = ab/\n

<x> = ^x si la condición es que comience desde el principio de la línea

{digito} Usa el valor de digito y sustituye el nombre por su valor en la expresión.

a{1,5} Espera desde una a cinco ocurrencias de a.

\n \{ \%

"\t" "[" "a"

Acciones

Cuando una cadena que se está analizando cumple con una expresión, se ejecuta la acción asociada a dicha expresión. La acción que se asocia a la expresión se escribe en lenguaje C, pero LEX no realiza ninguna verificación sobre dicha acción, para LEX esta acción es como si fuera un comentario.

[ \t\n] ;

En esta regla, la acción es nula, por lo tanto, lo que se hace es que los caracteres dentro de los corchetes sean ignorados.

[a-z]+ printf( "%s", yytext );

En esta regla, la acción a realizar es la impresión del valor de yytext.

Si se requiere que una acción esté formada por más de una instrucción, entonces se usan los operadores { y }, donde las instrucciones son especificadas dentro de las llaves.

\"[^"]* { if (yytext[yyleng-1] == ‘\\’)
yymore();
else
….
}

Existen en LEX ciertas variables y funciones predefinidas, las cuales son utilizadas normalmente en la parte correspondiente a las acciones.

Cuando se requiere que dos o más reglas realicen la misma acción, se puede utilizar el operador | al final de cada expresión:

{d}{s}{e}{n} |
{d}{c}{o}{s} |

{d}{r}{e}{a}{l} printf( "%s"m yytext+1 );

Variables

Funciones

=-[a-zA-Z] {
printf( "Op ( =-) ambigüo\n");
yyless( yyleng-1);
…..
}
Si se reguiere que sea tratado como "=-a", entonces tenemos
=-[a-zA-Z] {
printf( "Op ( =-) ambiguo \n");
yyless( yyleng-2);
…..
}
Una forma para escribir lo anterior sería:
=-/[A-Za-z] en el primer caso
=/-[A-Za-z] para el segundo

LEX maneja especificaciones ambiguas, lo cual se presenta cuando una cadena de entrada cumple con más de un patrón, por lo que LEX realiza las siguientes acciones:

 

Definiciones

Las definiciones en LEX son especificadas antes del primer %%, donde cualquier línea en esta sección que no esté dentro de %{ y %} y que comience en la columna uno, se asume que es una definición de sustitución de cadenas.

D [0-9]
E [DEde][-+]?{D}+
%%
{D}+ printf( "Entero" );
{D}+ "."{D}*({E})?|{D}*"."{D}+({E})?|{D}+{E}

Uso

lex programa

programa >entrada <salida

LEX y YACC

LEX escribe una función llamada yylex(), la cual es requerida por YACC, para que pueda hacer su análisis.

Normalmente, la acción que se realiza cuando se cumple un patrón es regresar a YACC un token asociado con el patrón que se cumple.

return (token);

Donde los tokens son definidos en un archivo de encabezado y posteriormente es incluido

Ejemplo

/* Archivo de Encabezado */
#define identificador 0
#define numero 1
#define suma 2
#define error 3
{%
/* Archivo de LEX */
#include "encabeza.h"
%}
D [0-9]
L [A-Za-z]
%%
(_|{L})({L}|{D}|_)* return identificador;
{D}+ return numero;
+|\- return suma;
. return error;
%%
main()
{
yylex();
}

Sumario

El esquema general de un archivo fuente de LEX es
{definiciones}
%%
{reglas}
%%
{subrutinas}
La sección de definiciones esta formada por una combinación de
%T
numero espacio cadena-de-caracteres
%T
%x nnn
donde nnn es un número entero representando el tamaño de un arreglo y x puede ser cualquiera de los siguientes valores

Las líneas en la sección de reglas son de la forma expresión acción, donde la acción puede contener más de una línea usando las llaves como delimitadores.

Las expresiones regulares en LEX usan los siguientes operadores:

x el carácter "x".
"x" el carácter "x", aún si x es un operador.
\x el carácter "x", aún si x es un operador.
[xy] el carácter x o y.
[x-z] los caracteres x, y o z.
[^x] cualquier carácter excepto x.
. cualquier carácter excepto nueva línea.
^x una x al comienzo de una línea.
<y>x una x si se cumplió la condición y.
x$ una x al final de la línea.
x? Una x opcional.
x* 0, 1, 2, … ocurrencias de x.
x+ 1, 2, 3, … ocurrencias de x.
x|y una x o una y.
(x) una x.
x/y una x pero solo si es seguida por una y.
{xx} la sustitución de xx por su valor especificado en la sección de definiciones.
x{m,n} de m hasta n ocurrencias de x.