You are on page 1of 9

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

Anlisis lxico (Scanner)

La fase de rastreo (scanner), tiene las funciones de leer el programa fuente como un archivo de caracteres y dividirlo en tokens. Los tokens son las palabras reservadas de un lenguaje, secuencia de caracteres que representa una unidad de informacin en el programa fuente. En cada caso un token representa un cierto patrn de caracteres que el analizador lxico reconoce, o ajusta desde el inicio de los caracteres de entrada. De tal manera es necesario generar un mecanismo computacional que nos permita identificar el patrn de transicin entre los caracteres de entrada, generando tokens, que posteriormente sern clasificados. Este mecanismo es posible crearlo a partir de un tipo especifico de maquina de estados llamado autmata finito.

2.1

Funcin del analizador lxico

Es la primera fase de un compilador. Su principal funcin consiste en leer la secuencia de caracteres del programa fuente, carcter a carcter, y elaborar como salida la secuencia de componentes lxicos que utiliza el analizador sintctico. El analizador sintctico emite la orden al analizador lxico para que agrupe los caracteres y forme unidades con significado propio llamados componentes lxicos (tokens). Los componentes lxicos representan: o o o o o o Palabras reservadas: if, while, do, Identificadores: variables, funciones, tipos definidos por el usuario, etiquetas, Operadores: =, >, <, >=, <=, +, *, Smbolos especiales: ;, ( ), { }, Constantes numricas. literales que representan valores enteros y flotantes. Constantes de carcter: literales que representan cadenas de caracteres.

El analizador lxico opera bajo peticin del analizador sintctico devolviendo un componente lxico conforme el analizador sintctico lo va necesitando para avanzar en la gramtica. Los componentes lxicos son los smbolos terminales de la gramtica. Suele implementarse como una subrutina del analizador sintctico. Cuando recibe la orden obtn el siguiente componente lxico, el analizador lxico lee los caracteres de entrada hasta identificar el siguiente componente lxico.
componente lxico programa fuente analizador lxico obtn siguiente componente lxico tabla de smbolos analizador sintctico rbol de anlisis sintctico

Adems el analizador lxico es responsable de: o o o o Manejo de apertura y cierre de archivo, lectura de caracteres y gestin de posibles errores de apertura. Eliminar comentarios, espacios en blanco, tabuladores y saltos de lnea. Inclusin de archivos y macros. Contabilizar nmero de lneas y columnas para emitir mensajes de error.

Una de las ventajas de separar el anlisis lxico y anlisis sintctico es que facilita la transportabilidad del traductor si se decide realizar cambios posteriores, por ejemplo cambiar las etiquetas begin-end por llaves de apertura y cierre { }.

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

2.2

Componentes lxicos, patrones y lexemas

En la fase de anlisis, los trminos componentes lxicos (token), patrn y lexema se emplean con significados especficos. Un analizador lxico, inicialmente lee los lexemas y le asigna un significado propio. componente lxico es la secuencia lgica y coherente de caracteres relativo a una categora: identificador, palabra reservada, literales (cadena/numrica), operador o carcter de puntuacin, adems de que un componente lxico puede tener uno o varios lexemas. patrn es una regla que genera la secuencia de caracteres que puede representar a un determinado componente lxico (expresin regular). lexema es una cadena de caracteres que concuerda con un patrn que describe un componente lxico (valor de cadena).

Ejemplo de una cadena de cdigo: const pi = 3.1416; Lexemas const = pi 3.1416 hola mundo Componente lxico const relacin identificador nmero literal Patrn const < o <= o = o <> o > o >= letra seguida de letras o nmeros cualquier literal numrica caracteres entre comillas

El analizador lxico recoge informacin sobre los componentes lxicos en sus atributos asociados. Los tokens influyen en las decisiones del anlisis sintctico, y los atributos, en la traduccin de los tokens. En la practica los componentes lxicos suelen tener solo un atributo. Para efectos de diagnostico, puede considerarse tanto el lexema para un identificador como el numero de lnea en el que se encontr por primera vez. Esta informacin puede ser almacenada en la tabla de smbolos para el identificador (estructura de datos). Para la cadena E=M*C**2 de ejemplo, los componentes lxicos y los valores de atributo asociado son: <identificador, atributo para el smbolo E> <op_asignacion> <identificador, atributo para el smbolo M> <op_multiplica> <identificador, apuntador al smbolo C> <op_exponente> <numero, atributo valor 2> Tome en cuenta que ciertas parejas no necesitan un valor de atributo. Los atributos relacionados con ese token debern ser conservados y transferidos a alguna estructura de datos para que sean empleados en las siguientes etapas del anlisis

2.3

Manejo de Buffer de entrada

Existen algunos aspectos de eficiencia relacionados con el manejo de buffer. Primero se menciona un esquema de doble buffer de entrada que resulta til como pre-anlisis de la entrada para identificar los componentes lxicos. El segundo esquema introduce algunas tcnicas tiles para aumentar la eficiencia del analizador lxico, empleando centinelas. Hay veces en que el analizador lxico necesita analizar previamente varios caracteres, adems del lexema para un patrn, antes de poder anunciar una concordancia. Se pueden emplear muchos esquemas de manejos de buffer, pero, aqu tan solo se sealarn algunos principios bsicos.

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

Parejas de buffer Se utiliza un buffer dividido en dos mitades de N (1024 512) caracteres cada una, Se leen N caracteres de entrada en cada mitad del buffer con un orden de lectura del sistema, en vez de invocar una instruccin de lectura para cada carcter de entrada. Si quedan menos de N caracteres en la entrada, entonces se lee un carcter especial eof en el buffer despus de los caracteres de entrada. Es decir, eof marca el final del archivo fuente y es distinto a cualquier carcter de la entrada.

* * Inicio lexema

2 eof frente

Se mantienen dos apuntadores en el buffer de entrada. La cadena de caracteres entre los dos apuntadores es el lexema en curso. Al principio, los dos apuntadores apuntan al primer carcter del prximo lexema que hay que encontrar. Uno de ellos, apuntador delantero, examina hacia adelante hasta encontrar una concordancia con un patrn. Una vez determinado el siguiente lexema, el apuntador delantero se coloca en el carcter de su extremo derecho. Despus de haber procesado el lexema, ambos apuntadores se colocan en el carcter situado inmediatamente despus del lexema. Con este esquema se pueden considerar los comentarios y los espacios en blanco como patrones que no producen componentes lxicos. Centinela Corrigiendo la deficiencia del mtodo anterior para reducir la necesidad de dos pruebas para cada avance del apuntador delantero. Se amplia cada mitad del buffer para admitir un carcter centinela al final. De esta manera se vuelve mas eficiente el proceso de cargar del buffer, realizando una carga en cada mitad.

\0

* * inicio lexema

2 \0 frente

eof

El manejo de buffer es una labor puramente de programacin y se recomienda realizarla de la manera que resulte mas sencilla, no es necesario apegarse a alguno de los dos mtodos antes mencionados.

2.4

Jerarqua de Chomsky

En el campo de las ciencias computacionales y especficamente en el rea de los lenguajes formales la jerarqua de Chomsky es una clase de gramtica formal, que describe de manera precisa un lenguaje. Las gramticas formales o gramticas suelen ser clasificadas en dos grandes tipos: las gramticas generativas, que en base a un conjunto de reglas nos indican como formar cadenas del lenguaje. Y las gramticas analticas, que nos indican como esos miembros del lenguaje pertenecen a un orden especifico. Una gramtica formal consiste de: o o o o Un conjunto finito de smbolos terminales Un conjunto finito de smbolos no terminales Un conjunto finito de reglas de produccin que consiste de una secuencia de stos smbolos Un smbolo inicial

Un lenguaje formal o gramtica formal es una secuencia de smbolos que podran ser construidos aplicando reglas de produccin para esas secuencias de smbolos, y podran en casi todos los casos describir de manera precisa un lenguaje de programacin.

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

La jerarqua de Chomsky consiste de los siguientes niveles de gramticas: o Gramticas sin restricciones (Tipo-0), son capaces de generar todos los lenguajes reconocidos por una maquina de Turing. Gramticas de contexto sensitivo (Tipo-1), son lenguajes capaces de ser reconocidos por una maquina de Turing no determinista. Gramticas libres de contexto (Tipo-2), estos lenguajes son exactamente todos aquellos lenguajes que pueden ser reconocidos por un autmata de pila no-determinstico. Las gramticas libres de contexto son la base terica para la construccin de la sintaxis en la mayora de los lenguajes de programacin. Gramticas regulares (Tipo-3), son exactamente todos los lenguajes que pueden ser reconocidos por un autmata de estado finito. Esta familia de lenguajes formales puede ser obtenida a partir de una expresin regular. Las expresiones regulares son comnmente usadas para realizar la bsqueda de patrones en estructuras lxicas de lenguajes de programacin.

2.5

Especificaciones de componentes lxicos

Las expresiones regulares son una notacin importante para especificar patrones. Cada patrn concuerda con una serie de cadenas que, de modo que las expresiones regulares servirn como nombres para conjuntos de cadenas. El trmino alfabeto denota cualquier conjunto finito de smbolos, por ejemplo el alfabeto binario { 0, 1 }. Una cadena es una secuencia de finita de smbolos de un alfabeto y un lenguaje se refiere a conjunto de cadenas de un alfabeto fijo.

2.5.1 Expresiones Regulares El origen de las expresiones regulares surge de la teora de autmatas y la teora de lenguajes formales, ambas parte de la ciencias computacionales terica. Este campo estudia los modelos computacionales (autmata) y la manera de describir y clasificar los lenguajes formales. Un lenguaje formal puede ser especificado de varias maneras, tales como: Cadenas producidas por alguna gramtica formal. Cadenas producidas por expresiones regulares. Cadenas aceptadas por algunos autmatas tales como las maquinas de Turing o autmatas de estado finito.

A las expresiones regulares frecuentemente se les llaman patrones, ya que son expresiones que describen a un conjunto de cadenas. Frecuentemente son usadas para dar una descripcin concisa de un conjunto, sin tener que listar todos sus elementos. Las expresiones regulares pueden ser expresadas en trminos de la teora de lenguajes formales. Consisten de constantes y operadores que denotan el conjunto de cadenas y operaciones sobre estos conjuntos, respectivamente. Dado un alfabeto las siguientes constantes son definidas: o o o Conjunto vaco: L( ) denota el conjunto { } Cadena vaca: L( ) denota el conjunto { } Carcter del alfabeto: L( a ), a elemento de denota el conjunto { a }

Operaciones bsicas en expresiones regulares Seleccin de alternativas (unin) Si r y s son expresiones regulares, entonces r | s es una expresin regular que define cualquier cadena que concuerda con r o con s. En trminos de lenguajes decimos que r | s es la unin de los lenguajes de r y s, o L(r | s) = L(r) U L(s) = { | esta en r o esta en s }.

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

ejemplo: o o o L(a | b) = L(a ) U L(b) = { a, b } L(a | ) = { a, } L(a | b | c | d ) = { a, b, c, d }

Concatenacin La concatenacin de dos expresiones regulares r y s se escribe como rs (yuxtaposicin) y corresponde a cualquier cadena que sea la concatenacin de dos cadenas, con la primera de ellas correspondiendo a r y la segunda a s. Por ejemplo la expresin regular ab corresponde a la cadena { ab }, mientras que la expresin regular (a | b)c corresponde a las cadenas { ac, bc }. De esta forma la operacin de concatenacin para expresiones regulares se puede definir como L(rs) = L(r) L(s) = { | esta en r y esta en s }. ejemplo: o o L(a | b) c = L(a | b) L(c) = { a, b } {c} = { ac, bc } L(ab|c)(d|ef)=L(ab|c)L(d|ef)={ab,c}{d,ef}={abd, abef, cd, cef}

Repeticin (cerradura de Kleene) Se escribe r*, donde r corresponde a la expresin regular. La expresin regular r* corresponde a cualquier concatenacin finita de cadenas, cada una de las cuales corresponde a r. Por ejemplo, la expresin regular a* corresponde a las cadenas { , a, aa, aaa, }, (concuerda con por que es la concatenacin de ninguna cadena concordante con a). En trminos de lenguaje podemos decir que:

S* = U S n
n =0

Donde Sn = S S es la concatenacin de S n veces (S0 = { }).

ejemplo: o o o L(a|b)* = {a, bb}* = {,a,bb,aa,abb,bba,bbbb,aaa,abba,abbbb,...} L(a | b*) = {a, b*} = { , a, b, bb, bbb, ...} L(ab|c)* = {ab,c}* = {, ab, c, abab, abc, cab, cc, ababab,...}

Para evitar los parntesis se asume que la repeticin tiene la precedencia mas alta, luego la concatenacin y al final la unin. Si no existiera ambigedad los parntesis pueden ser omitidos . Por ejemplo , (ab)c se escribe como abc y a|(b(c*)) puede ser escrito como a|bc*. De manera que los lenguajes regulares deben su nombre al hecho de que presentan regularidades o repeticiones de los mismo componentes, como por ejemplo el lenguaje L1: L1={ab, abab, ababab, abababab, ...} As pues, una expresin regular se construye a partir de expresiones regulares mas simples utilizando un conjunto de reglas definitorias (operaciones bsicas). Cada expresin regular r representa un lenguaje L(r). Las reglas de definicin especifican como se forma L(r) combinando de varias maneras los lenguajes representados por las subexpresiones de r. Se dice que un lenguaje designado por una expresin regular es un conjunto regular. Es importante recordar que la especificacin de una expresin regular es un ejemplo de definicin recursiva. Definicin regular: Es una forma de simplificacin, dando un nombre a las expresiones regulares y definiendo nuevas expresiones regulares utilizando dichos nombres como si fueran smbolos. Por ejemplo, podramos desarrollar una expresin regular para una secuencia de uno o mas dgitos, generando inicialmente una definicin regular para un digito. digito = 0 | 1 | 2 | | 9 (definicin regular) digito digito* (expresin regular para nmeros enteros sin signo)

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

Ahora estamos en posicin de elaborar la una definicin de expresiones regulares para la identificacin de los componentes de un lenguaje determinado. Los tokens de lenguajes de programacin tiende a caer dentro de varias categoras limitadas que son bastante estandarizadas, como palabras reservadas, smbolos especiales, identificadores y literales (numrica/cadena). Por ejemplo los identificadores en la mayora de los lenguajes de programacin es el conjunto de cadenas de letras y dgitos que empiezan con una letra. Para ello generamos las definiciones regulares para letra y digito: letra = a | b | c | | z | A | B | Z digito = 0 | 1 | 2 | | 9 identificador = letra ( letra | digito )* Los nmeros con signo son literales numricas constituidas por el punto decimal despus de un digito y por una literal que represente la parte del exponente. Con esta informacin desarrollamos las definiciones regulares y las expresiones regulares necesarias: ((+||)digito digito*) ((. digito)|) ((E(+||)digito)|) entero = (+||) digito digito* fraccin = ( . digito ) | exponente = ( E ( + | | ) digito ) | numero = digito fraccin exponente

Esta definicin establece que fraccin es un punto decimal seguido de uno o mas dgitos, o esta ausente. Un exponente, que es E seguido de un signo + - ausente, seguidos de uno o mas dgitos, o la ausencia de exponente. Tome en cuanta que, como mnimo debe existir un dgito despus del punto. De manera que numero concuerda con 1 y con 1.0. Abreviaturas en la notacin o Uno o mas casos el operador unitario postfijo + significa uno o mas casos de, de manera + que la expresin regular r que designa al lenguaje L(r), entonces r es una expresin que + + designa al lenguaje L(r) . As la expresin regular a representa al conjunto de todas las cadenas de una o mas a. El operador + tiene la misma precedencia que la repeticin, las identidades algebraicas son r* = r | y r + = r r*. Cero o un caso el operado unitario postfijo ? significa cero o un caso de. La notacin r? es la abreviatura de r | . Si r es una expresin regular, entonces (r)? es una expresin regular que designa el lenguaje L(r) U { }. Clases de caracteres una clase abreviada de caracteres como [a z] designa la expresin regular a | b | c | | z.

A menudo en la descripcin de los tokens de lenguaje de programacin utilizamos expresiones regulares, algunas cadenas se pueden definir mediante varias expresiones regulares diferentes, Por ejemplo, cadenas tales como if y while podran se identificadores o palabras clave. Una definicin de lenguaje de programacin debe establecer cual interpretacin se observar, y las expresiones regulares por si mismas no pueden hacer esto. En realizad, una definicin de lenguaje debe proporcionar reglas de de no ambigedad que explicaran cual significado es el conveniente para cada uno de tales casos. Existen dos reglas bsicas que suponen tales casos: o La primera establece que, cuando una cadena puede ser identificador o palabra clave, se prefiere por lo general la interpretacin como palabra clave.

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

La segunda establece que, cuando una cadena puede ser un token simple o una secuencia de varios tokens, por lo comn se prefiere la interpretacin del token simple. Esta preferencia se conoce a menudo como el principio de sub-cadena mas larga.

Una cuestin que surge en el principio de sub-cadena mas larga es lo referente a los delimitadores de tokens, o caracteres que implican que una cadena mas larga en el punto donde aparecen no pueden representar un token. Los caracteres que son parte no ambigua de otros tokens son delimitadores. Por ejemplo xtemp=ytem, el signo de = sirve como delimitador pues no forma parte de los identificadores. Los espacios en blanco, los retornos de lnea y los caracteres de tabulacin generalmente se asumen como delimitadores de token. De esta manera el reconocimiento de componentes lxicos podra realizarse partiendo del conjunto de cadenas dadas por expresiones regulares. Por ejemplo: if = if else = else oprelacion = < | <= | = | <> | > | >= identificador = letra ( letra | digito )* entero = ( + | )? digito+ real = ( + | )? digito+ ( . digito+ )? ( E ( + | )? digito+ )? delimitador = blanco | tab | nuevalnea Para este fragmento de lenguaje, el analizador lxico reconocer las palabras clave if, else, al igual que los lexemas representados por opRelacion, identificador, numero y delimitador. An cuando las expresiones regulares son un mecanismo poderoso de definicin de lenguajes, es necesario construir una herramienta computacional que nos permita su implementacin, para ello se emplean los autmatas de estado finito. Es decir que, las expresiones regulares debern ser transformadas a algn tipo de maquina de estados fcil de programar.

2.6

Reconocimiento de componentes lxico

Un reconocedor de lenguajes es un programa que toma como entrada una cadena x e indica si dicha cadena pertenece a una frase del programa. Se compila una expresin regular en un reconocedor construyendo un diagrama de transiciones generalizado llamado autmata finito. Un autmata finito puede ser determinista o no determinista, dependiendo del nmero de transiciones para un mismo smbolo de entrada. Tanto los autmatas finitos deterministas como los no deterministas pueden reconocer con precisin a los conjuntos regulares. Por tanto, ambos pueden reconocer con precisin lo que denotan las expresiones regulares.

2.6.1 Autmatas finitos Una maquina de estado finito o autmata finito, es un modelo computacional que consiste de un conjunto de estados, un estado de inicio, un alfabeto de entrada y una funcin de transicin que traza un mapa a un siguiente estado, a partir del smbolo de entrada y el estado actual. En particular, los autmatas finitos se pueden utilizar para describir el proceso de reconocimiento de patrones en cadenas de entrada. El sistema recibe una cadena constituida por smbolos de un alfabeto y determina si esa cadena pertenece al lenguaje que ese autmata reconoce. De esta manera se pueden construir analizadores lxicos, construyendo programas de computadora que realicen las operaciones de un autmata. Es claro que existe una fuerte relacin entre los autmatas y las expresiones regulares, y veremos mas adelante como construir un autmata finito a partir de una expresin regular.

2.6.2

Autmata finito no determinstico

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

2.6.3 Autmata finito determinstico Un autmata finito determinista (DFA por sus siglas en ingles), es un modelo donde el siguiente estado de la transicin esta dado particularmente por el estado actual y el carcter de entrada actual. Si ningn estado de transicin es especificado, la cadena entrante es rechazada. La siguiente definicin formalmente introduce un DFA, ( S, , T, s, A ) donde: o o o o o S conjunto finito no vaco de elementos llamado estados alfabeto de entrada T es una funcin de transicin de S en S s S estado inicial A S conjunto no vaco de estados finales

El ADF se encuentra en un estado inicial y lee una entrada de cadena de caracteres de izquierda a derecha. La funcin de transicin T define los estados de transicin y es denotada por T ( si ,c ) = si+1, donde si y si+1 son estados de S, y c es un carcter del alfabeto de entrada. La funcin de transicin indica que cuando un autmata esta en un estado si y recibe el siguiente smbolo de entrada c, el autmata deber cambiar al estado si+1. El carcter de entrada no causara transicin en caso de ser un carcter vaci. El siguiente ejemplo nos muestra un autmata que reconoce cadenas de lenguaje para una expresin regular ( a | b )* abb. El conjunto de estados del DFA es { 0, 1, 2, 3 } y el alfabeto de smbolos de entrada es { a, b }. Se considera 0 como el estado de inicio, y 3 el estado de aceptacin que esta indicado mediante un doble circulo. La siguiente funcin define dicho autmata: F = ({ 0, 1, 2, 3 }, { a, b }, T, 0, { 3 } ) Donde T es la tabla de transicin que refleja el patrn de la expresin regular que estamos evaluando T ( si ,c ) = si+1 definida como: Estado 0 1 2 3 Smbolos de entrada a b 1 0 1 2 1 3 1 0

La tabla de transicin tambin puede ser representada mediante un grafo de transicin, donde cada nodo representa los posibles estados y las lneas reflejan el flujo de la transicin que registran un cambio de un estado a otro en una coincidencia de carcter el estado 0 es considerado el inicio de la transicin y el estado 3 (doble circulo) representa el fin de la transicin o estado de aceptacin:
a a 0 b 1 a b 2 b b 3 a

Justamente el autmata que se acaba de disear es capas de aceptar cadenas de entrada que pertenezcan a la expresin regular dada anteriormente, es decir, { abb, aabb, babb, ababb, baabb, aaabb, }. Cualquier cadena de entrada que no corresponda con dicho patrn ser considerada como ajena al lenguaje, es decir, terminar en cualquier punto que no sea 3 (fin de la transicin) es considerado como un posible error. Igualmente es posible disear un algoritmo que realice exactamente las mismas operaciones que el autmata dado anteriormente para la expresin regular ( a | b )* abb. As pues,

UAA Sistemas Electrnicos

Compiladores

Eduardo Serna-Prez

consideremos que la funcin de transicin (siguiente estado) desde un estado s en un carcter de entrada c, esta dada por una operacin de seleccin de estado (case en s). Adems consideraremos la existencia de una funcin sigtecar() que devuelve el siguiente carcter de la cadena de entrada, obteniendo el siguiente algoritmo: s = 0; c = sigtecar( cadena ); while ( c != \0 ) { case ( s ) { 0: s = ( c == b )? 0 : 1: s = ( c == b )? 2 : 2: s = ( c == b )? 3 : 3: s = ( c == b )? 0 : } c = sigtecar( cadena ) } if ( s == 3 ) cadena valida

1 1 1 1

Dicho algoritmo es capas de evaluar una entrada de cadena y determinar si la misma forma parte del patrn especificado por la expresin regular dada. Si el algoritmo llega a un fin de cadena con un estado de aceptacin 3, quiere decir que dicha cadena es valida o concuerda con el patrn. Ahora estamos en posicin de poder construir autmatas mas elaborados partiendo de las expresiones regulares ya definidas, por ejemplo, pensemos en la definicin regular para un identificador que esta compuesta por la siguiente expresin regular letra ( letra | digito )*, para este caso considerremos el conjunto de estados como 2 { 0, 1 }, el alfabeto de entrada estar compuesto de las definiciones regulares letra y digito. El 0 es considerado como el inicio y 1 como el fin de la transicin. De esta manera generamos el siguiente diagrama de transicin para un identificador:

letra letra 0 1 digito

Bibliografa Aho, A.V., Sethi, R., Ullman, J.D. (1990), Compiladores: principios, tcnicas y herramientas, capitulo 1, pginas: 1- 25, 743-747. Louden, K.C. (1997), Construccin de Compiladores: Principios y prctica, capitulo 1, pginas: 1- 27. http://en.wikipedia.org/wiki/Compiler

You might also like