Вы находитесь на странице: 1из 5

Analizador lxico, sintctico y semntico con JFlex y

CUP
recipe

Lun, 2007-12-10 21:57 Vigilante

La siguiente receta explica con un ejemplo como construir un analizador lxico con JFlex y
un analizador sintctico y semntico con CUP (obviamente para Java). Adems, muestra el
uso de producciones de error.

Requisitos
jflex - analizador lxico para Java
cup - analizador sintctico/semntico LALR para Java

Construccin
El ejemplo consiste en un conversor de unidades mtricas. Admitira textos de entradas del
siguiente tipo:

Entrada.txt

Km 1 mm;
dm 3 dm;
Hm 393 m;
Dm 54 cm, mm 3429 dm;
Km 23 Dm;
dm 322 cm, Hm 0923 mm;

y devuelve en consola:

1 Km son 1000000 mm;


3 dm son 3 dm;
393 Hm son 39300 m;
...

Un archivo flex tiene la siguiente estructura (cada seccin se separa mediante %%) :

1. Cdigo de usuario
2. Opciones y declaraciones
3. Reglas lxicas

Conversor.lex

//* ------------Seccin codigo-usuario -------- */


import java_cup.runtime.*;
%%
/*- Seccin de opciones y declaraciones -*/
/*-OPCIONES --*/
/* Nombre de la clase generada para el analizador lexico */
%class conversor
/* Indicar funcionamiento autonomo*/
%standalone
%8bit
/* Acceso a la columna y fila actual de analisis CUP */
%line
%column
/* Habilitar la compatibilidad con el interfaz CUP para el generador
sintactico*/
%cup
/*-- DECLARACIONES --*/
%{/*Crear un nuevo objeto java_cup.runtime.Symbol con informacin sobre
el token actual sin valor*/

private Symbol symbol(int type){


return new Symbol(type,yyline,yycolumn);
}
/* Crear un nuevo objeto java_cup.runtime.Symbol con informacin sobre el
token actual con valor*/
private Symbol symbol(int type,Object value){
return new Symbol(type,yyline,yycolumn,value);
}
%}
/*-- MACRO DECLARACIONES --*/
LineTerminator = \r|\n|\r\n
WhiteSpace = {LineTerminator} | [ \t\f]
//finConversion = [,;]
num_int = [0-9]+
%%
/*-------- Seccin de reglas lexicas ------ */
<YYINITIAL> {
//{finConversion}{ return symbol.FCONVERSION}

"," { return symbol(sym.COMA);}


";" { return symbol(sym.PUNTOCOMA);}
"mm" { return symbol(sym.MM); }
"cm" { return symbol(sym.CM); }
"dm" { return symbol(sym.DCM); }
"m" { return symbol(sym.M); }
"Dm" { return symbol(sym.DCAM); }
"Hm" { return symbol(sym.HM); }
"Km" { return symbol(sym.KM); }
{num_int} { return symbol(sym.NUMBER, new Integer(yytext())); }

{WhiteSpace} { }
. {System.out.println("token ilegal <" + yytext()+ "> linea: " +
(yyline+1) + " columna: " + (yycolumn+1));}
}

En cuanto a un fichero CUP se pueden diferenciar cinco partes:


1. Especificaciones de package e imports.
2. Componentes de cdigo de usuario.
3. Lista de smbolos de la gramtica(terminalesno terminales).
4. Declaraciones de precedencia.
5. Especificacin de la gramtica.

Conversor.cup

/*Seccin de declaraciones package e imports*/


import java_cup.runtime.*;
/* Seccin componentes de cdigo de usuario */
parser code {:
public void report_error(String message, Object info) {
StringBuffer m = new StringBuffer("Error");
System.out.println("Mensaje: "+message);
System.out.println("info: "+info.toString());
if(info instanceof java_cup.runtime.Symbol) {
java_cup.runtime.Symbol
s=((java_cup.runtime.Symbol)info);
/* Comprueba si el numero de lnea es mayor o
igual que cero */
if(s.left >= 0) {
m.append(" en linea "+(s.left+1));
/*Comprueba si el numero de columna es
mayoro igual que cero */
if (s.right >= 0)
m.append(", y columna
"+(s.right+1));
}
}
m.append(" : "+message);
System.err.println(m);
}
public void report_fatal_error(String message, Object info) {
report_error(message, info);
System.exit(1);
}

public void conversion(String a, String b, int n){

int c=0,d=0;
System.out.print(n+" ");
if (a=="Km"){ c=6; System.out.print("Km"); }
else if (a=="Hm"){ c=5; System.out.print("Hm"); }
else if (a=="Dm"){ c=4; System.out.print("Dm"); }
else if (a=="m"){ c=3; System.out.print("m"); }
else if (a=="dm"){ c=2; System.out.print("dm"); }
else if (a=="cm"){ c=1; System.out.print("cm"); }
else if (a=="mm"){ c=0; System.out.print("mm"); }

if (b=="Km") d=6;
else if (b=="Hm") d=5;
else if (b=="Dm") d=4;
else if (b=="m") d=3;
else if (b=="dm") d=2;
else if (b=="cm") d=1;
else if (b=="mm") d=0;

System.out.print(" son "+n*Math.pow(10,c-d)+" ");

:};
/* Declaracin de la lista de smbolos de la gramtica */

/* Produciones de flujo normal */


terminal COMA, PUNTOCOMA, MM, DCM, CM, M, DCAM, HM, KM;
terminal Integer NUMBER;
non terminal Object programa, linea, expresiones, medida;

/* Declaracin de la gramtica */
programa ::= programa linea | linea;

linea ::= error NUMBER medida PUNTOCOMA {: parser.report_error("revise la


sintaxis",null); :} |
medida:m1 NUMBER:n medida:m2 PUNTOCOMA {:
parser.conversion(m1.toString(),m2.toString(),n.intValue());
System.out.println(m2); :} |
expresiones medida:m1 NUMBER:n medida:m2 PUNTOCOMA
{: parser.conversion(m1.toString(),m2.toString(),n.intValue());
System.out.println(m2); :} ;

expresiones ::= expresiones medida:m1 NUMBER:n medida:m2 COMA


{: parser.conversion(m1.toString(),m2.toString(),n.intValue());
System.out.println(m2); :} |
medida:m1 NUMBER:n medida:m2 COMA {:
parser.conversion(m1.toString(),m2.toString(),n.intValue());
System.out.println(m2); :} |
error NUMBER medida COMA {: parser.report_error("revise las
medidas en mayusculas",null); :};

medida ::= KM {: RESULT="Km"; :} | HM {: RESULT="Hm"; :} | DCAM {:


RESULT="Dm"; :} |
M {: RESULT="m"; :} | DCM {: RESULT="dm"; :} |
CM {: RESULT="cm"; :} | MM {: RESULT="mm"; :};

Necesitas un fichero que cree un objeto parser y comience el anlisis.

Main.java

import java_cup.runtime.Symbol;
import java.io.*;
class Main {
static boolean do_debug_parse = false;
static public void main(String[] args) throws java.io.IOException {
parser parser_obj = new parser(new conversor(new
FileReader(args[0])));
Symbol parse_tree = null;
try {
if (do_debug_parse)
parse_tree = parser_obj.debug_parse();
else parse_tree = parser_obj.parse();
System.out.println("Entrada correcta");
} catch (Exception e) {
System.out.println("Horror");
}

}
}

Makefile

all: java
javac *.java

java:
jflex *.lex
cup *.cup

clean:
$(RM) *.class
$(RM) parser.java sym.java
$(RM) *~

Вам также может понравиться