Skip to content

Ejecución

Para probar el analizador léxico se incluye en input.txt un programa que tiene todos los tokens del lenguaje:

java
// One-line comment

/*
 Multi-line comment
 */

DATA
	float price;
	int width;

CODE
	price = (width - 3.0) * 1.18;
	print price + 2 / 5;

Importante. Ahora no se debe ejecutar la clase main.Main. Si se hace, aparecerá el siguiente mensaje de error:

bash
Compiler started.

line 7:0 mismatched input 'DATA' expecting INT_LITERAL
Compilaton finished due to syntax errors.

1 errors detected.

Compiler finished.

Esto es debido a que main invoca al analizador sintáctico y este todavía no se ha hecho implementado. El sintáctico actualmente implementado (que se copió con del esqueleto) sólo reconoce literales enteros. Es por ello que, al redibir del léxico el token DATA en vez de un entero, notifica un error sintáctico.

En lugar de lo anterior, hay dos formas para poder comprobar la salida del léxico. La primera (y más cómodoa) es usar un comando que se obtuvo en el esqueleto del compilador:

bash
c:\mlang> antlr_tokens.bat input.txt

Esto imprime los tokens reconocidos en dicho fichero fuente:

bash
[@0,55:58='DATA',<'DATA'>,7:0]
[@1,62:66='float',<'float'>,8:1]
[@2,68:72='price',<IDENT>,8:7]
[@3,73:73=';',<';'>,8:12]
[@4,77:79='int',<'int'>,9:1]
[@5,81:85='width',<IDENT>,9:5]
[@6,86:86=';',<';'>,9:10]
[@7,91:94='CODE',<'CODE'>,11:0]
[@8,98:102='price',<IDENT>,12:1]
[@9,104:104='=',<'='>,12:7]
[@10,106:106='(',<'('>,12:9]
[@11,107:111='width',<IDENT>,12:10]
[@12,113:113='-',<'-'>,12:16]
[@13,115:117='3.0',<FLOAT_LITERAL>,12:18]
[@14,118:118=')',<')'>,12:21]
[@15,120:120='*',<'*'>,12:23]
[@16,122:125='1.18',<FLOAT_LITERAL>,12:25]
[@17,126:126=';',<';'>,12:29]
[@18,130:134='print',<'print'>,13:1]
[@19,136:140='price',<IDENT>,13:7]
[@20,142:142='+',<'+'>,13:13]
[@21,144:144='2',<INT_LITERAL>,13:15]
[@22,146:146='/',<'/'>,13:17]
[@23,148:148='5',<INT_LITERAL>,13:19]
[@24,149:149=';',<';'>,13:20]
[@25,152:151='<EOF>',<EOF>,14:0]
line 7:0 mismatched input 'DATA' expecting INT_LITERAL

Nótese que en la última línea anterior sigue saliendo el error sintáctico. Esto es normal ya que, después de imprimir la traza, intenta comenzar el análisis sintáctico. Simplemente hay que ignorar dicho error.

La segunda forma, por si se tiene curiosidad, sería haciendo a mano lo que hace el comando antlr_tokens.bat. Habría que hacer otro main que llame directamente al léxico en vez de llamar al sintáctico.

java
package main;

import org.antlr.v4.runtime.*;

import parser.GrammarLexer;

public class LexerTester {
    public static void main(String[] args) throws Exception {

        CharStream input = CharStreams.fromFileName("input.txt");
        GrammarLexer textLexer = new GrammarLexer(input);
        Token token;
        while ((token = textLexer.nextToken()).getType() != GrammarLexer.EOF) {
            System.out.printf(
                "Line: %d \tcolumn: %d \tlexeme: '%s' \t\ttype: %d, \t token: %s%n",
                token.getLine(),
                token.getCharPositionInLine() + 1,
                token.getText(),
                token.getType(),
                textLexer.getVocabulary().getDisplayName(token.getType()));
        }

        System.out.println("Traza lexer finalizada");
    }
}

Si se ejecuta esta clase en vez de la que se haya en la carpeta main, se obtendrá la traza del analizador léxico buscada.

bash
Line: 7     column: 1     lexeme: 'DATA'    type: 1,     token: 'DATA'
Line: 8     column: 2     lexeme: 'float'   type: 5,     token: 'float'
Line: 8     column: 8     lexeme: 'price'   type: 8,     token: IDENT
Line: 8     column: 13    lexeme: ';'       type: 14,    token: ';'
Line: 9     column: 2     lexeme: 'int'     type: 4,     token: 'int'
Line: 9     column: 6     lexeme: 'width'   type: 8,     token: IDENT
Line: 9     column: 11    lexeme: ';'       type: 14,    token: ';'
Line: 11    column: 1     lexeme: 'CODE'    type: 2,     token: 'CODE'
Line: 12    column: 2     lexeme: 'price'   type: 8,     token: IDENT
Line: 12    column: 8     lexeme: '='       type: 13,    token: '='
Line: 12    column: 10    lexeme: '('       type: 15,    token: '('
Line: 12    column: 11    lexeme: 'width'   type: 8,     token: IDENT
Line: 12    column: 17    lexeme: '-'       type: 11,    token: '-'
Line: 12    column: 19    lexeme: '3.0'     type: 7,     token: FLOAT_LITERAL
Line: 12    column: 22    lexeme: ')'       type: 16,    token: ')'
Line: 12    column: 24    lexeme: '*'       type: 10,    token: '*'
Line: 12    column: 26    lexeme: '1.18'    type: 7,     token: FLOAT_LITERAL
Line: 12    column: 30    lexeme: ';'       type: 14,    token: ';'
Line: 13    column: 2     lexeme: 'print'   type: 3,     token: 'print'
Line: 13    column: 8     lexeme: 'price'   type: 8,     token: IDENT
Line: 13    column: 14    lexeme: '+'       type: 9,     token: '+'
Line: 13    column: 16    lexeme: '2'       type: 6,     token: INT_LITERAL
Line: 13    column: 18    lexeme: '/'       type: 12,    token: '/'
Line: 13    column: 20    lexeme: '5'       type: 6,     token: INT_LITERAL
Line: 13    column: 21    lexeme: ';'       type: 14,    token: ';'
Traza lexer finalizada

Traza del analizador léxico

Durante la implementación de fases posteriores del compilador, es posible que al compilar un fichero de prueba se reciban errores que no se esperaban. En estos casos, para averiguar qué está yendo mal, es conveniente ir acotando por fases.

Lo primero que hay que descartar es que el léxico esté clasificando mal la entrada antes de hacer cambios en el sintáctico. Ahí es donde se recomienda usar antlr_tokens.bat para averiguar qué está entregando el léxico al sintáctico y así poder comprobar si el problema está en el analizador léxico o no.