|
Grado en Ingeniería Informática
Procesadores de Lenguajes
Curso 2022/2023
|
Práctica 8 |
|
El árbol de sintaxis abstracta de Tinto |
|
OBJETIVOS |
- Describir la estructura de datos utilizada en el compilador de Tinto
para almacenar toda la información de cada fichero fuente.
|
|
CÓDIGO A UTILIZAR |
El código de esta práctica añade 26 ficheros al compilador de Tinto, distribuidos en
4
nuevos paquetes.
|
|
ESTRUCTURA DEL CÓDIGO |
La etapa de análisis del compilador de Tinto tiene como
objetivo leer un fichero fuente y generar una estructura de datos que
almacene toda la información contenida en dicho fichero fuente. Esta
estructura de datos se conoce como árbol de sintaxis abstracta o
abstract sintax tree. Las clases utilizadas en el compilador de Tinto
para desarrollar esta estructura de datos se encuentran en el paquete
tinto.ast, que a su vez incluye otros tres subpaquetes. A continuación
se describen estos paquetes:
-
tinto.ast: Es el paquete raíz de todas las
clases utilizadas en la estructura de datos. El paquete sólo contiene las
clases que desarrollan el sistema de tipos, que son utilizadas por muchas de las
clases de los distintos subpaquetes.
-
tinto.ast.expression: Este paquete
contiene las clases dedicadas a describir las diferentes expresiones
aritméticas y lógicas incluidas en el lenguaje Tinto.
-
tinto.ast.statement:
Es el paquete en el que se incluyen las clases que describen las
diferentes sentencias del lenguaje Tinto: (if, while, return, etc.).
-
tinto.ast.struct:
Es el paquete al que pertenecen las clases que describen los
componentes de alto nivel del lenguaje Tinto (bibliotecas, funciones,
etc.).
|
|
DESCRIPCIÓN DEL PAQUETE
tinto.ast |
El paquete
tinto.ast contiene las clases dedicadas a describir
el sistema de tipos del lenguaje Tinto. El
paquete está formado por dos interfaces y una clase.
-
tinto.ast.Access: Es una interfaz que define las constantes usadas para
describir los dos tipos de acceso incluidos en el lenguaje: public y
private.
-
tinto.ast.Type: Es una interfaz que define las constantes utilizadas
para describir los tipos de datos incluidos en el lenguaje Tinto: void,
int, char y boolean.
-
tinto.ast.TypeSystem: Es la clase que desarrolla
los métodos asociados al sistema de tipos del lenguaje. Los
métodos definidos en esta clase son los siguientes:
-
boolean isInteger(int type): Verifica que un tipo sea entero.
-
boolean isBoolean(int type): Verifica que un tipo sea booleano.
-
boolean isChar(int type): Verifica que un tipo sea carácter.
-
boolean isVoid(int type): Verifica que un tipo sea void.
-
boolean isNumeric(int type):Verifica que un tipo sea numérico.
-
boolean isOrderable(int type1, int type2): Verifica que dos
tipos se pueden ordenar con '>' o '<'.
-
boolean isComparable(int type1, int type2): Estudia si dos tipos
de datos pueden compararse con los operadores '=' o '!='.
-
boolean isRegularWord(int type): Verifica que un tipo se represente
en un registro de propósito general de 32 bits.
-
int getSize(int type): Obtiene el tamaño del tipo de datos (en bytes).
|
|
DESCRIPCIÓN DEL PAQUETE
tinto.ast.struct |
El paquete
tinto.ast.struct contiene las clases dedicadas a describir los
componentes de alto nivel (bibliotecas, funciones) del lenguaje Tinto. El
paquete está formado por cuatro clases.
-
tinto.ast.struct.LibraryDeclaration:
Es la clase que contiene toda la información recopilada de un archivo
fuente, es decir, constituye la raíz del árbol de sintaxis abstracta a
construir. Está formada por los siguientes componentes:
-
name: Es el nombre de la biblioteca, que coincide con el
nombre del fichero fuente.
-
imported: Es un vector con los nombres de las diferentes
bibliotecas importadas en el archivo.
-
function: Es un vector que almacena la lista de las descripciones de
las funciones definidas en la biblioteca.
Los
diferentes métodos de la clase se limitan a acceder y a editar estos campos.
-
tinto.ast.struct.Function: Describe una función definida en el
interior de una biblioteca. Contiene los siguientes campos:
-
libname: Es el nombre de la biblioteca a la que pertenece
la función.
-
name: Es el nombre de la función.
-
access: Es el tipo de acceso a la función (público o privado).
-
type: Contiene el tipo de dato que devuelve la función.
-
argument: Contiene la lista de argumentos de llamada de la
función. Cada argumento es un objeto de la clase Variable.
-
localVar: Contiene la lista de variables locales definidas
en el cuerpo del método. Cada variable es un objeto de la clase
Variable.
-
body: Contiene el bloque de instrucciones del método. Es un
objeto de la clase tinto.ast.statement.BlockStatement.
La mayor parte de los métodos de la clase están dedicados a acceder y a
editar estos campos. A continuación se enumeran algunos métodos con una
funcionalidad diferente.
-
int[] getArgumtentTypes(): Obtiene la lista de tipos de
los argumentos. Se utiliza para verificar que no existan dos funciones con
el mismo nombre y los mismos tipos de argumentos.
-
boolean match(String, int[]): Verifica si la función
corresponde a ese nombre y a esos tipos de argumentos.
-
tinto.ast.struct.Variable: Contiene la
descripción de una variable local o un argumento de una función. Los
campos de la clase son los siguientes:
-
tinto.ast.struct.SymbolTable: Es la clase que
desarrolla la tabla de símbolos del compilador. La tabla de símbolos
contiene el conjunto de bibliotecas analizadas por el compilador y
se encarga de identificar la biblioteca y la función que se está analizando
en cada momento. Para esta funcióm , la tabla de símbolos construye
una pila de ámbitos de declaración de variables. Cuando una instrucción de
la función activa abre un nuevo ámbito de declaración (por ejemplo, un bloque
de instrucciones de un while), se apila un nuevo ámbito en esta clase.
Los ámbitos se representan por medio de tablas hash que almacenan los
nombres de las variables y las referencias a los objetos Variable asociados.
Los métodos definidos en esta clase son los siguientes:
-
void addLibrary(LibraryDeclaration lib): Añade una biblioteca
a la tabla de símbolos.
-
LibraryDeclaration getLibrary(String libname): Busca en la tabla
de símbolos una biblioteca con el nombre indicado.
-
LibraryDeclaration getActiveLibrary(): Obtiene la biblioteca activa,
es decir, la biblioteca que se está analizando en ese momento.
-
void setActiveLibrary(String libname): Asigna la biblioteca activa.
-
LibraryDeclaration[] getLibraries(): Obtiene la lista de bibliiotecas
en forma de array.
-
Function getActiveFunction(): Obtiene la función activa,
es decir, la función que se está analizando en ese momento.
-
void setActiveFunction(String name, int[] type): Asigna la función activa.
-
void createScope(): Crea un nuevo ámbito (una tabla hash) y lo
almacena en la cima de la pila.
-
void deleteScope(): Elimina el ámbito almacenado en la cima de la pila.
-
void addLocalVariable(Variable var): Añade una declaración de variable
en la función activa y la almacena en el ámbito de la cima de la pila.
-
void addArgument(Variable var) : Añade un argumento a la función activa
y lo almacena en el ámbito de la cima de la pila.
-
Variable getVariable(String name): Busca una variable con el nombre
indicado en todos los ámbitos de la pila.
-
Variable getVariableInScope(String name): Busca una variable con
el nombre indicado en el ámbito de la cima de la pila.
|
|
DESCRIPCIÓN DEL PAQUETE
tinto.ast.statement |
El paquete
tinto.ast.statement contiene las clases que describen las
diferentes instrucciones del lenguaje Tinto. El contenido del paquete es el
siguiente:
-
tinto.ast.statement.Statement:
Se trata de una clase abstracta que sirve como superclase de cualquier clase
que defina una instrucción. La clase sólo contiene el método abstracto
returns(), que debe verificar si la instrucción alcanza siempre un
return o no (las instrucciones que alcanzan siempre un return son
la propia instrucción return, un bloque de instrucciones que termine
en un return y una instrucción if-else donde las dos opciones
alcancen siempre un return).
-
tinto.ast.statement.IfStatement: Es la clase que describe
una instrucción if. Sus campos son los siguientes:
-
condition: Describe la condición de la instrucción if.
Es una referencia a un objeto Expression. Debe ser de tipo
boolean.
-
thenInst: Describe la instrucción a ejecutar cuando la
condición sea cierta. Es una referencia a un objeto Statement.
-
elseInst: Describe la instrucción a ejecutar cuando la
condición sea falsa. Es una referencia a un objeto Statement. Si
la instrucción no tiene cláusula else el campo debe tener una
referencia nula.
Los métodos de la clase se limitan a asignar y acceder a los valores de
estos campos. El método returns() devuelve cierto si las
instrucciones thenInst y elseInst alcanzan
un return.
-
tinto.ast.statement.WhileStatement: Es la clase
que describe una instrucción while. Está formada por los siguientes
campos:
Los
métodos se limitan a acceder y editar los valores de los campos. El
método returns() devuelve siempre falso.
-
tinto.ast.statement.ReturnStatement: Describe
una instrucción return. Contiene un único campo:
Los
métodos de la clase son los típicos de acceso y edición de este campo.
El método returns() devuelve siempre cierto.
-
tinto.ast.statement.AssignStatement: Es la
clase que describe una instrucción de asignación. Sus campos son:
-
lefthand:
Contiene la referencia a la variable que aparece en la parte izquierda
de la asignación. Es un objeto de la clase Variable.
-
expression:
Representa la parte derecha de la asignación, es decir, la expresión
que permite calcular el valor a asignar. Es una referencia a un objeto
de la clase Expression. El tipo de la expresión debe coincidir
con el tipo de la variable.
El método
returns() devuelve siempre falso. Los demás métodos se limitan
a obtener y asignar los valores de los campos.
-
tinto.ast.statement.CallStatement: Describe una
instrucción de llamada a una función. Está formada por un único campo.
-
tinto.ast.statement.BlockStatement: Es una
clase que describe un bloque de instrucciones. Se suele utilizar como
cuerpo de las instrucciones if y while. Sus campos son:
-
list:
Contiene la lista de instrucciones del bloque, es decir, la lista de
objetos Statement.
-
returns: Es un marcador que indica si el bloque de
instrucciones alcanza siempre un return. Este marcador se
actualiza cada vez que se añade una nueva instrucción al bloque.
El
método más importante es addStatement(Statement), que añade una
nueva instrucción al bloque y actualiza el marcador returns. El
método returns() devuelve el valor del marcador.
|
|
DESCRIPCIÓN DEL PAQUETE
tinto.ast.expression |
El paquete
tinto.ast.expression contiene las clases que permiten
describir los diferentes tipos de expresiones soportadas por el lenguaje
Tinto. Estas expresiones se utilizan como parte derecha en las asignaciones,
como argumentos en las llamadas a funciones y como condiciones en las
instrucciones if y while. El contenido del paquete es el
siguiente:
-
tinto.ast.expression.Expression:
Se trata de una clase abstracta que se utiliza como superclase de todas las
clases que describen expresiones. Su único campo es type, que
contiene el tipo de dato de la expresión. Este tipo se almacena como un
entero y puede tomar los valores definidos en la interfaz tinto.ast.Type.
-
tinto.ast.expression.OperatorExpression:
Es una clase abstracta que encapsula a todas las expresiones que representan
una operación sobre otras expresiones. Esta clase es desarrollada por las
subclases BinaryExpression y UnaryExpression.
-
tinto.ast.expression.LiteralExpression:
Es la clase abstracta que encapsula a todas las expresiones que representan
un valor literal. Esta clase es desarrollada por las
subclases BooleanLiteralExpression, CharLiteralExpression
e IntegerLiteralExpression.
-
tinto.ast.expression.ReferenceExpression:
Se trata de una clase abstracta que encapsula a todas las expresiones que
representan una referencia (a una variable o a una función).
-
tinto.ast.expression.BinaryExpression: Es la clase que
describe expresiones binarias, es decir, expresiones formadas por un
operador y dos operandos. La clase define una serie de constantes para
identificar los diferentes operadores binarios del lenguaje Tinto:
operadores lógicos (AND y OR), operadores aritméticos (PLUS, MINUS, PROD,
DIV y MOD) y operadores de comparación (EQ, NEQ, GT, GE, LT y LE). Los
componentes de la clase son los siguientes:
-
op: Código del operador binario. Su valor debe ser una de
las constantes definidas en la clase.
-
left: Operando de la izquierda de la expresión. Es una
referencia a un objeto Expression.
-
right: Operando de la derecha de la expresión. Es una
referencia a un objeto Expression.
Los métodos de la clase son los getters de estos campos. El tipo
de datos de la expresión se introduce en el constructor.
-
tinto.ast.expression.UnaryExpression: Es
la clase que describe expresiones unarias, es decir, expresiones
formadas por un operador y un único operando. La clase define una serie
de constantes para identificar los diferentes operadores unarios del
lenguaje Tinto: el operador lógico de negación (NOT) y los operadores
aritméticos unarios (PLUS y MINUS). También incluye una constante (NONE)
para indicar que no se aplica ningún operador unario al operando. Los
componentes de la clase son los siguientes:
Los métodos de la clase son los getters de estos campos. El tipo
de datos de la expresión se introduce en el constructor.
-
tinto.ast.expression.BooleanLiteralExpression:
Esta clase permite describir un literal de tipo boolean, es
decir, permite representar las constantes true y false.
Su único campo es value, que almacena el valor del
literal y el único método es el getter de este campo. La clase contiene
dos constructores que permiten construir el literal analizando el
lexema (las cadenas "true" y "false"), o directamente con
el valor. El tipo de datos de la expresión es boolean.
-
tinto.ast.expression.CharLiteralExpression: Es
la clase dedicada a representar literales de tipo carácter. Su único
campo es value, que almacena el valor del literal. La
clase contiene dos constructores: uno basado directamente en el valor
del literal y otro basado en el lexema. Para analizar el lexema se
utiliza el método privado getCharFromString(String), que
analiza las diferentes formas de representar un literal de tipo
carácter definidas en el lenguaje Tinto: caracteres editables (por
ejemplo, 'a'), caracteres no editables descritos con la barra invertida
(por ejemplo, '\n'), caracteres descritos en formato octal (por
ejemplo, '\071') y caracteres descritos en formato unicode (por
ejemplo, '\u007A'). El tipo de datos de la expresión es char.
-
tinto.ast.expression.IntegerLiteralExpression:
Describe literales de tipo entero. Su único campo es value,
que almacena el valor del literal, y su único método es getValue(),
que devuelve el valor de dicho campo. Los constructores permiten crear
los objetos a partir del lexema (por ejemplo, "325"), o directamente a
partir del valor. El tipo de datos de la expresión es int.
-
tinto.ast.expression.CallExpression: Es la
clase que describe una llamada a una función. El tipo de datos de
la expresión corresponde al tipo de datos que devuelve la función. Los
campos de la clase son los siguientes:
-
method:
Es una referencia al objeto Method que describe la función a la
que se llama.
-
library:
Es una referencia al objeto Library en el que está definida la
función a la que se llama, es decir, es una referencia a la biblioteca
a la que pertenece la función.
-
call:
Contiene la descripción de los argumentos de la llamada. Es un objeto
de la clase CallParameters.
-
tinto.ast.expression.CallParameters: Es la única clase del
paquete que no es subclase de Expression. Describe los argumentos de la
llamada a una función, es decir, la lista de expresiones utilizadas en
la definición de la llamada. Su único campo es parameter,
que contiene una lista de expresiones. Los métodos de la clase permiten
añadir expresiones a la lista ( addParameter() ), obtener
la lista ( getParameters() ) y obtener los tipos de datos
de las expresiones ( getTypes() ). Este último método se
utiliza para localizar la versión de la función considerando los tipos
de datos de la llamada. (El lenguaje Tinto soporta la sobrecarga de
funciones, es decir, la definición de funciones con el mismo nombre que
se diferencia en los tipos de datos de sus argumentos).
-
tinto.ast.expression.VariableExpression:
Describe una expresión formada por la referencia a una variable local o
a un argumento del método. Su único campo es var, que
almacena la referencia al objeto Variable que describe la
variable. El tipo de datos de la expresión corresponde al tipo de datos
de la variable.
|
|