17
Traductores DDS con CUP

Traductores DDS con CUP

Embed Size (px)

DESCRIPTION

Traductores DDS con CUP. A ::= L ; A | L ; L ::= L and J | L or J | L nand J | L nor | L xor J | L xnor J | J. J ::= ( L ) | true | false | not ( L ) | C C ::= numero == numero | numero != numero | numero < numero | numero > numero | numero = numero. - PowerPoint PPT Presentation

Citation preview

Traductores DDS con CUP

La gramática

• A ::= L ; A

| L ;

• L ::= L and J

| L or J

| L nand J

| L nor

| L xor J

| L xnor J

| J

• J ::= ( L )

| true

| false

| not ( L )

| C• C ::= numero == numero

| numero != numero

| numero < numero

| numero > numero

| numero <= numero

| numero >= numero

Las acciones semánticas

• A ::= L:ele semicolon

{: System.out.println("\n\nExpresion lógica correcta. Valor final: "+ ele +"\n\n"); :} A

| L:ele semicolon

{: System.out.println("\n\nExpresion lógica correcta. Valor final: "+ ele +"\n\n"); :};

En negrita se muestran las acciones semánticas para cada producción. En este caso podemos ver que el valor del atributo sintetizado de L (ele), es el resultado final de la operación booleana, por tanto es lo que se muestra por pantalla.

Las acciones semánticas

• L ::= L:ele opand J:jota{: boolean resultado;

resultado = (ele && jota); //Operación and de JavaRESULT = resultado; :}

• | L:ele opor J:jota {: boolean resultado;

resultado = (ele || jota); //Operación or de JavaRESULT = resultado; :}

• | L:ele opnand J:jota {: boolean resultado = Boolean.TRUE;

if(ele && jota) //Resultado verdadero siempre que ele y jota no sean verdaderosresultado = Boolean.FALSE;

RESULT = resultado; :}

En estas producciones hay que realizar una operación booleana con los atributos ele y jota. Este resultado se pasa al padre (L) como atributo sintetizado. Este valor se sube a través de la operación:

RESEULT = resultado.

Las acciones semánticas

• | L:ele opnor J:jota {: boolean resultado = Boolean.FALSE;

if(!ele && !jota) //Resultado verdadero si ele y jota son falsosresultado = Boolean.TRUE;

RESULT = resultado; :}

• | L:ele opxor J:jota {: boolean resultado = Boolean.FALSE;

if(ele != jota) //Resultado verdadero si ele y jota son diferentesresultado = Boolean.TRUE;

RESULT = resultado; :}

• | L:ele opxnor J:jota {: boolean resultado = Boolean.FALSE;

if(ele == jota) //Resultado verdadero si ele y jota son igualesresultado = Boolean.TRUE;

RESULT = resultado; :}

• | J:jota{: RESULT = jota; :}

Más operaciones booleanas del mismo tipo que las anteriores. En la última producción simplemente se pasa el resultado que tiene jota al padre L.

Las acciones semánticas• J ::= apertura_parentesis L:ele cierre_parentesis

{: RESULT = ele; :} //Se sintetiza el resultado de la expresión L. Tiene que venir un valor booleano

• | vtrue {: RESULT = Boolean.TRUE; :} //Asignación de valores booleanos a nodos hoja del árbol sintáctico

• | vfalse {: RESULT = Boolean.FALSE; :} //Asignación de valores booleanos a nodos hoja del árbol sintáctico

• | opnot apertura_parentesis L:ele cierre_parentesis {: RESULT = !ele; :} //El valor de la expresión L se niega y se pasa hacia arriba

• | C:ce {: RESULT = ce; :}//El resultado de C se le pasa a J

Las acciones semánticas

• C ::= numero:n1 opigual numero:n2{: int valor1 = Integer.parseInt(n1);

int valor2 = Integer.parseInt(n2);boolean resultado;resultado = (valor1 == valor2);RESULT = resultado; :}

• | numero:n1 opdist numero:n2 {: int valor1 = Integer.parseInt(n1);

int valor2 = Integer.parseInt(n2);boolean resultado;

resultado = (valor1 != valor2);RESULT = resultado; :}

• | numero:n1 opmenor numero:n2 {: int valor1 = Integer.parseInt(n1);

int valor2 = Integer.parseInt(n2);boolean resultado;resultado = (valor1 < valor2);RESULT = resultado; :}

A continuación se muestran las producciones que realizan operaciones con números. Estos operaciones deben devolver un valor booleano, por ese motivo se hace RESULT = resultado, siendo resultado una variable booleana. Los valores n1 y n2 se cogen directamente de la cadena de entrada puesto que numero es un terminal

• | numero:n1 opmayor numero:n2 {: int valor1 = Integer.parseInt(n1);

int valor2 = Integer.parseInt(n2);boolean resultado;resultado = (valor1 > valor2);RESULT = resultado; :}

• | numero:n1 opmenori numero:n2{: int valor1 = Integer.parseInt(n1);

int valor2 = Integer.parseInt(n2);boolean resultado;resultado = (valor1 <= valor2);RESULT = resultado; :}

• | numero:n1 opmayori numero:n2 {: int valor1 = Integer.parseInt(n1);

int valor2 = Integer.parseInt(n2);boolean resultado;resultado = (valor1 >= valor2);RESULT = resultado; :}

Ejemplo

• (true xor false ) and not ( 7 < 4 );

• Para explicar la gramática he cogido un ejemplo que contiene una operación de cada tipo: operaciones lógicas, operaciones relacionales con números, negaciones y paréntesis.

Ejemplo: Árbol sintáctico

En las siguientes imágenes se mostrarán algunas de las producciones que se aplican con sus respectivas acciones semánticas.

Ejemplo: Árbol sintáctico

J ::= vtrue {:RESULT = Boolean.TRUE;:}

Se le da un valor a J y con RESULT lo subimos para arriba.

Ejemplo: Árbol sintáctico

L ::= J:jota{:RESULT = jota;:}

El valor de J se sube a su padre L.

Ejemplo: Árbol sintáctico

El valor de J igual a false se haría de esta forma:RESULT = Boolean.FALSE;

L ::= L:ele opxor J:jota {:boolean resultado = Boolean.FALSE;if(ele != jota)

resultado = Boolean.TRUE;RESULT = resultado;:}

Una vez que se tienen los valores de L y J, valores que son sintetizados, se realiza la operación. Este valor se sube a la L superior.

Ejemplo: Árbol sintáctico

Cuando ya tenemos el resultado de L, simplemente hay que pasárselo a J. Los paréntesis no afectan al valor del atributo sintetizado que se pasa hacia arriba.

J ::= apertura_parentesis L:ele cierre_parentesis {:RESULT = ele;:}

Ejemplo: Árbol sintáctico

Cuando en la cadena de entrada se reciben números, hay que aplicar alguna producción que incluya operadores relacionales. En este caso se aplica la siguiente producción, que calcula el valor y se lo pasa a C.

C := numero:n1 opmenor numero:n2 {:int valor1 = Integer.parseInt(n1);int valor2 = Integer.parseInt(n2);boolean resultado;resultado = (valor1 < valor2);RESULT = resultado;:}

Después este valor se pasará de C a J y de J a L.J ::= C:ce {: RESULT = ce; :}L ::= J:jota {: RESULT = jota; :}

Ejemplo: Árbol sintáctico

Para hacer la negación de un valor, es necesario tener ese valor. Por este motivo hay que esperar a que se calcule el valor de L. Una vez que se tiene, se puede negar y subirlo hacia el padre.

J ::= opnot apertura_parentesis L:ele cierre_parentesis {:RESULT = !ele;:}

Ejemplo: Árbol sintáctico

Cuando ya se tienen los dos operandos de la operación and, esta se realiza y se le asigna al padre.

L ::= L:ele opand J:jota{:boolean resultado;resultado = (ele && jota); RESULT = resultado;:}

Ejemplo: Árbol sintáctico

Cada vez que hasta esta producción suba un valor booleano desde L, se imprimirá por pantalla con el resultado final.

A ::= L:ele semicolon {: System.out.println("\n\nExpresion lógica correcta. Valor final: "+ ele +"\n\n"); :} A

Esta última A recibirá otro valor de L a través de la siguiente producción:A ::= L:ele semicolon {: System.out.println("\n\nExpresion lógica correcta. Valor final: "+ ele +"\n\n");