Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
otros:compilers [2009/11/07 19:00] alfred |
otros:compilers [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| ====== Compiladores ====== | ====== Compiladores ====== | ||
| Para crear un compilador necesitamos un analizador léxico (o //scanner//) analiza el texto, y un analizador sintáctico (o //parser//) el que analiza la estructura del texto y realiza las acciones necesarias según esta. El analizador léxico recorre el texto y va pasando las porciones útiles (//tokens//) al parser, este actuará según la estructura en la que estén colocados los tokens. | Para crear un compilador necesitamos un analizador léxico (o //scanner//) analiza el texto, y un analizador sintáctico (o //parser//) el que analiza la estructura del texto y realiza las acciones necesarias según esta. El analizador léxico recorre el texto y va pasando las porciones útiles (//tokens//) al parser, este actuará según la estructura en la que estén colocados los tokens. | ||
| - | * Para Java el creador de analizadores léxicos se llama [[#jflex|JFlex]] y el creador de parsers [[#cup|CUP]]. Estas son herramientas a las que se les pasa código y, a partir de este, generan el analizador o el parser. | + | * Para Java el creador de analizadores léxicos se llama [[#jflex|JFlex]] y el creador de parsers [[#cup|CUP]]. Estas son herramientas a las que se les pasa código y, a partir de este, generan el analizador o el parser. |
| + | * Los nombrados anteriormente son versiones de los primeros creadores Lex y Yacc. | ||
| + | * Actualmente existen otros generadores de parsers como son [[http://www.gnu.org/software/bison/|Bison]], [[http://www.antlr.org/|ANTLR]]... | ||
| ===== JFlex ===== | ===== JFlex ===== | ||
| Línea 254: | Línea 256: | ||
| {{otros:compilers:arbol.png?500|}} \\ \\ | {{otros:compilers:arbol.png?500|}} \\ \\ | ||
| Siendo los **símbolos terminales** los elementos que están en las ramas del árbol (paréntesis, números, signos...) y los símbolos** no terminales** los elementos que están en el tronco (código, igualdad, operación...). | Siendo los **símbolos terminales** los elementos que están en las ramas del árbol (paréntesis, números, signos...) y los símbolos** no terminales** los elementos que están en el tronco (código, igualdad, operación...). | ||
| + | |||
| + | |||
| Línea 265: | Línea 269: | ||
| * ''parser.java'' donde estará el código del parser. | * ''parser.java'' donde estará el código del parser. | ||
| * ''sym.java'' donde se definirán todos los símbolos. | * ''sym.java'' donde se definirán todos los símbolos. | ||
| - | Para que JFlex sea compatible con CUP debemos agregar a las instrucciones de generación el parámetro ''%%cup''. | + | Para que JFlex sea compatible con CUP debemos agregar a las instrucciones de generación el parámetro ''%cup''. \\ |
| + | Cuando combinamos los códigos generados por JFlex y CUP el que lanza el analizador léxico ahora es la misma clase parser. El siguiente código sería un ejemplo de inicio de parseo: | ||
| + | <code java> | ||
| + | parser p = null; | ||
| + | Yylex lex = null; | ||
| + | try { | ||
| + | if (args.length == 0) { | ||
| + | System.out.println("Llegint des de l' stream d'entrada: "); | ||
| + | lex = new Yylex(System.in); | ||
| + | } else { | ||
| + | System.out.println("Llegint des del fitxer: " + new java.io.File(args[0]).getAbsolutePath()); | ||
| + | lex = new Yylex(new java.io.FileReader(args[0])); | ||
| + | } | ||
| + | p = new parser(lex); | ||
| + | p.parse(); | ||
| + | catch ... | ||
| + | </code> | ||
| + | Dentro del código JFlex tendremos que retornar objetos ''Symbol'', el constructor de estos, entre otras cosas, recibe un tipo de simbolos (de la lista de símbolos en el archivo ''sym.java'' generado), dos objetos (el left y el right) que luego podremos recoger y el valor. En el siguiente ejemplo cuando se encuentra una definción ".code" se envia que es un símbolo del tipo ''STARTCODE'', el número de línea (como objeto left), nada (como objeto right), y el texto (por si se necesita): | ||
| + | <code> | ||
| + | ".code" { return new Symbol(sym.STARTCODE, yyline + 1, 0, yytext()); } | ||
| + | </code> | ||
| {{otros:compilers:flex_and_cup.tar.gz|Aquí}} un par de ejemplos. | {{otros:compilers:flex_and_cup.tar.gz|Aquí}} un par de ejemplos. | ||
| + | |||
| + | |||
| ==== Código ==== | ==== Código ==== | ||
| + | El código CUP se estructura de la siguiente forma: | ||
| + | - Código Java de fuera de la clase (tipo imports...). | ||
| + | - Código interno de la clase parser y que podrá ser accedido desde el código generado entre: ''parser code {: :}'' | ||
| + | - El action code, entre: ''action code {: :}'' | ||
| + | - El código que define la gramática. | ||
| + | El código que define la gramática comienza con la definición de los nombres de símbolos terminales y no terminales: | ||
| + | <code> | ||
| + | terminal WORD, COMA, NUMBER, DOSPUNTOS, CORCHIZQ, CORCHDER; | ||
| + | terminal STARTPROGRAM, ENDPROGRAM, STARTCODE, ENDCODE, STARTDECVAR, ENDDECVAR, STARTMACRO, ENDMACRO, STARTDECMACRO, ENDDECMACRO; | ||
| + | terminal COMANDO, REGISTRO, TIPO; | ||
| + | nonterminal programa, name, bloccodi, codi, liniacodi, blocvariables, blocmacros, decvars, valor, macro, decmacros, etiqueta; | ||
| + | nonterminal memaddr, operando1, operando2; | ||
| + | </code> | ||
| + | Luego la creación de la gramática se haría con la estructura explicada anteriormente, pero con la siguiente sintaxis: | ||
| + | <code> | ||
| + | PROGRAMA ::= VARBLOCK FUNCBLOCK CODEBLOCK | ||
| + | | VARBLOCK CODEBLOCK | ||
| + | ; | ||
| + | </code> | ||
| + | Además podemos incluir código y leer los tokens pasados por el analizador léxico, por ejemplo podemos leer el contenido de cada token (agregando '':nombre_variable'' tras su definición) o acceder a los objetos left y right con ''nleft'' y ''nright''. | ||
| + | <code> | ||
| + | DEF_FUNC ::= NOMFUNC ID:w PAR_IZQ PAR_DER CORCH_IZQ CODE_BODY CORCH_DER | ||
| + | {: | ||
| + | System.out.println("Se ha definido una función llamada: " + w.toString() + " en linea:" + nleft); | ||
| + | :} | ||
| + | | ... | ||
| + | </code> | ||
| + | |||
| En el ejemplo de la documentación encontramos la definición de la gramática siguiente: | En el ejemplo de la documentación encontramos la definición de la gramática siguiente: | ||
| <code> | <code> | ||
| Línea 298: | Línea 352: | ||
| ; | ; | ||
| </code> | </code> | ||
| - | Corresponde a una lista de expresiones donde | ||
| - | ===== Compiladores con Python ===== | + | |
| - | ===== Compiladores con .NET ===== | + | |
| + | |||
| + | |||
| + | ===== Notas ===== | ||
| + | * La herramienta de Python para generar analizadores léxicos y sintácticos es la denominada PLY (que se encuentra [[http://www.dabeaz.com/ply/index.html|aquí]]), su nombre viene de //Python Lex Yacc//. | ||
| + | |||