jueves, 14 de diciembre de 2017

Practica PL1 (UNED - 2017-2018): Parte 1 - Analizador lexico (I)

Empezamos con la explicacion: un compilador se basa en tres analizadores: un analizador lexico que recoge un texto y clasifica lo que va encontrando, caracter a caracter, para enviarlo a un analizador sintactico. Luego el analizador sintáctico lo pasa a un nuevo analizador, el semántico, que verifica si es correcto el programa.

Os pongo un ejemplo mas comprensible, basado en la vida real.

Supongamos que queremos crear un sistema para reconocer frases simples del estilo "Juan es calvo", basadas en la estructura SUJETO - VERBO_ES - COMPLEMENTO_DIRECTO (C_DIRECTO, para abreviar).

Un analizador lexico leeria "Juan", lo clasificaría como "SUJETO" y pasaria ese token a un analizador sintáctico.

Despues, el analizador sintáctico cuando tuviera las tres palabras se encargaria de analizar si cumplen la estructura SUJETO - VERBO_ES - C_DIRECTO. Asi si le llegara la frase "Verde es calvo" detectaría

Mas adelante, un nuevo analizador (el semantico), analizaría frases que sintacticamente son correctas para ver si tienen sentido. Así, "Juan es calvo" sería valida, pero "Juan es morado" no.

-------------------

Ahora nos vamos a centrar en el analizador lexico. Ese analizador lee el texto y realiza el envio en diversas unidades conocidas como "tokens".

En principio, el analizador lexico utiliza un codigo como este para cada token.

Token token = new Token (sym.PLUS);
                           token.setLine (yyline + 1);
                           token.setColumn (yycolumn + 1);
                           token.setLexema (yytext ());
return token;

Nosotros simplificaremos un poco esto, creando una nueva funcion nuevoToken:

// Genera un nuevo Token. Se usa para reducir longitud de codigo.
private Token nuevoToken (int idToken){
Token token = new Token (idToken);
token.setLine (yyline + 1);
token.setColumn (yycolumn + 1);
token.setLexema (yytext ());
return token;
}

Los primeros tokens que vamos a usar son las palabras reservadas. Para que se reconozcan vamos a insertarlos en el archivo scanner.flex, y usaremos los nombres que queramos. Aqui teneis unos ejemplos:

    "AND" {return nuevoToken(sym.AND);}
    "BEGIN" {return nuevoToken(sym.BEGIN);}
    "BOOLEAN" {return nuevoToken(sym.BOOLEAN);}
    "CONST" {return nuevoToken(sym.CONST);}
    "DO" {return nuevoToken(sym.DO);}

Tambien hay que introducir los simbolos que usaremos. Mas ejemplos:

    "+" {return nuevoToken(sym.PLUS);}  
    "/"  {return nuevoToken(sym.DIVIDE);}     
    "(" {return nuevoToken(sym.ABRIR_PAREN);}
    ")" {return nuevoToken(sym.CERRAR_PAREN);}
    "," {return nuevoToken(sym.COMA);}

Podriamos usar otros nombres para los tokens, pero usar los que hay definidos es lo mas sencillo
Y en el archivo parser.cup tambien tendremos que introducirlos. Los tokens son lo que se conoce como "elementos no terminales", asi que para los tokens anteriores agregaremos las siguientes lineas:

terminal Token AND;
terminal Token BEGIN;
terminal Token BOOLEAN;
terminal Token CONST;
terminal Token DO;

Obviamente, no os lo he puesto entero. Tengo que revisar mi practica, ya que la hice en el grupo que me correspondía y me faltan los requisitos del otro grupo. Ya que estoy, completo la practica.

Por hoy lo dejo aquí. En la proxima entrega pondré los tokens correspondientes a los tokens que no son palabras reservadas (identificadores, numeros y demás).

Un saludo.


3 comentarios:

  1. Tengo una nueva duda. Al incluir el método nuevoToken en el archivo scanner.flex se crea el correspondiente método en la clase scanner.java pero me aparecen en esta clase un error relacionado con la clase token que dice lo siguiente : "Token cannot be resolved to a type" en la linea donde se declara el método nuevoToken. Y después, en cada una de las llamadas al método con un argumento del tipo (sym.AND) también reporta un error : "The method nuevoToken(int) from the type Scanner refers to the missing type Token". ¿Me podrías ayudar con esto? he escrito al profesor del equipo docente pero hasta ahora no he recibido respuesta, y había pensado que igual a ti te habría ocurrido algo parecido. Un saludo!

    ResponderEliminar
    Respuestas
    1. Tienes declarado el token en el archivo.cup?

      Eliminar
    2. te refieres a los terminales? Si, están todos declarados.

      Eliminar