Skip to content

Implementación

Una gramática atribuida está formada por dos tablas: una que indica qué atributos se añaden a los nodos del árbol y otra que indica las reglas semánticas que hay que aplicar en los nodos.

Por tanto, implementar una gramática atribuida consiste en implementar cada tabla por separado. Se comenzará implementando en este apartado la tabla de atributos y a continuación, en el siguiente, se implementará la tabla de reglas.

Implementación de la Tabla de Atributos

Implementar una tabla de atributos consiste sencillamente en añadir los atributos indicados en sus filas.

  • Si el atributo se añade a un nodo, hay que añadir dicho atributo y sus métodos de acceso a la clase que implementa dicho nodo.
  • Si el atributo se añade a una categoría, hay que añadir los métodos de acceso al interfaz que implementa dicha categoría y además implementarlos en su clase abstracta.

En el caso de MLang, hay que añadir un atributo varDefinition a la clase variable Variable.

java
public class Variable extends AbstractExpression  {

    ...

	private VarDefinition varDefinition;


	public void setVarDefinition(VarDefinition varDefinition) {
		if (varDefinition == null)
			throw new IllegalArgumentException("Parameter 'varDefinition' can't be null. Pass a non-null value or use 'varDefinition?' in the abstract grammar");
		this.varDefinition = varDefinition;

	}

    public VarDefinition getVarDefinition() {
        return varDefinition;
    }

    ...
}

Lo anterior se puede hacer automáticamente con VGen. Basta con indicar en el fichero de entrada de VGen, /specifications/AbstractGrammar.txt, que la fase de identificación añade un atributo al árbol. Para ello, basta con añadir al final del mismo las dos líneas resaltadas.

java
CATEGORIES
expression;
statement;
type;

NODES
program -> varDefinition* statement*;

varDefinition -> type string;

intType:type -> ;
floatType:type -> ;

print:statement -> expression;
assignment:statement -> left:expression right:expression;

arithmetic:expression -> left:expression operator:string right:expression;
variable:expression -> string;
intLiteral:expression -> int;
floatLiteral:expression -> float;

ATTRIBUTE GRAMMAR Identification
variable -> varDefinition;

Ahora sólo quedaría regenerar el código:

bash
c:\mlang> vgen.bat

El resultado es el mismo que si se hubiera hecho manualmente. Sin embargo, las ventajas de usar VGen son:

  • Queda documentado en /specifications/AbstractGrammar.txt qué atributos añadió cada fase, es decir, dicho fichero es tanto documentación como ejecutable.
  • Si se cambia de idea y se quiere quitar o cambiar algún atributo, sólo hay que indicarlo y regenerar con vgen. No es necesario tocar el código.
  • Si el atributo se añade a una categoría, VGen se encarga de saber a cuántas clases afecta el cambio (interfaces, clases abstractas y clases concretas) incluso aunque haya relaciones de herencia múltiple.

TIP

Se asume que los atributos son sintetizados. Si se quiere indicar expresamente, se puede hacer de la siguiente manera:

java
ATTRIBUTE GRAMMAR Identification
variable -> [syn] varDefinition;

Si se quiere indicar que el atributo es heredado, habrá que hacerlo expresamente:

java
ATTRIBUTE GRAMMAR Identification
variable -> [inh] varDefinition;

El indicar el tipo de atributo se utiliza a la hora de generar los esqueletos de los recorridos, ya que con esta información se genera código adicional que ayuda a detectar si en el visitor se ha olvidado el asignar el atributo en algún sitio en el que se debiera haber hecho.