Skip to content

Implementación de las Reglas

Para finalizar la etapa de gestión de memoria, queda por implementar el recorrido del árbol siguiendo como guía la tabla de reglas de su gramática atribuida.

De nuevo, al igual que ocurría en etapas anteriores, hay tres opciones:

  • Implementarlo de manera manual.
  • Utilizar la plantilla para crear visitors que VGen ha generado en /vgen.output/skeleton.visitor/ llamada SkeletonForNewVisitors.txt.
  • Definir la gramática atribuida en /specifications/AbstractGrammar.txt para que VGen genere un esqueleto específico para dicha gramática.

Dado que ya se definió una gramática atribuida llamada MemoryAllocation en el fichero de entrada de VGen, se optará de nuevo por la tercera opción.

java
CATEGORIES
...

NODES
program -> ...
...

// -----------------------
ATTRIBUTE GRAMMAR Identification
variable -> varDefinition;

// -----------------------
ATTRIBUTE GRAMMAR TypeChecking
expression -> type;
expression -> lvalue:boolean;

// -----------------------
ATTRIBUTE GRAMMAR MemoryAllocation
varDefinition -> [inh] address:int;    // Inherited attribute

Al hacer lo anterior se obtuvo en /vgen.output/skeleton.attgrammars/ un fichero llamado MemoryAllocation.java. Se muestra a continuación parte de su contenido:

java
public class MemoryAllocation extends DefaultVisitor {

	// class Program(List<VarDefinition> varDefinitions, List<Statement> statements)
	@Override
	public Object visit(Program program, Object param) {

		for (var varDefinition : program.getVarDefinitions()) {
			// TODO: Remember to initialize INHERITED attributes <----
			// varDefinition.setAddress(?);
		}

		super.visit(program, param);

		return null;
	}

    // ... (ommited for brevity)

}

Nótese como en visit(Program) VGen ha añadido comentarios para recordar que hay que inicializar el atributo address. Dado que se definió como heredado, en vez de añadir los recordatorios en el propio nodo varDefinition, los añade en todos los nodos que tengan a este como hijo (añadiendo un bucle para ello si es multivaluado).

La forma de proceder con el esqueleto anterior, de nuevo, es:

  • Copiar todos los métodos visit del esqueleto anterior sobre la clase /src/semantic/MemoryAllocation.java.
  • Borrar todo método visit de nodos que no tengan ninguna regla en su fila de la tabla de reglas.
  • En los métodos restantes, seguir el esquema de implementación de las gramáticas L-atribuidas visto anteriormente.

La clase MemoryAllocation.java, aplicando los pasos anteriores, quedaría así:

java
public class MemoryAllocation extends DefaultVisitor {

    // class Program(List<VarDefinition> varDefinitions, List<Statement> statements)
    @Override
    public Object visit(Program program, Object param) {

        var currentAddress = 0;

        for (var varDefinition : program.getVarDefinitions()) {

            // varDefinition.accept(this, param);

            varDefinition.setAddress(currentAddress);
            currentAddress += varDefinition.getType().getSize();
        }

        return null;
    }

}

Nótese que se ha comentado la llamada a varDefinition.accept(this, param) ya que no hay reglas semánticas en varDefinition que requieran visita. Si se hubiera dejado, aunque hubiera funcionado perfectamente, se estaría realizando un recorrido innecesario del árbol.