Professional Documents
Culture Documents
Compiladores
PRCTICA OBLIGATORIA
OBJETIVOS ............................................................................................................................................ 1
DESCRIPCIN DEL LENGUAJE A IMPLEMENTAR ...................................................................................... 1
EL COMPILADOR .................................................................................................................................... 1
Programa reconocedor de componentes lxicos.............................................................................. 1
Compilador del lenguaje .................................................................................................................. 4
PRUEBAS DEL COMPILADOR................................................................................................................... 8
NORMAS DE ENTREGA DE LA PRCTICA ................................................................................................. 8
APNDICE 1. LAS HERRAMIENTAS JFLEX Y BYACC/JAVA ...................................................................... 8
JFlex ................................................................................................................................................. 8
Yacc (Byacc/Java) ............................................................................................................................ 9
APNDICE 2. SOFTWARE PARA REALIZAR LA PRCTICA ...................................................................... 10
APNDICE 3. DOCUMENTACIN SOBRE EL LENGUAJE JAVA................................................................. 10
Objetivos
Diseo de una gramtica para un lenguaje propio de programacin sencillo (que
necesariamente ser diferente del lenguaje que mostramos en los ejemplos que se detallan a lo
largo de la descripcin de la prctica)
Implementacin de un programa que reconozca el lxico de un lenguaje, utilizando la
herramienta jflex
Implementacin de un compilador para el lenguaje utilizando las herramientas jflex(lex) y
byacc/JAVA, que son las versiones de lex y yacc que generan Java respectivamente.
y nombres de
El compilador
Implementar un programa que, utilizando jflex y byacc/Java, compile un programa escrito en el
lenguaje diseado. Si algn alumno desea realizar esta practica en C con las herramientas de Unix,
tendr que tener en cuenta las opciones y directivas especficas para ellas. El plan de trabajo se
describe en los apartados posteriores.
programa suma;
variables a,b: vector(5) de entero;
i,res:entero;
# un procedimiento auxiliar
proc inicializar;
a <-- {1,1,1,1,1};
b <-- {1,1,0,1,0} ;
fin;
# programa principal
inicio
i <-- 0;
mq i<5 hacer
res <- res + a[i] * b[i];
i <-- i + 1;
fmq;
fin;
escribir res;
Figura 1. Ejemplo de programa
c:\>
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
Es
un entero: <0>
una llave: <}>
un punto y coma: <;>
una palabra clave: <fin>
un punto y coma: <;>
un comentario: <# programa principal>
una palabra clave: <inicio>
un identificador: <i>
una asignacin: <<-->
un entero: <0>
un punto y coma: <;>
una palabra clave: <mq>
un identificador: <i>
un operador relacional: <<>
un entero: <5>
una palabra clave: <hacer>
un identificador: <res>
un operador relacional: <<>
un operador arimtico: <->
un identificador: <res>
un operador arimtico: <+>
un identificador: <a>
un corchete: <[>
un identificador: <i>
un corchete: <]>
un operador arimtico: <*>
un identificador: <b>
un corchete: <[>
un identificador: <i>
un corchete: <]>
un punto y coma: <;>
un identificador: <i>
una asignacin: <<-->
un identificador: <i>
un operador arimtico: <+>
un entero: <1>
un punto y coma: <;>
una palabra clave: <fmq>
un punto y coma: <;>
una palabra clave: <escribir>
un identificador: <res>
un punto y coma: <;>
una palabra clave: <fin>
un punto y coma: <;>
%%
/* Para utilizar el analizador lxico por separado */
%standalone
IDENT=[a-zA-Z][a-zA-Z0-9_]*
%%
{IDENT}
{
}
Para compilar este programa y ejecutarlo, se procede en los siguientes pasos. Cuando se escribe un
programa en jflex, lo que hay que hacer es compilarlo, utilizando para ello el comando jflex. Como
resultado genera un fichero llamado Yylex.java. Este fichero se compila utilizando el compilador de
Java y como consecuencia se tiene una clase Yylex.class. As para el programa reconoce pedido en
esta prctica se procedera del siguiente modo :
c:\> jflex reconoce.l
c:\> javac Yylex.java
%%
%ignorecase
/* directiva para utilizar jflex con byacc */
%byaccj
/* declaracin de cdigo */
%{
private Parser yyparser;
%}
/* macros */
IDENT =[a-zA-Z][a-zA-Z0-9_]*
NUMERO=[0-9]+
%%
PROGRAMA
System.err.println("Es un <PROGRAMA>");
return Parser.PROGRAMA;
}
{
System.err.println("Es un <PUNTOYCOMA>");
return Parser.PUNTOYCOMA;
}
{
yyparser.yylval = new ParserVal(yytext());
System.err.println("Es un identificador: <" +
return Parser.IDENT;
}
";"
{IDENT}
{NUMERO}
}
[\ \t\r\n]+
try {
yyparser.yylval = new ParserVal(Integer.parseInt(yytext()));
return Parser.NUMERO;
} catch (java.lang.NumberFormatException e) {
return Parser.ILEGAL;
}
{
}
yytext() + ">" );
{}
import java.io.*;
/* declaracion de tokens */
%token PROGRAMA PUNTOYCOMA
%token <sval> IDENT
/* aqui los otros tokens del lenguaje */
/* %type <cadena> sent_asig */
/* aqui al declaracion de las cadenas para las sentencias */
%%
/* codificacion de las producciones de la gramatica del lenguaje */
cabecera : PROGRAMA IDENT PUNTOYCOMA
{
System.out.println("class " + $2 + "{");
System.out.println($2 + "(){");
System.out.println();
System.out.println("}");
System.out.println("public static void main(String[] args) {");
System.out.println($2 + " v = new " + $2 + "();");
System.out.println("}");
System.out.println("}");
}
;
%%
/*.. aqu el cuerpo de los procedimientos para manejar la tabla de smbolos*/
En el ejemplo se ha escrito el cdigo armazn para generar una cabecera de un programa. El cdigo
generado, resultado de ejecutar el compilador sera con un programa que nicamente consistiera de la
cabecera sera:
class suma{
suma(){
}
public static void main(String[] args) {
suma v = new suma();
}
}
Figura 6. Cdigo generado por el compilador
Tanto para las variables como para los procedimientos es necesario definir una tabla de smbolos, en la
que se guardar el nombre de cada smbolo, distinguiendo de qu tipo es y el nombre que tiene.
Cuando se declara una nueva variable o procedimiento, hay que comprobar si ya est declarado antes
(en cuyo caso se emite un mensaje de error). Por otro lado, cuando se usa una variable o un
procedimiento hay que comprobar si existe una variable o procedimiento, respectivamente, con ese
nombre; caso de que no, se emite el correspondiente mensaje de error. Tanto la definicin de la tabla
de smbolos como las funciones y procedimientos necesarios para manejarla se implementaran en Java
en la zona de declaracin de cdigo de usuario, indicada en la figura 5, despus de incluir el cdigo
correspondiente a byacc.
La generacin de cdigo se har en un lenguaje Java, para la cul se explica como generar el cdigo de
un programa vaco. Para generar el cdigo, se asocia a las reglas que correspondan, una accin
semntica que simplemente escriba en el lenguaje elegido, en este caso Java, el trozo de cdigo que
realiza lo que indica la regla. Por ejemplo, si tenemos la siguiente regla
Cabecera PROGRAMA Nombre ;
el
%{
%}
import java.io.*;
/* declaracion de tokens */
%token PROGRAMA PUNTOYCOMA
%token <sval> IDENT
/* aqui los otros tokens del lenguaje */
/* %type <cadena> sent_asig */
/* aqui al declaracion de las cadenas para las sentencias */
%%
/* codificacion de las producciones de la gramatica del lenguaje */
cabecera : PROGRAMA IDENT PUNTOYCOMA
{
System.out.println("class " + $2 + "{");
System.out.println($2 + "(){");
System.out.println();
System.out.println("}");
%%
/*.. aqu el cuerpo de los procedimientos para manejar la tabla de smbolos*/
/* definicin analizador lxico */
private Yylex lexer;
/* yylex(): utliza el analizador lxico */
private int yylex () {
int yyl_return = -1;
try {
yylval = new ParserVal(0);
yyl_return = lexer.yylex();
}
catch (IOException e) {
System.err.println("IO error :"+e);
}
return yyl_return;
}
/* Mtodo para manejar errores */
public void yyerror (String error) {
System.err.println ("Error: " + error);
}
/* Constructor: inicializa el analizador lxico */
public Parser(Reader r) {
lexer = new Yylex(r, this);
}
/* main */
public static void main(String args[]) throws IOException {
Parser yyparser;
if ( args.length > 0 ) {
// parse a file
yyparser = new Parser(new FileReader(args[0]));
yyparser.yyparse();
} else {
}
Figura 7. Listado de un ejemplo del fichero compilador.y
JFlex
En relacin a aspectos derivados de la programacin en JFlex, cabe destacar :
La estructura de un fichero JFLEX es:
Cdigo de usuario
%%
opciones y declaraciones
%%
reglas lxicas
Para devolver un token se hace con return nombre-de-token.
Cuando se reconoce un token NUMERO, no basta con que jflex devuelva que es un token
NUMERO sino que adems debe devolver el valor de ste. Esto se hace con la siguiente accin,
cuando se reconoce la expresin regular correspondiente a un numero:
{
try {
yyparser.yylval = Interger.parser(yytext());
return Parser.NUMERO;
} catch (java.lang.NumberFormatException e) {
return Parser.ILEGAL;
}
Cuando se reconoce un token de tipo identificador, hay que devolver que es un token IDENT, y
el nombre de ste. Cuando se reconoce la expresin regular correspondiente a un
identificador, se tiene que ejecutar la siguiente accin:
{
yytext() + ">" );
Los comentarios se tratan en el analizador lxico. Para ello se incluye el siguiente par
expresin-regular/accin donde salta todos los caracteres despus del carcter # y hasta que
llega a salto de lnea ; y como accin no realiza nada
"#"[^\n\r]*
{}
Para compilar cdigo en jflex y generar cdigo en Java o cualquier otro lenguaje:
Cuando se escribe un programa en jflex, lo que hay que hacer es compilarlo, utilizando para ello el
comando jflex <fichero.l>. Como resultado genera un fichero Yylex.java. Este fichero se compila
utilizando el compilador de Java y como consecuencia se tiene una clase. As para el programa
reconoce pedido en esta prctica se procedera del siguiente modo :
c:\> jflex reconoce. l
c:\> javac Yylex.java
c:\> java cp . Yylex
Yacc (Byacc/Java)
Con relacin a aspectos de programacin:
La estructura de un fuente byacc/Java es:
declaraciones
%%
acciones
%%
cdigo de usuario
Yylex.class).
c:\> java cp . Parser suma.cal
(Compila
pantalla)
el programa
suma.cal.
10