PLY (Python Lex-Yacc)

2-12-2014 The Lex & Yacc INVESTIGACIÓN Integrantes del Equipo Edgar Uriel Linares Delgado -Daniel Alejandro Catalán Du

Views 28 Downloads 0 File size 413KB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

2-12-2014

The Lex & Yacc INVESTIGACIÓN

Integrantes del Equipo Edgar Uriel Linares Delgado -Daniel Alejandro Catalán Duran -Higinio Alexander Solano Olivares

¿Qué es Lex and Yacc? Lex es un programa para 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. Aunque tradicionalmente se trata de software propietario, existen versiones libres de lex basadas en el código original de AT&T en sistemas como OpenSolaris y Plan 9 de los laboratorios Bell. Otra versión popular de software libre de lex es Flex. Lex - Un Analizador Léxico Generador ayuda a programas de escritura cuyo flujo de control está dirigido por casos de expresiones regulares en el flujo de entrada. Es muy adecuado para las transformaciones de tipo editor de script y para la segmentación de entrada en preparación para una rutina de análisis.Lex fuente es una tabla de expresiones regulares y fragmentos de programas correspondientes. La tabla se traduce a un programa que lee un flujo de entrada, copiarla en un flujo de salida y la partición de la entrada en cadenas que concuerden con las expresiones dadas. Como se reconoce cada una de esas cuerdas se ejecuta el fragmento de programa correspondiente. El reconocimiento de las expresiones se lleva a cabo por un autómata finito determinista generado por Lex. Los fragmentos de programas escritos por el usuario se ejecutan en el orden en el que las expresiones regulares correspondientes se producen en el flujo de entrada. Los programas de análisis léxicos escritos con Lex aceptan especificaciones ambiguas y elegir el partido más largo posible en cada punto de entrada. Si es necesario, preanálisis sustancial se realiza en la entrada, pero el flujo de entrada será apoyado hasta el final de la partición actual, por lo que el usuario tiene libertad general para manipularlo Lex puede generar analizadores en C o Ratfor, un lenguaje que puede ser traducida automáticamente a Fortran portátil. Está disponible en el PDP-11 UNIX, Honeywell SMOC, y los sistemas de IBM OS. Este manual, sin embargo, sólo se discutirá la generación de analizadores en C en el sistema UNIX, que es la única forma admitida de Lex por UNIX versión 7. Lex está diseñado para simplificar la interfaz con Yacc, para los que tienen acceso a este sistema compilador de compilador.

Yacc -Sin embargo, otro compilador compilador proporciona una herramienta general para describir la entrada a un programa de ordenador. El usuario Yacc especifica las estructuras de su entrada, junto con el código que puede invocarse como se reconoce cada dicha estructura. Yacc convierte tal especificación en una subrutina que Han- agu- el proceso de entrada; con frecuencia, es conveniente y apropiado que la mayor parte del flujo de control en la aplicación del usuario controlarlo mediante el subprograma.

¿Cómo funcionan? El usuario proporciona el código adicional más allá de la expresión que emparejan necesita para completar sus tareas, posiblemente incluyendo código escrito por otros generadores. El programa que reconoce las expresiones se genera en el lenguaje de programación de propósito general empleado para fragmentos de programas del usuario. De este modo, se proporciona un lenguaje de expresión de alto nivel para escribir las expresiones de cadena que se ajustará mientras que la libertad del usuario para escribir acciones es irreprochable. Esto evita obligando al usuario que desee utilizar un lenguaje de manipulación de cadenas para el análisis de entrada para escribir el procesamiento de programas para la misma y, a menudo inapropiado lenguaje manejo de cadenas. Lex no es un lenguaje completo, sino más bien un generador que representa una nueva característica del lenguaje que se puede añadir a los diferentes lenguajes de programación, llamado `` lenguajes principales. '' Así como lenguajes de propósito general pueden producir código a ejecutar en diferentes equipos informáticos, Lex puede escribir código en diferentes lenguajes principales. El lenguaje anfitrión se utiliza para el código de salida generada por Lex y también para los fragmentos de programas añadidos por el usuario. Lex convierte expresiones y acciones (llamado origen en esta nota) en el host lenguaje de propósito general del usuario; el programa generado se llama yylex. El programa yylex reconocerá expresiones en una corriente (llamada entrada en esta nota) y llevar a cabo las acciones especificadas para cada expresión como se detecte. Véase la Figura 1. + ------- + Fuente -> | Lex | -> yylex + ------- + + ------- + Entrada -> | yylex | -> Salida + ------- + Una visión general de Lex Figura 1

Para un ejemplo trivial, considere un programa para eliminar de la entrada de todos los espacios en blanco o tabuladores en los extremos de las líneas. %% [\ T] + $;

es todo lo que se requiere. El programa contiene un delimitador %% para marcar el inicio de las reglas, y una regla. Esta norma contiene una expresión regular que coincide con una o más instancias de la caracteres en blanco o pestaña (escrito \ t para la visibilidad, de acuerdo con la convención de lenguaje C) justo antes de la final de una línea. Los paréntesis indican la clase de caracteres hecha de blanco y ficha; el + indica `` uno o más ... ''; y los $ indica el final de la línea `` '', como en QED. No se especifica ninguna acción, por lo que el programa generado por Lex

(yylex) ignorará estos personajes. Todo lo demás se copiará. Para cambiar cualquier cadena restante de espacios en blanco o tabuladores a un solo espacio en blanco, añadir otra regla: %% [\ T] + $; [\ T] + printf ("");

El autómata finito generado para esta fuente buscará ambas reglas a la vez, observando a la terminación de la serie de espacios en blanco o tabuladores si hay o no un carácter de nueva línea, y la ejecución de la acción de la regla deseada. La primera regla coincide con todas las cadenas de espacios en blanco o tabuladores al final de las líneas, y la segunda regla todos los restantes cadenas de espacios en blanco o tabuladores. Lex puede ser utilizado solo para las transformaciones sencillas, o para el análisis y recopilación de estadísticas en un nivel léxico. Lex también se puede utilizar con un generador de analizador para llevar a cabo la fase de análisis léxico; es particularmente fácil para interactuar Lex y Yacc [3]. Programas Lex reconocen expresiones sólo regulares; Yacc escribe analizadores que aceptan una gran clase de gramáticas de contexto libre, pero requieren un analizador de nivel inferior para reconocer tokens de entrada. Por lo tanto, una combinación de Lex y Yacc es a menudo apropiado. Cuando se utiliza como un preprocesador para un generador de analizadores sintácticos más tarde, Lex se utiliza para dividir el flujo de entrada, y el generador de analizador asigna estructura a las piezas resultantes. El flujo de control en este caso (que podría ser el primer medio de un compilador, por ejemplo) se muestra en la Figura 2. Los programas adicionales, escrito por otros generadores o con la mano, se puede añadir fácilmente a los programas escritos por Lex. gramática léxica reglas reglas || vv + + + --------- --------- + | Lex | | Yacc | + + + --------- --------- + || vv + + + --------- --------- + Entrada -> | yylex | -> | yyparse | -> entrada analizada + + + --------- --------- +

Lex con Yacc Figura 2

Yacc usuarios se darán cuenta de que el nombre yylex es lo Yacc espera que su analizador léxico para ser nombrado, por lo que el uso de este nombre por Lex simplifica la interfaz. Lex genera un autómata finito determinista de las expresiones regulares en la fuente [4]. El autómata se interpreta, en lugar de compilado, con el fin de ahorrar

espacio. El resultado es todavía un analizador rápido. En particular, el tiempo empleado por un programa de Lex para reconocer y dividir un flujo de entrada es proporcional a la longitud de la entrada. El número de Lex gobierna o la complejidad de las normas no es importante en la determinación de la velocidad, a menos que las reglas que incluyen adelante contexto requieren una cantidad significativa de volver a escanear. Lo que aumentar con el número y la complejidad de las normas es el tamaño de la autómata finito, y por lo tanto el tamaño del programa generado por Lex. En el programa escrito por Lex, fragmentos del usuario (en representación de las acciones a realizar como se encuentre cada expresión regular) se recogen como casos de un interruptor. El intérprete autómata dirige el flujo de control. Se proporciona oportunidad para que el usuario inserte o bien declaraciones o manifestaciones adicionales en la rutina que contiene las acciones, o para añadir subrutinas, fuera de esta rutina de acción. Lex no se limita a la fuente que puede ser interpretado sobre la base de una búsqueda hacia delante carácter. Por ejemplo, si hay dos reglas, una que buscan ab y otro para abcdefg, y la corriente de entrada es abcdefh, Lex reconocerá ab y dejar el puntero de entrada justo antes de cd. . . Dicha copia de seguridad es más costoso que el tratamiento de los idiomas más simples. Uso de Lex con Yacc Lex y Yacc (un generador de analizadores sintácticos) suelen ser utilizados juntos. Yacc utiliza una gramática formal para analizar un flujo de entradas, algo que Lex no puede hacer con expresiones regulares simples (Lex se limita a los autómatas de estados finitos simples). Sin embargo, Yacc no puede leer en un flujo de entradas simple - requiere una serie de símbolos. Lex se utiliza a menudo para proporcionar a Yacc estos símbolos.

JLex: Un generador de analizador léxico para Java Lex es un generador de analizador léxico para el sistema operativo UNIX, dirigida al lenguaje de programación C. Lex toma un archivo de especificación de formato especial que contiene los detalles de un analizador léxico. Esta herramienta crea un archivo fuente C para el lexer tabla impulsada asociado.La utilidad JLex se basa en el modelo de generador de analizador léxico Lex. JLex toma un archivo de especificación similar al aceptado por Lex, a continuación, crea un archivo de código fuente de Java para el analizador léxico correspondiente.

JLex Especificaciones Un archivo de entrada JLex está organizado en tres secciones, separadas por directivas de dos por ciento (`` %% ''). Una especificación adecuada JLex tiene el

siguiente formato. código de usuario %% Directivas JLex %% reglas de expresiones regulares Las directivas `` %% '' distinguen secciones del archivo de entrada y se deben colocar al principio de su línea. El resto de la línea que contiene el `%%` '' directivas pueden ser descartados y no deben utilizarse para alojar declaraciones o código adicionales. La sección de código de usuario - la primera sección del archivo de especificación - se copia directamente en el archivo de salida resultante. Esta zona de la especificación proporciona espacio para la realización de clases de utilidad o tipos de retorno. La sección de directivas JLex es la segunda parte del archivo de entrada. Aquí, las definiciones de macros se dan y los nombres de estado se declaran. La tercera sección contiene las reglas de análisis léxico, cada uno de los cuales consta de tres partes: una lista opcional estado, una expresión regular, y una acción.

El código de usuario precede a la primera directiva de doble ciento (`` %% '). Este código se copia literalmente en el archivo de origen analizador léxico que JLex salidas, en la parte superior del archivo. Por lo tanto, si el archivo de origen lexer necesita comenzar con una declaración del paquete o con la importación de una clase externa, la sección de código de usuario debe comenzar con la declaración correspondiente. Esta declaración se copiará en la parte superior del archivo fuente generada.

Reglamento Interno de Analizador Léxico Clase El% {...}% directiva permite al usuario escribir código Java para copiar en la clase de análisis léxico. Esta directiva se utiliza como sigue. %{

%} Para ser reconocido correctamente, el% {y%} deben Estar situados en el principio de una línea. El código Java especificado en se copia entonces en la clase de análisis léxico creado por JLex. clase yylex { ... ... } Esto permite que la declaración de variables y funciones internas de la clase analizador léxico generado. Los nombres de variables que comienzan con yy deben ser evitados, ya que estos están reservados para el uso de la clase analizador léxico generado. Los analizadores léxicos Generados JLex tomará una especificación adecuadamente formado y transformarlo en un archivo de código fuente de Java para el analizador léxico correspondiente. El analayzer léxico generado reside en la clase yylex. Hay dos constructores a esta clase, tanto requiere un solo argumento: la corriente de entrada a ser de testigos. El flujo de entrada puede ser de tipo java.io.InputStream o java.io.Reader (como StringReader ). Tenga en cuenta que la java.io.Reader constructor debe utilizarse si está generando un lexer aceptar caracteres Unicode, como el JDK 1.0 java.io.InputStream clase no siempre leer Unicode correctamente. La función de acceso al léxico es Yylex.yylex (), que devuelve el siguiente token de la corriente de entrada. El tipo de retorno es Yytoken y la función se declara de la siguiente manera. clase yylex {... pública Yytoken yylex () { ...} El usuario debe declarar el tipo de Yytoken y puede lograr esto convenientemente en la primera sección de la especificación JLex, la sección de código de usuario. Por ejemplo, para hacer Yylex.yylex () devuelve una envoltura alrededor de los números enteros, el usuario introduzca el siguiente código en algún lugar anterior al primer `` %% ''. clase Yytoken {int campo; Yytoken (int f) = f {campo; }} Luego, en las acciones léxicas, envueltos enteros serían devueltos, en algo así como así. {...

volver nueva Yytoken (0); ...} Asimismo, en la sección de código de usuario, una clase podría definirse declarar constantes que se corresponden a cada uno de los tipos de tokens. códigos de token de clase {... CADENA public static final = 0; INTEGER public static final = 1; ...} Luego, en las acciones léxicas, estos códigos simbólicos podrían ser devueltos. {... volver nueva Yytoken (CADENA); ...} Estos son ejemplos simplificados; En uso real, uno probablemente definir una clase de testigo que contiene más información que un código de número entero. Estos ejemplos comienzan a ilustrar las técnicas orientadas a objetos un usuario puede emplear para definir un tipo de token arbitrariamente complejas para ser devueltos por Yylex.yylex (). En particular, la herencia permite al usuario devolver más de un tipo de token. Si se necesitaba un tipo de token distinto para las cadenas y enteros, el usuario podría hacer las siguientes declaraciones. clase Yytoken {...} clase IntegerToken extiende Yytoken {...} clase StringToken extiende Yytoken {...} A continuación, el usuario puede volver tanto IntegerToken y StringToken tipos de las acciones léxicas. Los nombres de la clase de análisis léxico, la función tokening, y el tipo que devuelve cada uno pueden alterarse usando las directivas JLex.

PLY (Python Lex-Yacc) ¿Qué es un ply? Es nada más que una aplicación lex / yacc sencillo ¿Qué es ply.lex? Esto se refiere a la parte de análisis léxico, encargado del análisis de las estructuras. ¿Qué es ply.yacc? Es un módulo el cual se encarga la creación de un programa de análisis.

PLY características esenciales. -Se implementa completamente en Python. -Se utiliza el análisis sintáctico LR – que es razonablemente eficiente y muy adecuado para gramáticas más grandes. -PLY proporciona la mayor parte de las características estándar de lex / yacc incluido el apoyo a las producciones vacías, las reglas de prioridad la recuperación de errores y soporte para gramáticas ambiguas. -PLY es sencillo de usar y proporciona muy extensa comprobación de errores. -PLY no trata de hacer nada más ni menos que proporcionar la funcionalidad básica lex / yacc. En otras palabras, no es un marco de análisis sintáctico grande o un componente de algún sistema más grande. -La versión original de la capa fue desarrollado en 2001 para su uso en un curso de Introducción a los compiladores, donde los estudiantes lo utilizaron para construir un compilador para un lenguaje Pascal simple. Debido a su uso en un entorno de enseñanza, se realizó un gran trabajo para proporcionar una amplia comprobación de errores. Además, se utilizó esta experiencia para resolver los problemas comunes de usabilidad. Desde entonces una variedad de mejoras incrementales se han hecho para el sistema. PLY consta de dos módulos separados; lex.py y yacc.py , ambos de los cuales se encuentran en un paquete de Python llamada capa. El módulo lex.py se utiliza para romper texto de entrada en una colección de fichas especificadas por una colección de reglas de expresiones regulares yacc.py se utiliza para reconocer la sintaxis del lenguaje que se ha especificado en el formulario de una gramática libre de contexto. yacc.py utiliza análisis sintáctico LR y genera sus tablas de análisis sintáctico utilizando el LALR ( 1 ) ( por defecto) o algoritmos de generación de tabla SLR . Las dos herramientas tienen el propósito de trabajar juntos. Específicamente

lex.py ofrece una interfaz externa en forma de una función de señal () que devuelve el siguiente token válido en el flujo de entrada. yacc.py llama a esto varias veces para recuperar tokens e invocar las reglas gramaticales. La salida de yacc.py es a menudo un árbol de sintaxis abstracta (AST). Sin embargo, esto es totalmente en manos del usuario. Si se desea yacc.py también se puede utilizar para implementar simples compiladores de una pasada. Al igual que su contraparte Unix, yacc.py proporciona la mayor parte de las características que usted espera incluyendo una extensa revisión de errores, validación de la gramática, el apoyo a las producciones vacías, fichas de error y resolución de ambigüedad a través de reglas de precedencia. De hecho, todo lo que es posible en yacc tradicional debe ser apoyado en capas. La principal diferencia entre yacc.py y yacc Unix es que yacc.py no implica un proceso de generación de código independiente. En su lugar, PLY se basa en la reflexión (introspección) para construir sus lexers y analizadores. A diferencia de tradicional lex / yacc que requieren un archivo de entrada especial que se convierte en un archivo fuente separado las especificaciones que figuran a PLY son programas Python válidos. Esto significa que no hay archivos de origen adicionales ni hay un paso especial construcción del compilador (por ejemplo, correr yacc para generar código Python para el compilador). Desde la generación de las tablas de análisis sintáctico es relativamente caro, PLY almacena en caché los resultados y las guarda en un archivo. Si no se detectan cambios en la fuente de entrada, las tablas se leen de la memoria caché. De lo contrario, se regeneran. Uso PLY consta de dos archivos: lex.py y yacc.py. Estos están contenidos dentro del directorio ‘ply’ que también puede ser utilizado como un paquete de python.

Para utilizar capas, simplemente copia el directorio ‘ply’ de su proyecto y de importación lex y yacc del paquete de ‘ply’ asociado. Por ejemplo: importar ply.lex como lex ply.yacc importación como yacc Como alternativa, puede copiar sólo la lex.py archivos y yacc.py individualmente y los utilizan como módulos. Por ejemplo: lex importación yacc importación El setup.py archivo se puede utilizar para instalar capas usando distutils. El archivo doc / ply.html contiene documentación completa sobre cómo usar el sistema.

Como implementarlo. Python Lex-Yacc El extremo delantero del intérprete se implementa utilizando capas. No es de extrañar, PLY es una reescritura en Python de la Lex familiar y Yacc. Lex es un analizador léxico responsable de tomar una secuencia de caracteres y dar salida a una corriente de símbolos tales como enteros, cadenas, palabras clave y símbolos. Por otro lado, Yacc es un analizador responsable de tomar una corriente de tokens y reconociendo conjuntos de fichas como construcciones del lenguaje, tales como declaraciones de variables, definición de funciones, y si las declaraciones.

CAPA fue desarrollado originalmente por David Beazley para una clase introductoria sobre los compiladores de la Universidad de Chicago. Beazley

requiere sus estudiantes usan CAPA desarrollar un lenguaje Pascal-como simple que incluyó el análisis léxico, el análisis, la comprobación de tipos, la inferencia de tipos, de alcance anidada, y la generación de código en ensamblador para el procesador SPARC. Esto llevó CAPA a ser un proyecto maduro. Además, PLY cuenta con amplias instalaciones de prueba de errores para detectar errores comunes. A diferencia de Yacc en C, que utiliza LALR-análisis, PLY utiliza LRanálisis, que es razonablemente eficiente y muy adecuado para gramáticas más grandes, pero restringe ligeramente los tipos de gramáticas que puede ser analizado correctamente. Además, a diferencia de Lex y Yacc en C, PLY basa en Python reflexión, por lo que no existen por separado Lex y Yacc archivos-todo está en Python.

Python Lex El primer paso para la implementación de un intérprete es escribir la tokenizer utilizando Python Lex; ver Listado Uno. Fichas se reconocen usando expresiones regulares. Los pasos son sencillos: 1. Los nombres de todos los tipos de tokens válidos se declaran como una lista de cadenas con nombre fichas. 2. Las fichas que no requieren un procesamiento especial se declaran utilizando variables de nivel de módulo denominado t_TOKEN_TYPE donde TOKEN_TYPE coincide con alguna cadena en la lista de "tokens". Cada una de estas variables contiene una cadena de expresión regular que coincide con el símbolo correspondiente (Python cuerdas primas se utilizan por lo general, ya que son la forma más conveniente de escribir cadenas de expresiones regulares).

3. Las fichas que requieren un procesamiento especial se declaran utilizando funciones de nivel de módulo que siguen la misma convención de nombres. Cada una de estas funciones tiene una cadena de documentación que es una expresión regular que coincide con el símbolo correspondiente. El orden de estas funciones es importante ya que cada expresión regular se trató en orden. Por lo tanto, las funciones con las expresiones regulares más complejas (flotadores, por ejemplo) deben venir antes de las funciones con las expresiones regulares complejas menos (intercepciones, por ejemplo). Cada función recibe un valor de tipo LexToken, lo modifica, y por lo general lo devuelve. A diferencia de Lex en C, que utiliza los sindicatos, el valor devuelto tiene un atributo llamado "valor" que se puede ajustar a un valor de cualquier tipo (incluso una instancia). Esta flexibilidad es conveniente. Si ninguno se devuelve o si se encuentra sin retorno, el analizador léxico ignora el token actual y pasa a la siguiente token. Esto puede ser usado para implementar el control de espacios en blanco, pero un t_ignore variable de

nivel de módulo llamado es más eficiente para esta tarea. Una vez definidas las reglas Tokenizer, lex.lex () se utiliza para construir el tokenizer. Un principal (por ejemplo, si __name__ == '__main__' :) se incluye que pone a prueba la funcionalidad del tokenizer mediante pruebas de regresión. Esta es una buena práctica de programación en Python, pero es casi imprescindible cuando se escribe un idioma. (El código fuente completo de principal está disponible electrónicamente, véase "Centro de Recursos").

Python Yacc El siguiente paso para la implementación de un intérprete es escribir el analizador utilizando Python Yacc; ver Listado Dos. Después de importar la lista de fichas del módulo tokenizer escrito anteriormente, se definen una serie de funciones. Ejemplo 1 muestra una tal función que reconoce una expresión en paréntesis y establece que el valor de toda la expresión es igual al valor de la expresión en el paréntesis. Cada función tiene una cadena de documentación que contiene la especificación gramática independiente del contexto apropiado (esta idea fue tomada de SPARK kit de herramientas de John Aycock. Cada función tiene un argumento único, t, que es una secuencia de valores (empezando en el índice 1) que coinciden con los respectivos símbolos en la cadena de documentación. Estos valores son los mismos valores que se almacenaron en atributos t.value en el tokenizer. El cuerpo de la función hace lo que el procesamiento es apropiado y coloca el resultado en t [0].

Ejemplo: # calclex.py # tokenizer for a simple expression evaluator for # numbers and +,-,*,/ import ply.lex as lex # List of token names. This is always required tokens = ( 'NUMBER', 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'LPAREN', 'RPAREN',) # Regular expression rules for simple tokens t_PLUS = r'\+' t_MINUS = r'-' t_TIMES = r'\*' t_DIVIDE = r'/' t_LPAREN = r'\(' t_RPAREN = r'\)'

# A regular expression rule with some action code def t_NUMBER(t): r'\d+' t.value = int(t.value) return t # Define a rule so we can track line numbers def t_newline(t): r'\n+' t.lexer.lineno += len(t.value) # A string containing ignored characters (spaces and tabs) t_ignore = ' \t' # Error handling rule def t_error(t): print "Illegal character '%s'" % t.value[0] t.lexer.skip(1) # Build the lexer lexer = lex.lex()

Webgrafia

http://www.dabeaz.com/ply/ply.html https://ng.techweb.com/authds/gateway?gateway=true&return=http%3A%2F%2Fw ww.drdobbs.com%2Fweb-development%2Fprototyping-interpreters-using-pythonle%2F184405580 https://escompiladores.wordpress.com/2014/03/11/ply-una-implementacion-de-lexy-yacc-en-python/ http://www.gacetadelinux.com/es/lg/issue79/divakaran.html https://code.google.com/p/ply/

http://www.drdobbs.com/web-development/prototyping-interpreters-using-pythonle/184405580 http://es.wikipedia.org/wiki/Lex_(inform%C3%A1tica) http://translate.google.com.mx/translate?hl=es419&sl=en&tl=es&u=http%3A%2F%2Fdinosaur.compilertools.net%2F&sandbox=1 http://translate.google.com.mx/translate?hl=es419&sl=en&u=http://www.cs.princeton.edu/~appel/modern/java/JLex/current/manu al.html&prev=search http://www.cc.uah.es/ie/docencia/ProcesadoresDeLenguaje/2.3.JLex.pdf