Este ejemplo muestra como realizar un analizador léxico a mano en java, el analizador léxico reconoce los elementos básicos para una calculadora : "+", "-", "*", "/" ademas de números enteros, también se incluye un analizador sintáctico implementado por descenso recursivo para la siguiente gramática
E -> num EP
EP -> "+" num EP
| "-" num EP
| epsilon
el diagrama de estados del analizador léxico es el siguiente, acompañado de su tabla de transiciones.
E -> num EP
EP -> "+" num EP
| "-" num EP
| epsilon
el diagrama de estados del analizador léxico es el siguiente, acompañado de su tabla de transiciones.
public class Lexer { private CharReader mLector = null; private int mNumeroDeLinea = 1; private int mNumeroDeCaracter = 1; private String mLexema = ""; //texto del token private boolean hayError = false; //para saber desde afuera, si hay algun error public static int TOKEN_PALABRA = 1001; public static int TOKEN_COMA = 1002; public static int TOKEN_ESPACIO = 1003; public static int TOKEN_INT = 1004; public static int TOKEN_SUMA = 1005; public static int TOKEN_RESTA = 1006; public static int TOKEN_MUL = 1007; public static int TOKEN_DIV = 1008; public static int TOKEN_FLOAT = 1009; public String getUltimoLexema() { return mLexema; } public Lexer() { } public int getNextToken() { if (mLector == null) { return -1; } char caracterActual; int estadoActual = 0; hayError = false; mLexema = ""; while (mLector.listo()) { caracterActual = peekChar(); if (estadoActual == 0) { //transicion con S if (Character.isWhitespace(caracterActual)) { estadoActual = 1; readChar(); //consumir el caracter } else if (Character.isLetter(caracterActual)) { // estadoActual = 2; readChar(); //consumir el caracter } else if (Character.isDigit(caracterActual)) { // D estadoActual = 3; // este es el estado de numero, el 3 readChar(); //consumir el caracter } else if (caracterActual == '+') { estadoActual = 4; readChar(); //consumir el caracter } else if (caracterActual == '-') { estadoActual = 5; readChar(); //consumir el caracter } else if (caracterActual == '*') { estadoActual = 6; readChar(); //consumir el caracter } else if (caracterActual == '/') { estadoActual = 7; readChar(); //consumir el caracter } else { //llega un caracter que no es valido en este estado hayError = true; readChar(); //quitar el error ( un caracter ) return -1; } } //fin del estado 0 else if (estadoActual == 1) { if (Character.isWhitespace(caracterActual)) { estadoActual = 1; //inncesario pero mas claro si readChar(); //consumir el caracter } else { mLexema = ""; // estadoActual = 0; //return TOKEN_ESPACIO; } } else if (estadoActual == 2) { if (Character.isLetter(caracterActual)) { estadoActual = 2; readChar(); //consumir el caracter } else { return TOKEN_PALABRA; } } else if (estadoActual == 3) { if (Character.isDigit(caracterActual)) { estadoActual = 3;// readChar(); //consumir el caracter } else if (caracterActual == '.') { estadoActual = 8; readChar(); //consumir el caracter } else { return TOKEN_INT; } } else if (estadoActual == 4) { return TOKEN_SUMA; } else if (estadoActual == 5) { return TOKEN_RESTA; } else if (estadoActual == 6) { return TOKEN_MUL; } else if (estadoActual == 7) { return TOKEN_DIV; } else if (estadoActual == 8) { if (Character.isDigit(caracterActual)) { estadoActual = 9; readChar(); //consumir el caracter } else { //error lexico, este no es de aceptacion hayError = true; readChar(); //quitar el error ( un caracter ) return -1; } } else if (estadoActual == 9) { if( Character.isDigit( caracterActual ) ) { estadoActual = 9; // eso falto readChar(); } return TOKEN_FLOAT; } } //caso que llegue hasta aqui , es que no encontro token return -1; } private char peekChar() { if (mLector == null) { //no hay archivo abierto return Character.MIN_VALUE; } if (!mLector.listo()) { //no esta listo return Character.MIN_VALUE; } return mLector.peekNextChar(); } private char readChar() { if (mLector == null) { //no hay archivo abierto return Character.MIN_VALUE; } if (!mLector.listo()) { //no esta listo return Character.MIN_VALUE; } char temp = mLector.ReadNextChar(); //si el caracter actual es ENTER "" == cadenas , '' == caracter if (temp == '\n') { mNumeroDeLinea++; // incrementar en 1 mNumeroDeCaracter = 1; //regresar a 1 } else { mNumeroDeCaracter++; } //concatenar este caracter, a la cadena mLexema mLexema += temp; return temp; } public void inicializar(String pFilePath) { //solo preparar el charReader con el archivo que nos indican mLector = new CharReader(); mLector.inicializar(pFilePath); mNumeroDeLinea = 1; mNumeroDeCaracter = 1; } }
Descargar Codigo Fuente
Comentarios
Publicar un comentario