14
TECNOLOGICO NACIONAL DE MEXICO Instituto Tecnológico de la Laguna Ingeniería en Sistemas Computacionales LENGUAJES Y AUTOMATAS II SEMESTRE: Ene - Jun / 2015 GRUPO: “A” 10 – 11 Hrs PRACTICA No. P01a P01a - Parser predictivo recursivo del lenguaje SIMPLE ALUMNO: 11130022 Esmeralda Aldaco Balderas 11130036 Eduardo Díaz Salazar 11130601 Anselmo Garcia Espino PROFESOR: Ing. Luis Fernando Gil Vázquez Torreón, Coah. a 17 de Febrero del 2015

Parser predictivo recursivo del lenguaje simple

Embed Size (px)

Citation preview

Page 1: Parser predictivo recursivo del lenguaje simple

TECNOLOGICO NACIONAL DE MEXICO

Instituto Tecnológico de la Laguna Ingeniería en Sistemas Computacionales

LENGUAJES Y AUTOMATAS II

SEMESTRE: Ene - Jun / 2015 GRUPO: “A” 10 – 11 Hrs

PRACTICA No. P01a

P01a - Parser predictivo recursivo del lenguaje SIMPLE

ALUMNO:

11130022 Esmeralda Aldaco Balderas 11130036 Eduardo Díaz Salazar

11130601 Anselmo Garcia Espino

PROFESOR: Ing. Luis Fernando Gil Vázquez

Torreón, Coah. a 17 de Febrero del 2015

Page 2: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 2

Ejercicio 1

Diseñar un Parser Predictivo Recursivo para la siguiente gramática libre de contexto que define un lenguaje básico llamado SIMPLE, el cual permite declarar variables de tipo entero, real y carácter y soporta la sentencia de asignación en el cuerpo principal del programa.

P V C V id : T V | empty

T entero | real | caracter

C inicio S fin

S id opasig E S | empty

E num | num.num

El Parser deberá incluir una modificación a la gramática que permita soportar la sentencia si-entonces que tiene la siguiente estructura sintáctica:

si <condición> entonces

inicio <sentencias>

fin

donde

<condición> := <expresión> oprel <expresión> oprel := > | < | >= | <= | = | <> <expresión> := son las expresiones generadas por el símbolo E

Análisis Es necesario calcular los conjuntos primeros de todas las producciones.

PRIMEROS (P) = {PRIMEROS (V), PRIMEROS (C)}

PRIMEROS (V) = {id, €}

PRIMEROS (T) = {entero, real, caracter}

PRIMEROS (C) = {inicio}

PRIMEROS (S) = {id, si, €}

PRIMEROS (E) = {num, num.num}

Page 3: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 3

Diseño

Procedure P

begin

if preanalisis IN {id} then

begin

//P VC

V

C

end

else if preanalisis == ‘inicio’ then

begin

//P € C

C

end

else

error // error sintáctico

end

Procedure V

begin

if preanalisis == ‘id’ then

begin

//V id : T

emparejar (‘id’)

emparejar (‘:’)

T

end

else

begin

//V €

end

end

Procedure T

begin

if preanalisis == ‘entero’ then

begin

//T entero

emparejar (‘entero’)

end

else if preanalisis == ‘real’ then

begin

//T real

emparejar (‘real’)

end

else if preanalisis == ‘caracter’ then

begin

//T caracter

emparejar (‘caracter’)

end

else

Page 4: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 4

error // error sintáctico

end

Procedure C

begin

if preanalisis == ‘inicio’ then

begin

//C inicio S fin

emparejar (‘inicio’)

S

emparejar (‘fin’)

end

else

error // error sintáctico

end

Procedure S

begin

if preanalisis == ‘id’ then

begin

//S id opasig E S

emparejar (‘id’)

emparejar (‘opasig’)

E

S

end

else if preanalisis == ‘si’ then

begin

//S si E oprel E entonces C S

emparejar (‘si’)

E

emparejar (‘oprel’)

E

emparejar (‘entonces’)

C

S

end

else

begin

//S €

end

end

Page 5: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 5

Procedure E

begin

if preanalisis == ‘num’ then

begin

//E num

emparejar (‘num’)

end

if preanalisis == ‘num.num’ then

begin

//E num.num

emparejar (‘num-num’)

end

else

error // error sintáctico

end

Código

SintacticoSemantico.java

/*:-----------------------------------------------------------------------------

*: INSTITUTO TECNOLOGICO DE LA LAGUNA

*: INGENIERIA EN SISTEMAS COMPUTACIONALES

*: LENGUAJES Y AUTOMATAS II

*:

*: SEMESTRE: ENE-JUN/2015 HORA: 10 - 11 HRS

*:

*:

*: Clase con la funcionalidad del Analizador Sintactico

*

*:

*: Archivo : SintacticoSemantico.java

*: Autor : Fernando Gil ( Estructura general de la clase )

*: Grupo de Lenguajes y Automatas II ( Procedures )

*: Fecha : 03/Sep/2014

*: Compilador : Java JDK 7

*: Descripción : Esta clase implementa un parser descendente del tipo

*: Predictivo Recursivo. Se forma por un metodo por cada simbolo

*: No-Terminal de la gramatica mas el metodo emparejar ().

*: El analisis empieza invocando al metodo del simbolo inicial.

*: Ult.Modif. :

*: Fecha Modificó Modificacion

*:=============================================================================

*: 12/Feb/2015 Eduardo Díaz Se agregaron los procedures correspondientes

*: a la gramatica del lenguaje simple

*: 13/Feb/2015 Eduardo Díaz Se modifico el procedure S y se agrego

*: soporte para que reconociera una sentencia

*: condicional.

*:-----------------------------------------------------------------------------

*/

package compilador;

import javax.swing.JOptionPane;

public class SintacticoSemantico {

private Compilador cmp;

Page 6: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 6

private boolean analizarSemantica = false;

private String preanalisis;

//--------------------------------------------------------------------------

// Constructor de la clase, recibe la referencia de la clase principal del

// compilador.

//

public SintacticoSemantico ( Compilador c ) {

cmp = c;

}

//--------------------------------------------------------------------------

//--------------------------------------------------------------------------

// Metodo que inicia la ejecucion del analisis sintactico predictivo.

// analizarSemantica : true = realiza el analisis semantico a la par del sintactico

// false= realiza solo el analisis sintactico sin comprobacion semantica

public void analizar ( boolean analizarSemantica ) {

this.analizarSemantica = analizarSemantica;

preanalisis = cmp.be.preAnalisis.complex;

P();

// * * * INVOCAR AQUI EL PROCEDURE DEL SIMBOLO INICIAL * * *

}

//--------------------------------------------------------------------------

private void emparejar ( String t ) {

if ( cmp.be.preAnalisis.complex.equals ( t ) ){

cmp.be.siguiente ();

preanalisis = cmp.be.preAnalisis.complex;

}

else

errorEmparejar ( t , cmp.be.preAnalisis.lexema );

}

//--------------------------------------------------------------------------

// Metodo para devolver un error al emparejar

//--------------------------------------------------------------------------

private void errorEmparejar ( String _token, String _lexema ) {

String msjError = "ERROR SINTACTICO: ";

if ( _token.equals ( "id" ) )

msjError += "Se esperaba un identificador";

else if ( _token.equals ( "num" ) )

msjError += "Se esperaba una constante entera";

else if ( _token.equals ( "num.num" ) )

msjError += "Se esperaba una constante real";

else if ( _token.equals ( "literal" ) )

msjError += "Se esperaba una literal";

else if ( _token.equals ( "oparit" ) )

msjError += "Se esperaba un operador aritmetico";

else if ( _token.equals ( "oprel" ) )

msjError += "Se esperaba un operador relacional";

else if ( _token.equals ( "opasig" ) )

msjError += "Se esperaba operador de asignacion";

else

msjError += "Se esperaba " + _token;

msjError += " se encontró " + _lexema;

cmp.me.error ( Compilador.ERR_SINTACTICO, msjError );

}

// Fin de ErrorEmparejar

//--------------------------------------------------------------------------

// Metodo para mostrar un error sintactico

private void error ( String _descripError ) {

cmp.me.error ( cmp.ERR_SINTACTICO, _descripError );

}

// Fin de error

//--------------------------------------------------------------------------

Page 7: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 7

// * * * * PEGAR AQUI EL CODIGO DE SUS PROCEDURES * * * *

//--------------------------------------------------------------------------

// Metodo del procedimiento P

//--------------------------------------------------------------------------

private void P() {

if (preanalisis.equals("id")) {

//P-->VC

V();

C();

} else if (preanalisis.equals("inicio")) {

//P-->emptyC

C();

} else {

error("El programa debe iniciar con una declaracion de una variable o con la palabra inicio");

}

}

// Fin de P

//--------------------------------------------------------------------------

//--------------------------------------------------------------------------

// Metodo del procedimiento V

//--------------------------------------------------------------------------

private void V() {

if (preanalisis.equals("id")) {

//V-->id:T

emparejar("id");

emparejar(":");

T();

V();

} else {

} //V-->empty

}

// Fin de V

//--------------------------------------------------------------------------

//--------------------------------------------------------------------------

// Metodo del procedimiento T

//--------------------------------------------------------------------------

private void T() {

if (preanalisis.equals("entero")) {

//T-->entero

emparejar("entero");

} else if (preanalisis.equals("real")) {

//T-->real

emparejar("real");

} else if (preanalisis.equals("caracter")) {

//T-->caracter

emparejar("caracter");

} else {

error("Error en el tipo de dato de la variable, se esperaba entero, real o caracter");

}

}

// Fin de T

//--------------------------------------------------------------------------

Page 8: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 8

//--------------------------------------------------------------------------

// Metodo del procedimiento C

//--------------------------------------------------------------------------

private void C() {

if (preanalisis.equals("inicio")) {

//C-->inicio S fin

emparejar("inicio");

S();

emparejar("fin");

} else {

error("Error en el cuerpo del programa.");

}

}

// Fin de C

//--------------------------------------------------------------------------

//--------------------------------------------------------------------------

// Metodo del procedimiento S

//--------------------------------------------------------------------------

private void S() {

if (preanalisis.equals("id")) {

//S-->id opasig E S

emparejar("id");

emparejar("opasig");

E();

S();

} else if (preanalisis.equals("si")) {

//S--> si condicinal entonces C

emparejar("si");

E();

emparejar("oprel");

E();

emparejar("entonces");

C();

S();

} else { // S--> empty

}

}

// Fin de S

//--------------------------------------------------------------------------

//--------------------------------------------------------------------------

// Metodo del procedimiento E

//--------------------------------------------------------------------------

private void E() {

if (preanalisis.equals("num")) {

//E-->num

emparejar("num");

} else if (preanalisis.equals("num.num")) {

//E-->num.num

emparejar("num.num");

} else {

error("Error, se esperaba entero o real");

}

}

// Fin de E

//--------------------------------------------------------------------------

//--------------------------------------------------------------------------

}

Page 9: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 9

Lexico.java /*:-----------------------------------------------------------------------------

*: INSTITUTO TECNOLOGICO DE LA LAGUNA

*: INGENIERIA EN SISTEMAS COMPUTACIONALES

*: LENGUAJES Y AUTOMATAS II

*:

*: SEMESTRE: ENE-JUN/2015 HORA: 10 - 11 HRS

*:

*:

*: # Clase que implementa la etapa de Analisis de Lexico

*

*:

*: Archivo : Lexico.java

*: Autor : Fernando Gil

*: Fecha : 03/SEP/2014

*: Compilador : Java JDK 7

*: Descripción :

*:

*:

*: Ult.Modif. :

*: Fecha Modificó Modificacion

*:=============================================================================

*: 12/Feb/2015 Eduardo Díaz Se agregaron las palabras reservadas del

*: lenguaje simple

*: 13/Feb/2015 Eduardo Díaz Se modifico el metodo EsPalabraReservada.

*: Se agrego "si" y "entonces" como soporte

*: de un condicional.

*:-----------------------------------------------------------------------------

*/

package compilador;

public class Lexico {

final int TOKREC = 15;

final int MAXTOKENS = 500;

private String[] _lexemas;

private String[] _tokens;

private String _lexema;

private int _noTokens;

private int _i;

private int _iniToken;

private Automata oAFD;

private Compilador cmp;

//--------------------------------------------------------------------------

public Lexico ( Compilador cmp ) // constructor por defecto

{

this.cmp = cmp;

_lexemas = new String[MAXTOKENS];

_tokens = new String[MAXTOKENS];

oAFD = new Automata();

_i = 0;

_iniToken = 0;

_noTokens = 0;

}

//--------------------------------------------------------------------------

public void Inicia()

{

_i = 0;

_iniToken = 0;

_noTokens = 0;

_lexemas = new String[MAXTOKENS];

_tokens = new String[MAXTOKENS];

}

//--------------------------------------------------------------------------

Page 10: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 10

public void Analiza(String texto)

{

Boolean recAuto;

int noAuto;

while (_i < texto.length())

{

recAuto=false;

noAuto=0;

for(;noAuto<TOKREC&&!recAuto;)

if(oAFD.Reconoce(texto,this,noAuto))

recAuto=true;

else

noAuto++;

if (recAuto)

{

_lexema = texto.substring(_iniToken, _i);

switch (noAuto)

{

//-------------- Automata Delimita--------------

case 0 : //_tokens[_noTokens] = "Delimita";

break;

//-------------- Automata Opmult--------------

case 1 : _tokens[_noTokens] = "opmult";

break;

//-------------- Automata Opsuma--------------

case 2 : _tokens[_noTokens] = "opsuma";

break;

//-------------- Automata Identi--------------

case 3 : _tokens[_noTokens] = "id";

break;

//-------------- Automata Literal--------------

case 4 : _tokens[_noTokens] = "literal";

break;

//-------------- Automata Signo--------------

case 5 : _tokens[_noTokens] = "signo";

break;

//-------------- Automata Opasigna--------------

case 6 : _tokens[_noTokens] = "opasig";

break;

//-------------- Automata Reales1--------------

case 7 : _tokens[_noTokens] = "num.num";//"Reales1";

break;

//-------------- Automata Reales2--------------

case 8 : _tokens[_noTokens] = "num.num";//"Reales2";

break;

//-------------- Automata Reales3--------------

case 9 : _tokens[_noTokens] = "num.num";//"Reales3";

break;

//-------------- Automata Enteros--------------

case 10 : _tokens[_noTokens] = "num";//"Enteros";

break;

//-------------- Automata Oprel--------------

case 11 : _tokens[_noTokens] = "oprel";

break;

//-------------- Automata Oprel2--------------

case 12 : _tokens[_noTokens] = "oprel";

break;

//-------------- Automata CarEsp--------------

case 13 : _tokens[_noTokens] = "caresp";

break;

//-------------- Automata Punto--------------

case 14 : _tokens[_noTokens] = "punto";

break;

}

if(noAuto != 0)

_lexemas[_noTokens++] = _lexema;

}

else

_i++;

_iniToken = _i;

}

//Activar metodo pasarBufferEntrada

pasarBufferTabla ( );

} // fin del método Analiza()

Page 11: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 11

//--------------------------------------------------------------------------

public int getI()

{

return _i;

}

//--------------------------------------------------------------------------

public void setI(int valor)

{

_i=valor;

}

//--------------------------------------------------------------------------

public int getIniToken()

{

return _iniToken;

}

//--------------------------------------------------------------------------

public String[] Tokens()

{

return _tokens;

}

//--------------------------------------------------------------------------

public String[] Lexemas()

{

return _lexemas;

}

//--------------------------------------------------------------------------

public int NOTOKENS()

{

return _noTokens;

}

//--------------------------------------------------------------------------

private Boolean EsPalabraReservada(String lex)

{

String palres[] = { "entero",

"real",

"caracter",

"inicio",

"fin",

"si",

"entonces"

};

for (int i = 0; i < palres.length; i++) {

if (lex.equals ( palres[i] ) ) {

return true;

}

}

return false;

}

//--------------------------------------------------------------------------

Page 12: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 12

// Toma los tokens y los pasa a la tabla de simbolos y buffer de entrada

// Revision en 22/Nov/2012

private void pasarBufferTabla ( )

{

// Comenzamos con establecer la entrada, la l?nea y una bandera para

// palabras reservadas

int entrada = 0;

Linea_BE lineaBE = null;

Linea_TS lineaTS = null;

Boolean noPalres = true;

//tabla de simbolos, linea reservada

lineaTS = new Linea_TS ( "", "", "", "");

entrada = cmp.ts.insertar ( lineaTS );

lineaTS = null;

//Vamos a comparar todos los tokens obtenidos e insertar en la tabla

//de s?mbolos

for ( int i = 0; i < _noTokens; i++ )

{

//Comparando el identificador que no sea palabra reservada

if ( _tokens[ i ].equals ( "id" ) )

{

if(EsPalabraReservada(_lexemas[i])){

lineaBE = new Linea_BE (

_lexemas [ i ], _lexemas [ i ], 0 );

}

else {

lineaTS = new Linea_TS (

_tokens [ i ], _lexemas [ i ], "", "" );

entrada = cmp.ts.insertar ( lineaTS );

lineaBE = new Linea_BE (

_tokens [ i ], _lexemas [ i ], entrada );

}

}

//Variables que deja pasar a tabla de simbolos

else if ( _tokens [ i ].equals ( "num" ) ||

_tokens [ i ].equals ( "num.num" ) ||

_tokens [ i ].equals ( "literal" ) )

{

lineaTS = new Linea_TS (

_tokens [ i ], _lexemas [ i ], "", "" );

entrada = cmp.ts.insertar ( lineaTS );

lineaBE = new Linea_BE (

_tokens [ i ], _lexemas [ i ], entrada );

}

//Los siguientes no se insertan en tabla simbolos

else if ( _tokens [ i ].equals ( "opmult" )

|| _tokens [ i ].equals ( "opsuma" )

|| _tokens [ i ].equals ( "signo" )

|| _tokens [ i ].equals ( "opasig" )

|| _tokens [ i ].equals ( "oprel" ) )

lineaBE = new Linea_BE (

_tokens [ i ], _lexemas [ i ], 0 );

else if ( _tokens [ i ].equals ( "caresp" ) ||

_tokens [ i ].equals ( "punto" ) )

lineaBE = new Linea_BE (

_lexemas [ i ], _lexemas [ i ], 0 );

//Verificar que la línea no está vacía para agregar a la tabla

if ( lineaBE != null )

cmp.be.insertar ( lineaBE );

//Limpiar lineas

lineaBE = null; lineaTS = null;

}

}//Fin del metodo para pasar al buffer entrada y tabla simbolos

//--------------------------------------------------------------------------

Page 13: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 13

}

Prueba de Ejecución

En esta captura se puso a prueba el compilador, se agregaron 2 declaraciones al inicio seguidas de 4 condicionales

con una sentencia dentro cada una. Y El compilador superó la prueba.

Page 14: Parser predictivo recursivo del lenguaje simple

ITL Lenguajes y Automatas II Ene-Jun/2015

Pag. 14

En esta captura a diferencia de la anterior hay dos condicionales y dentro de cada condicional se encuentra otra condicion con su respectiva sentencia cada una. Al fina se agrego una sentencia y el compilador nuevamente pasó

la prueba.

Aquí intencionalmente por motivos de prueba se puso “finww” en lugar de “fin” en el terminador del condicional y el

compilador nos muestra 6 errores.