• No se han encontrado resultados

PROCESADORES DEL LENGUAJES Ev. Alternativa

N/A
N/A
Protected

Academic year: 2021

Share "PROCESADORES DEL LENGUAJES Ev. Alternativa"

Copied!
14
0
0

Texto completo

(1)

PROCESADORES DEL LENGUAJES Ev.

Alternativa 2016-17

NOMBRE: ___________________________________________________________________ GRUPO: _______

EL LENGUAJE LVECT

LVECT es un lenguaje de programación secuencial. El programa LVECT consta de declaraciones de variables y secuencia de asignaciones. Las variables en LVECT pueden ser numéricas o vectores. Las variables numéricas almacenan números naturales. Los vectores se declaran con un rango de índices naturales y almacenan números naturales en sus componentes. Toda variable o componente de vector se considera inicializado a cero tras su declaración. Las expresiones de LVECT son de tipo natural y se definen recursivamente desde números naturales, variables numéricas, componentes de vectores, sumas, restas y multiplicaciones de expresiones y expresiones con paréntesis. A continuación se muestra un programa LVECT.

PROGRAMA VARIABLES x,y,v[2..5],w[1..3],z; ASIGNACIONES v[2] = 1; x = 1; v[3] = x; x = v[2]; v[2] = 1; w[x] = x+1; v[w[x+1]+3] = 2*(v[3]+v[2]); w[v[2]] = 3; SE PIDE:

Analizador sintáctico para el lenguaje LVECT.

Descripciones a entregar: (2 puntos)

[DISEÑO ABSTRACTO] Gramática (independiente de tecnología) para describir la sintaxis del programa LVECT. [IMPLEMENTACIÓN] Parser Antlr implementando la gramática propuesta en el diseño abstracto.

(2)

[DISEÑO ABSTRACTO]

programa : PROGRAMA variables asignaciones

variables : VARIABLES vars PUNTOYCOMA

asignaciones : ASIGNACIONES (asignacion)*

vars : variable COMA vars | variable

variable : IDENT CORCHETEABIERTO NUMERO RANGO NUMERO CORCHETECERRADO | IDENT

asignacion : var_expresion ASIG expresion PUNTOYCOMA

expresion : expresion1 (MAS|MENOS|POR) expresion | expresion1

expresion1 : NUMERO

| var_expresion

| PARENTESISABIERTO expresion PARENTESISCERRADO

var_expresion : IDENT CORCHETEABIERTO expresion CORCHETECERRADO | IDENT

[IMPLEMENTACIÓN]

class AnasintLVECT extends Parser;

programa : PROGRAMA variables asignaciones ;

variables : VARIABLES vars PUNTOYCOMA ;

asignaciones : ASIGNACIONES (asignacion)* ;

vars : (variable COMA) => variable COMA vars | variable

;

variable : (IDENT CORCHETEABIERTO)=> IDENT CORCHETEABIERTO NUMERO RANGO NUMERO CORCHETECERRADO

| IDENT ;

asignacion : var_expresion ASIG expresion PUNTOYCOMA ;

expresion : (expresion1 (MAS|MENOS|POR))=>

expresion1 (MAS|MENOS|POR) expresion | expresion1

;

expresion1 : NUMERO

(3)

| PARENTESISABIERTO expresion PARENTESISCERRADO ;

var_expresion : (IDENT CORCHETEABIERTO) =>

IDENT CORCHETEABIERTO expresion CORCHETECERRADO | IDENT

;

(4)

PROCESADORES DEL LENGUAJES Ev.

Alternativa 2016-17

NOMBRE: ___________________________________________________________________ GRUPO: _______

EL LENGUAJE LOBJ

LOBJ es un lenguaje de programación secuencial orientado a objetos. El programa LOBJ consta de declaraciones de clase, declaraciones de objetos y secuencia de asignaciones. La declaración de clase incluye nombre y conjunto de atributos. El atributo pueden ser entero o de tipo clase. Las expresiones en LOBJ están limitadas a enteros, valores nulos, objetos y selección de atributos. Los atributos se expresan mediante navegaciones al estilo Java. A continuación se muestra un programa LOBJ con errores semánticos.

PROGRAMA CLASES

A[a:entero,objB:B,b:entero], B[objA:A,a:entero], C[objA:A,objB:B]; OBJETOS

oA:A, oB:B, oC:C;

ASIGNACIONES

oA.objB = oB;

oA.objB = oA; // error (a) asignación oA.objB = oA con diferentes tipos oB = oA; // error (a) asignación oB = oA con diferentes tipos oC.objA.c = 1; // error (b) oC.objA.c es un atributo inexistente oC.objA = oA;

oC.objA = 1; //error (a) asignación oC.objA = 1 con diferentes tipos oC.objA.a = 1;

oC.c = oB.b; //error (b) atributo oC.c inexistente //error (b) atributo oB.b inexistente oC.objA.objB.a = 1;

SE PIDE:

Analizador semántico que detecte errores en cada asignación del programa.

Para una asignación dada, el analizador comprobará si hay accesos a atributos inexistentes. Si no hay tales accesos, se comprobará si los tipos en la parte izq y dcha de la asignación son distintos.

Los errores deben ser informados por consola al procesar cada asignación y siguiendo el formato mostrado en el programa de ejemplo.

Descripciones a entregar: (4 puntos) [DISEÑO ABSTRACTO]

Diseño abstracto del analizador semántico. [IMPLEMENTACIÓN]

(1) Gramática sin atribuir que reconozca los árboles de sintaxis abstracta generados por el analizador del Anexo. (2) Atribuir la gramática resultante en (1) con la implementación del diseño abstracto.

(5)

Anexo

class Anasint extends Parser; options{ buildAST = true; k=2; } tokens{ VARIABLE; }

programa : PROGRAMA^ clases objetos asignaciones ;

clases : CLASES^ decl_clases PUNTOYCOMA! ;

objetos : OBJETOS^ decl_objetos PUNTOYCOMA! ;

asignaciones : ASIGNACIONES^ (asignacion)* ;

decl_clases : (decl_clase COMA) => decl_clase COMA! decl_clases | decl_clase

;

decl_objetos : (decl_objeto COMA) => decl_objeto COMA! decl_objetos | decl_objeto

;

decl_clase : IDENT^ CORCHETEABIERTO! decl_atributos CORCHETECERRADO! ;

decl_objeto : IDENT^ DOSPUNTOS! IDENT ;

decl_atributos : (decl_atributo COMA) => decl_atributo COMA! decl_atributos | decl_atributo

;

decl_atributo : IDENT^ DOSPUNTOS! IDENT ;

asignacion : variable ASIG^ expresion PUNTOYCOMA! ; expresion : NUMERO | NULO | variable ;

variable : (IDENT PUNTO) =>

(IDENT PUNTO!)+ IDENT {#variable = #(#[VARIABLE,"VARIABLE"],##);} | IDENT {#variable = #(#[VARIABLE,"VARIABLE"],##);}

(6)

[DISEÑO ABSTRACTO] (DECISIÓN)

(1) El analizador necesitará almacenar la estructura de cada clase: nombre de clase,

nombre de loa atributos y sus tipos. Esta información es necesaria para calcular el tipo de una expresión.

memoria clases:

[clase1 [atributo1.1 tipo1.1] [atributo 1.2 tipo1.2] ... clase2 [atributo2.1 tipo2.1] [atributo 2.2 tipo2.2] ...]

(DECISIÓN)

(2) El analizador necesitará conocer el tipo de cada objeto para poder calcular el

tipo de una expresión. memoria objetos:

[ob1 clase1,....]

(DECISIÓN)

(3) El tipo de un objeto se obtiene consultando la memoria objetos.

El tipo de un atributo se determina accediendo a la memoria objetos y a la memoria clases.

Ejemplo: el tipo de oC.objA.a se determina accediendo sucesivamente a la clase del objeto oC (memoria objetos),

a la clase del atributo objA (memoria clases) y finalmente al tipo del atributo a.

Toda constante numérica es de tipo entero.

El acceso a un atributo inexistente hace indeterminado el tipo de la expresión.

(DECISIÓN)

(4) Para cada asignación se calculará el tipo de la parte izquierda y

el tipo de la expresión a la derecha. Si en el cálculo de dichos tipos, se accede a un atributo inexistente, se informará de error (b) acceso a atributo inexistente.

Si no hay error de acceso a atributo inexistente, se comparará los tipos resultantes. Si no son iguales se informará de error (a) partes izq. y dcha.

con distintos tipos. [IMPLEMENTACIÓN]

Gramática sin atribuir que reconozca los árboles de sintaxis abstracta generados por el analizador del Anexo. class Anasem0LOBJ extends TreeParser;

options{

importVocab=AnasintLOBJ; }

programa : #(PROGRAMA clases objetos asignaciones) ;

(7)

;

objetos : #(OBJETOS decl_objetos) ;

asignaciones : #(ASIGNACIONES (asignacion)*) ; decl_clases : (decl_clase)+ ; decl_objetos : (decl_objeto)+ ;

decl_clase : #(IDENT decl_atributos) ;

decl_objeto : #(IDENT IDENT) ;

decl_atributos : (decl_atributo)+ ;

decl_atributo : #(IDENT IDENT) ;

asignacion : #(ASIG variable expresion) ; expresion : NUMERO | NULO | variable ;

variable: #(VARIABLE seq_id) ;

seq_id : (IDENT)+ ;

Atribuir la gramática resultante en (1) con la implementación del diseño abstracto. header{

import java.util.*; }

class AnasemLOBJ extends TreeParser; options{ importVocab=AnasintLOBJ; } { Map<String,Map<String,String>> clases = new HashMap<String,Map<String,String>>();

Map<String,String> objetos = new HashMap<String,String>();

(8)

void chequear_error_a(String t1, String t2, AST variable, AST expresion){ boolean error_a = false;

if (t1.equals("__indeterminado") | t2.equals("__indeterminado")) error_a = false; else{ if (t1.equals("entero")) if (!t2.equals("entero")) error_a = true; else error_a = false; else if (t2.equals("__cualquiera")) error_a = false; else error_a = !(t1.equals(t2)); } if (error_a)

System.out.println("error (a) asignación "+ convertir_variable(variable)+" = "+

convertir_expresion(expresion)+" con diferentes tipos"); }

String calcular_tipo(AST variable){ AST id = variable.getFirstChild();

String tipo = objetos.get(id.getText()); id = id.getNextSibling();

while (id!=null & !tipo.equals("__indeterminado")){

if (clases.get(tipo).keySet().contains(id.getText())) tipo = clases.get(tipo).get(id.getText());

else{

tipo = "__indeterminado";

System.out.println("error (b) acceso a atributo "+ convertir_variable(variable)+" inexistente"); error_b = true; } id = id.getNextSibling(); } return tipo; }

String convertir_variable(AST variable){ String resultado = new String(); AST it = variable.getFirstChild(); resultado+=it.getText(); it = it.getNextSibling(); while (it!=null){ resultado+="."+it.getText(); it = it.getNextSibling(); } return resultado; }

String convertir_expresion(AST expresion){ String resultado = new String(); switch(expresion.getType()){

case NUMERO: resultado=expresion.getText(); break;

(9)

break;

case VARIABLE: resultado=convertir_variable(expresion); break; default: break; } return resultado; } }

programa : #(PROGRAMA clases objetos asignaciones) ;

clases : #(CLASES decl_clases) ;

objetos : #(OBJETOS decl_objetos) ;

asignaciones : #(ASIGNACIONES (asignacion)*) ; decl_clases : (decl_clase)+ ; decl_objetos : (decl_objeto)+ ;

decl_clase : #(a:IDENT decl_atributos[a]) ;

decl_objeto : #(a:IDENT b:IDENT) {objetos.put(a.getText(),b.getText());} ;

decl_atributos [AST clase]

{Map<String,String>atributos = new HashMap<String,String>();}:

(decl_atributo[atributos])+ {clases.put(clase.getText(),atributos);} ;

decl_atributo [Map<String,String>atributos]: #(a:IDENT b:IDENT) {atributos.put(a.getText(),b.getText());}

;

asignacion {String t1,t2;}: {error_b = false;}

#(ASIG v:variable {t1=calcular_tipo(v);} t2=e:expresion) { chequear_error_a(t1, t2, v, e);}

;

expresion returns [String tipo = new String()]: a:NUMERO {tipo = "entero";}

| b:NULO {tipo = "__cualquiera";} | c:variable {tipo = calcular_tipo(c);} ;

variable : #(VARIABLE s:seq_id) ;

seq_id : (IDENT)+ ;

(10)

PROCESADORES DEL LENGUAJES Ev.

Alternativa 2016-17

NOMBRE: __________________________________________________________________ GRUPO: _______

EL LENGUAJE LEC2

LEC2 es un lenguaje de programación secuencial. Un programa LEC2 está formado por una declaración de contextos y una secuencia de instrucciones. Los contextos son secciones del programa en las que se declaran e inicializan variables con constantes numéricas (ej. x = 5). Un programa LEC puede tener uno o más contextos. Todo programa LEC tiene un contexto

por defecto (ej. DEFECTO 1). Hay dos tipos de instrucciones en LEC2: expresiones aritméticas contextualizadas y selección de contextos por defecto. Las expresiones LEC se construyen con operadores aritméticos, constantes numéricas y variables. Los operadores aritméticos son suma (+), resta (-) y producto (*). Las constantes numéricas son enteros positivos o cero. La variable LEC2 puede referenciar a un contexto (ej. z{2} es una variable del contexto 2) o al contexto por defecto (ej. x).

El siguiente ejemplo muestra un programa escrito en el lenguaje LEC2:

CONTEXTO 1 x = 5; y = 7; z = 1; CONTEXTO 2 x = 9; z = 3; DEFECTO 1 INSTRUCCIONES (x{2} - y) * z; (x{1} + y{1}) * z{2}; DEFECTO 2; (x - z) * z; SE PIDE:

Compilador de programas LEC2 a Java.

Compilar un programa LEC2 (sin errores) significa generar una clase Java con método main(). El código del método main() debe simular la semántica del programa LEC2. Por tanto, la construcción del compilador implicará diseñar la compilación de los contextos, contexto por defecto e instrucciones de un programa LEC2. Compilar una expresiónLEC2 significa generar código Java para la expresión y mostrar el resultado de su evaluación por consola.

Por ejemplo, la expresión (x{2} - y) * z; en el programa de ejemplo debe evaluarse en Java a la constante 2 (justificación: x{2}=9, y=7, z=1).

Por ejemplo, la expresión (x - z) * z; en el programa de ejemplo debe evaluarse en Java a la constante 18 (justificación: x=9, z=3).

Descripciones a entregar: (4 puntos)

[DISEÑO ABSTRACTO] Diseño abstracto del compilador indicando para cada elemento de un programa LEC2 qué código Java le corresponde. Muestre el resultado de su compilación para el programa de ejemplo.

[IMPLEMENTACIÓN] Gramática atribuida del analizador incluyendo la implementación del diseño abstracto. Use la gramática propuesta en Anexo.

(11)

Anexo

class Compilador extends TreeParser; options{

importVocab=Anasint; }

programa : #(PROGRAMA contextos defecto instrucciones) ;

contextos : #(CONTEXTOS (contexto)+) ;

contexto : #(CONTEXTO NUMERO asignaciones) ;

asignaciones : (asignacion)+ ;

asignacion : #(ASIG VARIABLE NUMERO) ;

defecto : #(DEFECTO NUMERO) ;

instrucciones : #(INSTRUCCIONES (instruccion)*) ; instruccion : defecto | expresion ;

expresion : #(MAS expresion expresion) | #(MENOS expresion expresion) | #(POR expresion expresion) | #(LLAVEABIERTA VARIABLE NUMERO) | VARIABLE

| NUMERO

| #(PARENTESISABIERTO expresion)

(12)

[DISEÑO ABSTRACTO] (DECISIÓN)

(1) Programa LEC2 se corresponde con clase Java con main()

(DECISIÓN)

(2) Contexto LEC2 se corresponde con mapa Java declarado como variable local del método main(). La clave de dicho mapa es el número que

identifica el contexto en LEC2 y el valor es otro mapa con clave una cadena de caracteres para identificar las variables del contexto y el valor es de tipo entero para almacenar el valor de tales variables.

(DECISIÓN)

(3) Cada expresión LEC2 genera una expresión entera Java

que será imprimida por consola mediante un código System.out.println.

(DECISIÓN)

(4) La compilación de instrucciones de selección de contexto por defecto no genera

código Java. Se representará por una variable interna del compilador.

Muestre el resultado de su compilación para el programa de ejemplo.

import java.util.*; public class P {

public static void main(String[] args) {

Map<String, Integer>ctxt1 = new HashMap<String, Integer>(); ctxt1.put("x",5);

ctxt1.put("y",7); ctxt1.put("z",1);

Map<String, Integer>ctxt2 = new HashMap<String, Integer>(); ctxt2.put("x",9);

ctxt2.put("z",3);

System.out.println((ctxt2.get("x")-ctxt1.get("y"))*ctxt1.get("z")); System.out.println((ctxt1.get("x")+ctxt1.get("y"))*ctxt2.get("z")); System.out.println((ctxt2.get("x")-ctxt2.get("z"))*ctxt2.get("z")); } } [IMPLEMENTACIÓN] header{ import java.util.*; import java.io.*; }

class CompiladorLEC2 extends TreeParser; options{ importVocab=AnasintLEC2; } { FileWriter f; Integer ctxt_defecto;

void abrir_fichero(String nombre_fichero){ try{

f = new FileWriter(nombre_fichero);

(13)

} void cerrar_fichero(){ try{ f.close(); }catch(IOException e){System.out.println(e.toString());} } void escribir_fichero(String s){ try{ f.write(s); }catch(IOException e){System.out.println(e.toString());} } void escribir_espacios(){ try{ for(int i=0;i<espacios;i++) f.write(' '); }catch(IOException e){System.out.println(e.toString());} } int espacios = 0; void escribir_importaciones(){ escribir_espacios();

String r = new String("import java.util.*;\n\n"); escribir_fichero(r);

}

void escribir_comienzo_clase(){ escribir_espacios();

String r = new String("public class P {\n"); escribir_fichero(r); espacios += 3; } void escribir_fin(){ espacios -= 3; escribir_espacios();

String r = new String("}\n"); escribir_fichero(r);

}

void escribir_comienzo_main(){ escribir_espacios();

String r = new String("public static void main(String[] args) {\n"); escribir_fichero(r);

espacios += 3; }

void declarar_contexto(AST n){ escribir_espacios();

String r = new String("Map<String, Integer>ctxt"+n.getText()+" = "+ "new HashMap<String, Integer>();\n");

escribir_fichero(r); }

void declarar_variable_en_contexto(AST contexto, AST variable, AST numero){

escribir_espacios();

(14)

variable.getText()+"\","+numero.getText()+");\n"); escribir_fichero(r);

}

void generar_codigo_expresion(String expresion){ escribir_espacios();

String r = new String("System.out.println("+expresion+");\n"); escribir_fichero(r);

} }

programa [String nombre_fichero]:

{abrir_fichero(nombre_fichero);} #(PROGRAMA {escribir_importaciones(); escribir_comienzo_clase(); escribir_comienzo_main();} contextos defecto instrucciones)

{escribir_fin();escribir_fin();cerrar_fichero();} ;

contextos : #(CONTEXTOS (contexto)+) ;

contexto : #(CONTEXTO n:NUMERO {declarar_contexto(n);} asignaciones[n]) ;

asignaciones[AST numero]: (asignacion[numero])+ ;

asignacion[AST numero] : #(ASIG v:VARIABLE n:NUMERO) {declarar_variable_en_contexto(numero,v,n);} ;

defecto : #(DEFECTO n:NUMERO) {ctxt_defecto = new Integer(n.getText());} ;

instrucciones : #(INSTRUCCIONES (instruccion)*) ;

instruccion {String r;}: defecto

| r=expresion {generar_codigo_expresion(r);} ;

expresion returns [String r = new String()] {String r1,r2;}: #(MAS r1=expresion r2=expresion){r=r1+"+"+r2;} | #(MENOS r1=expresion r2=expresion){r=r1+"-"+r2;} | #(POR r1=expresion r2=expresion){r=r1+"*"+r2;} | #(LLAVEABIERTA v:VARIABLE n:NUMERO)

{r="ctxt"+n.getText()+".get(\""+v.getText()+"\")";} | w:VARIABLE {r="ctxt"+ctxt_defecto.toString()+".get(\""+w.getText()+"\")";} | m:NUMERO {r=m.getText();} | #(PARENTESISABIERTO r1=expresion) {r="("+r1+")";} ;

Referencias

Documento similar

qrre tiene este Kenl Monasterio (ir Soti I~&gt;ren:o. Es un manuscrito anónimo. y que dehc ser el que redact6 fray Nicolás de Madrid. De él se hilo una ci~pia. ~lr~npir~irkcror,

 Buscar Buque Base, esta botón nos lanzará a un archivo Excel, en donde existe una amplia base de datos de cada tipo de buque, que ayudará al usuario, en el caso

[r]

SVP, EXECUTIVE CREATIVE DIRECTOR JACK MORTON

Social Media, Email Marketing, Workflows, Smart CTA’s, Video Marketing. Blog, Social Media, SEO, SEM, Mobile Marketing,

El discurso de la ciudad existente se hace patente más por la ideología de imágenes que por un preciso análisis histórico, y en este sentido el binomio

ESTRUCTURACIÓN Y ACCESO A LOS CONTENIDOS, LOS RECURSOS DIDÁCTICOS DIGITALES Y SERVICIOS PARA EL APRENDIZAJE. Qué criterios se establecen para la selección, clasificación y acceso

pilares cortos debe evitarse en lo posible (figuras 85, 86 87, 88 y 89), y en todo caso, proporcionar un análisis y posterior diseño especial que aseguren que en caso de fallar