![]() |
|
|
2ª Parte: Problemas
Duración: | 1 hora 30 minutos |
Puntuación: | 6.5 puntos (sobre 10) |
Fecha: | 19 de septiembre de 2000 |
Nota: | No se podrán usar libros ni apuntes. |
EJERCICIO 1 (2 puntos)
Sea la siguiente gramática: G=<ET, EN, S, P>, ET={a, b, c}, EN={S, A, B}, S=S, P={S -> AB, A -> aA, A -> B, B -> bA, B -> c}. Se pide:
Apartado 1
Esta claro que las cadenas del lenguaje definido por S se forman como concatenación de las cadenas de los lenguajes definidos por A y por B. Si analizamos las reglas de producción, podemos deducir que las cadenas del lenguaje A estan formadas por una secuencia cualquiera de a's y b's (de A -> aA se sigue que si se añade por la izquierda una a a una cadena del lenguaje A se obtiene una cadena del lenguaje A; de A -> B y B -> bA se sigue que si se añade por la izquierda una b a una cadena del lenguaje A se obtiene una cadena del lenguaje A; por tanto si se añade por la izquierda cualquier combinación de a's y b's a una cadena del lengauaje A se obtiene una cadena del lenguaje A), terminada con una c (la única forma de llegar a una derivación sin símbolos no terminales a partir de A es utilizando A -> B -> c). Finalmente, las cadenas del lenguaje B son o la cadena c o b concatenada con cualquier cadena de A. Por lo tanto tenemos:
RFND= <E, Q, f, qi, Qf>
E= {a, b, c}
Q= {q1, q2, q3, q4}
qi= q1
Qf= {q4}
La siguiente gramática define una parte de un lenguaje de programación dedicada a la declaración de tipos: G=<ET, EN, S, P>, ET={NUM, IDENT, TYPE, EQ, ARRAY, COR, CHETE, DOTS, OF, PC, RECORD, END, DP}, EN={<DT>, <DT_List>, <DType>, <DAType>, <DRType>, <RCampos>, <RCampo>}, S=<DT>, P={<DT> -> TYPE <DT_List>, <DT_List> -> <DType> PC <DT_List>, <DT_List> -> <DType>, <DType> -> <DAType>, <DType> -> <DRType>, <DAType> -> IDENT EQ ARRAY COR NUM DOTS NUM CHETE OF IDENT, <DRType> -> IDENT EQ RECORD <RCampos> END, <RCampos> -> <RCampo> PC <RCampos>, <RCampos> -> <RCampo>, <RCampo> -> IDENT DP IDENT}.
El significado de los símbolos terminales es el
siguiente:
Símbolo | Significado | Símbolo | Significado |
NUM | constante entera positiva o cero | IDENT | identificador |
TYPE | palabra clave TYPE | EQ | = |
ARRAY | palabra clave ARRAY | COR | [ |
CHETE | ] | DOTS | .. |
OF | palabra clave OF | PC | ; |
RECORD | palabra clave RECORD | END | palabra clave END |
DP | : |
Se pide:
TYPE T1= ARRAY [0..10] OF Integer; T2= RECORD e1: T1; e2: Boolean END |
package Parser; import java_cup.runtime.*;
parser code {:
public void syntax_error(Symbol s) {
report_error("Error de sintaxis en linea " + s.left, null);
}
public void unrecovered_syntax_error(Symbol s) throws
java.lang.Exception {
report_fatal_error("", null);
}
:};
terminal TYPE, EQ, ARRAY, COR, CHETE, DOTS, OF, PC, RECORD, END, DP; terminal Integer NUM; terminal String IDENT;
...(a)...
...(b)...Solución:
Apartado 1
Nota: El símbolo \ representa la cadena vacía.
Cadena de tokens: TYPE IDENT EQ ARRAY COR NUM DOTS NUM CHETE OF IDENT PC IDENT EQ RECORD IDENT DP IDENT PC IDENT DP IDENT END
Árbol de derivación:
Apartado 3
La gramática que se proporciona es de tipo 2, ya que todas sus reglas son de tipo 2 y existen reglas que no son de tipo 3 (por ejemplo, <DType> -> <DAType>). Sin embargo, el lenguaje que se define es de tipo 3. Esto se puede ver obervando que las cadenas de este lenguaje se pueden formar utilizando los operadores disponibles en expresiones regulares: unión, concatenación y cierres. Para empezar, las cadenas del lenguaje que define la gramática se forman concatenando el simbolo TYPE con cadenas del lenguaje <DT_List>, por lo que el lenguaje que define la gramática es regular si el lenguaje <DT_List> tambien lo es. El lenguaje <DT_List> es exactamente (<DType> PC)* <DType>, luego <DT_List> es regular si <DType> también lo es. El lenguaje que define <DType> es la unión de <DAType> (cuyo lenguaje esta formado por una única cadena) y <DRType>. Luego <DType> es regular si lo es <DRType>. El lenguaje <DRType> es una concatenación de símbolos no terminales y el lenguaje <RCampos>, luego <DRType> sera regular si lo es <RCampos>. El lenguaje <RCampos> es exactamente (<RCampo> PC)* <RCampo>, luego <RCampos> es regular si <RCampo> lo es, pero el lenguaje <RCampo> esta formado por una única cadena, luego es regular igual que <RCampos>, <DRType>, <DType>, <DT_List>, <DT>.
Apartado 4
Nota: Se ha utilizado un mismo interfaz para cada uno de estos conjuntos de símbolos no terminales:
import java.util.*;
public interface DTList {
public Vector ObtenerListaTipos();
}
public interface DType { }
import java.util.*;
public interface ListaCampos {
public Vector ObtenerListaCampos();
}
public interface DCampo { }
import java.util.*;
public class UnTipo implements DTList {
private Vector listaTipos;
public UnTipo(DType tipo) {
listaTipos= new Vector();
listaTipos.addElement(tipo);
}
public Vector ObtenerListaTipos() {
return listaTipos;
}
}
import java.util.*;
public class VariosTipos implements DTList {
private Vector listaTipos;
public VariosTipos(DType tipo, DTList lista) {
listaTipos= lista.ObtenerListaTipos();
listaTipos.addElement(tipo);
}
public Vector ObtenerListaTipos() {
return listaTipos;
}
}
public class Array implements DType {
public String nombre;
public Integer rango1;
public Integer rango2;
public String tipo;
public Array(String n, Integer r1, Integer r2,
String t) {
nombre=n;
rango1=r1;
rango2=r2;
tipo=t;
}
}
public class Record implements DType {
public String nombre;
public ListaCampos lista;
public Record(String n, ListaCampos l) {
nombre=n;
lista=l;
}
}
import java.util.*;
public class UnCampo implements ListaCampos {
private Vector listaCampos;
public UnCampo(DCampo campo) {
listaCampos= new Vector();
listaCampos.addElement(campo);
}
public Vector ObtenerListaCampos() {
return listaCampos;
}
}
import java.util.*;
public class VariosCampos implements ListaCampos {
private Vector listaCampos;
public VariosCampos(DCampo campo, ListaCampos lista)
{
listaCampos= lista.ObtenerListaCampos();
listaCampos.addElement(campo);
}
public Vector ObtenerListaCampos() {
return listaCampos;
}
}
public class RCampo implements DCampo {
public String nombre;
public String tipo;
public RCampo(String n, String t) {
nombre= n;
tipo= t;
}
}
Apartado 5
import AST.*; parser code {: public void syntax_error(Symbol s) { report_error("Error de sintaxis en linea " + s.left, null); } public void unrecovered_syntax_error(Symbol s) throws java.lang.Exception { report_fatal_error("", null); } :}; terminal TYPE, EQ, ARRAY, COR, CHETE, DOTS, OF, PC, RECORD, END, DP; terminal String IDENT; terminal Integer NUM; non terminal DTList DT, DTList; non terminal DType DType; non terminal ListaCampos RCampos; non terminal DCampo RCampo; start with DT; DT ::= TYPE DTList:d {:RESULT=d; :} ; DTList::= DType:d1 PC DTList:d2 {:RESULT=new VariosTipos(d1, d2); :} | DType:d {:RESULT=new UnTipo(d); :} ; DType ::= IDENT:i1 EQ ARRAY COR NUM:n1 DOTS NUM:n2 CHETE OF IDENT:i2 {:RESULT=new Array(i1,n1,n2,i2); :} | IDENT:i EQ RECORD RCampos:r END {:RESULT=new Record(i,r); :} ; RCampos ::= RCampo:r1 PC RCampos:r2 {:RESULT=new VariosCampos(r1,r2); :} | RCampo:r {:RESULT=new UnCampo(r); :} ; RCampo ::= IDENT:i1 DP IDENT:i2 {:RESULT=new RCampo(i1,i2); :} ;