Skip to content

Implementación

Ahora hay que implementar una función que reciba tokens del analizador léxico y determine, mediante la implementación de las reglas de producción, si éstos forman estructuras válidas del lenguaje. Aunque se podría hacer a mano, para acelerar el proceso se utilizará la herramienta Antlr.

Creación del analizador sintáctico con Antlr

Para generar un analizador sintáctico con Antlr, sólo hay que escribir la gramática en el fichero /specifications/Grammar.g4, el cual ahora mismo sólo reconoce enteros. Habría que actualizarlo con la nueva especificación.

Antlr admite tanto notación BNF como EBNF. El elegir una y otra es cuestión de preferencia personal. La versión en BNF sería la siguiente:

antlr
grammar Grammar;

import Lexer;

program: 'DATA' varDefinitions 'CODE' statements EOF;

varDefinitions
	: // empty
    | varDefinitions varDefinition
	;

statements
	: // empty
	| statements statement
	;

varDefinition: type IDENT ';';

type
	: 'float'
	| 'int'
	;

statement
	: 'print' expression ';'
	| expression '=' expression ';'
	;

expression
	: expression ('*' | '/') expression
	| expression ('+' | '-') expression
	| '(' expression ')'
	| IDENT
	| INT_LITERAL
	| FLOAT_LITERAL
	;

La versión en EBNF modificaría la regla program y elimina las reglas varDefinitions y statements, dejando el resto de las reglas igual:

antlr
program: 'DATA' varDefinition* 'CODE' statement* EOF;

// El resto igual
varDefinition: ...
type: ...
statement: ...
expression: ...

TIP

Nótese como la regla de la multiplicación se ha definido antes que la de la suma, para resolver la ambigüedad y dar mayor prioridad a la multiplicación.

Creación del analizador léxico con Antlr

Independientemente de cómo se haya expresado la gramática (en BNF o EBNF), la especificación del analizador léxico será la misma. Esta se hace en el fichero /specifications/Tokenizer.g4:

antlr
lexer grammar Tokenizer;

INT_LITERAL: [0-9]+;
FLOAT_LITERAL: [0-9]+ '.' [0-9]+;

IDENT: [a-zA-Z][a-zA-Z0-9_]*;

LINE_COMMENT: '//' .*? ('\n' | EOF) -> skip;
MULTILINE_COMMENT: '/*' .*? '*/' -> skip;

WHITESPACE: [ \t\r\n]+ -> skip;

Nótese cómo se ha simplificado la especificación del analizador léxico respecto a la del capítulo anterior. Se está aprovechando la funcionalidad de Antlr de poder definir directamente en la gramática, entre comillas simples, los tokens de un único lexema, encargándose él de hacer la definición del token. Se evita asi tener que definir en el léxico tokens como DATA, INT, PRINT, MULT, SEMICOLON, OPEN_PARENTHESIS y otros. Aunque, si se prefiere, se puede seguir haciendo tal y como se hizo en el capítulo anterior.

Uso de Antlr

Una vez modificados los ficheros \specifications\Grammar.g4 y \specifications\Tokenizer.g4, quedaría solamente usar Antlr para generar el código Java correspondiente. Para ello, hay que invocar el siguiente comando:

bash
c:\mlang> antlr.bat

Al hacer esto, aparecerán en la carpeta parser los ficheros GrammarLexer.java (el analizador léxico) y GrammarParser.java (el analizador sintáctico).

WARNING

Información para usuarios de Eclipse. Hay veces en que eclipse no detecta el cambio en un fichero generado por una herramienta y, por tanto, seguirá compilando la versión antigua del mismo. Si esto ocurre, debe seleccionarse el proyecto en la ventana Package Explorer y pulsar F5 para actualizar. En ocasiones, habrá incluso que repetir la pulsación de F5 varias veces.