Trabalho desenvolvido em conjunto com:
- Luís Godinho 112959;
- Nuno Faria 112994;
- Diogo Guedes 114256;
- José Marques 114321.
Relatório para a linguagem AGL desenvolvido na unidade curricular de Compiladores 2023/2024.
Foi nos proposto, como projeto final, o desenvolvimento de uma linguagem de programação designada por AGL (Animated Graphics Language), bem como as correspondentes ferramentas necessárias para a compilação da mesma, que permita a criação de programas numa linguagem de programação genérica (Python).
Esta linguagem tem como principal funcionalidade permitir a criação e manipulação de figuras gráficas 2D.
Também nos foi proposto desenvolvermos uma linguagem secundária, designada por XAGL, que permite auxiliar a linguagem AGL.
No desenvolvimento do projeto, foi utilizada a ferramenta ANTLR4 como Parser Generator, implementado em Java para a linguagem principal, AGL, e em Python para a linguagem secundária, XAGL.
Foram definidos 3 níveis para a realização deste projeto:
- Nível Mínimo;
- Nível Desejável;
- Nível Adicional;
Foi ainda sugerido a resolução de um desafio.
O nosso grupo conseguiu cumprir totalmente os requisitos definidos no nível mínimo, que consistem em:
-
Definição de uma gramática para a linguagem AGL que suporta:
- Comentários de linha e de bloco;
- Instanciação de uma vista (View);
- Instanciação dos modelos gráficos base Dot, Line, Rectangle, Ellipse, Text, Arc, ArcChord e PieSlice;
- Mover e alterar propriedades dos modelos gráficos;
- Instanciação e expressões envolvendo os tipos de dados Integer, Number, Point, Vector, String e Time;
- Construção with;
- For loop;
-
Verificação semântica da gramática;
-
Definição e implementação de uma gramática secundária para a linguagem AGL, xAGL;
- Instanciação dos modelos gráficos base Polyline, Spline, Polygon e Blob;
- Mover e alterar propriedades dos modelos gráficos mencionados;
- Tipo de dados Boolean;
- Manipulação de expressões booleanas;
- While loop;
- Vetores em coordenadas polares;
- Criação de modelos (Model)
- Tipo de dados iterável Array, com mecanismos de instaciação, acesso e manipulação dos seus elementos (adição e remoção);
- Rotação de objetos Polygon;
view : View with {
[property] = [value];
...
}
Esta view pode ter properties como width, height, definição do ponto central da mesma, title e background.
var : varType = value;
Estas variáveis podem ter tipos como Integer, Number, String, Point, Vector.
[var] : [object] at (x,y) with {
[property] = [value];
...
}
Esta instanciação pode ser realizada de duas formas. Estas são atribuídas a uma variável, ou instanciação sem atribuição e podem ser de vários tipos, como Rectangle, Line, Ellipse, Arc, ArcChord, PieSlice, Text, Dot.
move [view/obj] by (x,y);
Mover uma view ou objeto por x e y pixels.
refresh view [after [time] ms/s];
Atualizar a view, ou seja, faz com que objetos que ainda não estavam visíveis se tornem visíveis. Caso seja especificado um tempo então a view só será atualizada após esse tempo.
wait mouse click;
Espera por um click do mouse para continuar a execução, este retorna o ponto da view onde foi clicado.
close view;
Fecha a view.
for [var] in [value]..[value] do {
[other_instructions]
}
s : Script = “file.xagl”
Esta instrução instância o path para o ficheiro do script.
play s with {
[var] = [my_var]
}
Esta instrução executa o scrip, onde são passadas as variáveis que irão atuar no script.
Construção with
with Identifier ['.'Identifier] do {
[property] = [value]
...
}
Esta construção funciona de forma a que seja possível alterar vários atributos de um determinado objeto. Caso seja um modelo, é necessário aceder ao objeto dentro do mesmo que queremos modificar
Comando Print
print [value]
Com o print, é possível imprimir no terminal o valor de uma variável ou expressão, como um valor de um Array.
Para alem da diferença de a linguagem AGL ser compilada e a linguagem XAGL ser interpretada, esta segunda também não possibilita a instalação de qualquer objeto, variável ou view, sendo apenas utilizada para atuar sobre itens já existentes. Além disso, esta linguagem, assemelha-se bastante à linguagem principal visto que as instruções são iguais, logo não iremos abordar as suas instruções no relatório.
Para este nível, adicionamos novos objetos como Polyline, Spline, Polygon e Blob. Estes objetos são compostos por um ponto inicial e vários pontos sendo estes instanciados da seguinte forma:
[polytype] at (x,y) with {
Point(x1,y1);
Point(x2,y2);
[property] = [value]
...
}
Dependendo do tipo de objeto, como o Spline e o Blob, devem ter as propriedades de Smoothing e Degree.
Criamos um novo tipo de dados sendo estes os Booleans (true e false). A instanciação destes é realizada da mesma maneira da instanciação de qualquer outra variável, ou seja:
[var] : Boolean = [value];
Aqui, foram introduzidos dois tipos de instruções de controlo de fluxo. Ambos funcionam com condições ou com a utilização do tipo Boolean.
Instrução While
Esta itera sobre as intruções interiores enquanto que a condição seja verdadeira.
while [condition] do {
[instruction]
...
}
Instrução If
Esta verifica se a condição passada é verdadeira e dependendo do resultado, esta pode realizar a instrução no seu interior ou continua a sua execução.
if [condition] do
[intruction]
...
else if [condition] do
[instruction]
...
else
[instruction]
...
fi
Estes são compostos por um conjunto de objetos, anteriormente descritos. A sua instanciação segue o modelo:
Pacman :: Model {
face : PieSlice at (0,0) with {
length = (50,50);
fill = "pink";
start = 30;
extent = 300;
}
Ellipse at (20,35) with {
fill = "black";
length = (5,5);
}
}
Este é um modelo Pacman, que é composto por uma PieSlice, que é atribuida à variavel face, e uma Ellipse. Contudo, este não é colocado na View até ser realizada a próxima instrução:
[var] : Pacman at (x,y);
ou seja, é colocado o centro do modelo no ponto especificado.
Para este nível foi adicionada a possibilidade de criar arrays, e de adicionar, remover e aceder aos valores nesse mesmo array.
Criação de um array.
[var] : Array = [<value>, <value>, ...];
Adição de um elemento ao array.
[var].add([value]);
Remoção de um elemento do array.
[var].remove([value]);
Acesso a um elemento do array.
<var>[<index>]
Este para além de ser acedido, pode ser atribuído a uma variável.
Adicionamos também uma instrução para remover objetos da view.
undraw [obj];
rotate [Identifier] by [angle] degrees;
Esta instrução permite rodar um objeto Polygon por um determinado ângulo.
Nesta secção, apresentamos uma explicação sucinta dos erros semânticos que encontramos e que são verificados pelo nosso analisador semântico.
-
Verificação se os elementos do tipo Rectangle, Line, Ellipse possuem a propriedade comprimento;
-
Verificação se os elementos Arc, ArcChord ou PieSlice possuem a propriedade comprimento, início e extend;
-
Verificação se os elementos do tipo Text têm a propriedade Text;
-
Verificação se as variáveis para a construção do with estão definidas;
-
Verificação se o identificador do loop existe;
-
Verificação da duplicação de um objeto;
-
Verificação se a View tem todas as suas propriedades definidas;
-
Verificação se o elemento inserido é do tipo instanciado;
-
Verificação se os elementos do tipo Polygon e Polyline tem a propriedade pontos;
-
Verificação se os elementos Blob e Spline tem as propriedades pontos, smoothing e degree;
-
Verificação se uma certa View existe;
-
Verificação se um input é do tipo desejado.
Para executar o projeto, é necessário:
- Executar o comando
export PYTHONPATH=$PWDna pasta src/ do projeto; - Criar um ficheiro .agl com o código a ser compilado;
- (Opcional) Criar um ficheiro .xagl com o código a ser utilizado como script no código principal;
- Executar o comando
antlr4-build AGL. - Executar o comando
antlr4-build -python XAGL. - Executar o comando
antlr4-run < example.agl. - Executar o comando
python3 output.py.
- Os values referidos anteriormente podem ser valores, variáveis ou expressões matemáticas;