|
Trabalhos Práticoslinks rápidos: [t1][t2][t3][t4][final] Enunciado do Trabalho Prático 1: (slides [pdf])Objectivo: Construir um interpretador de expressões aritméticas utilizando o gerador de analisadores sintácticos JavaCC. Fase 1: Complete a gramática JavaCC definida no ficheiro G1.jj para aceitar a linguagem CALC cuja sintaxe concreta é a seguinte: exp ::= term ( "+" | "-" ) exp term ::= factor ( "*" | "/" ) term factor ::= num | "(" exp ")"
Utilize a classe Calc, definida no ficheiro Calc1.java que lê uma expressão do Objecto System.in e faz uso da classe Parser produzida pelo JavaCC para validar as expressões. Teste a sua gramática com diferentes expressões. Fase 2: Utilize o resultado da fase 1 e complete a gramática JavaCC definida no ficheiro G2.jj de modo a construir a árvore de sintaxe abstracta da linguagem CALC que se define da seguinte forma: num: integer -> CALC
add: CALC x CALC -> CALC
sub: CALC x CALC -> CALC
mul: CALC x CALC -> CALC
div: CALC x CALC -> CALC
Utilize para o efeito as seguintes classes e interface de exemplo: Implemente as restantes classes necessárias para completar o exercício de construir a AST. Note que as classes devem implementar o interface IASTNode. Fase 3: Finalmente, utilize o método evaluate, que as classes AST implementam, para avaliar as expressões. Modifique o método main do parser para que este receba a AST construída, avalie a expressão e apresente o resultado. Fase 4: Gere o código CIL correspondente à avaliação das expressões. Utilize para o efeito as seguintes classes e interface de exemplo: Implemente as restantes classes e modifique a classe geradora de código CIL de acordo com as necessidades encontradas. Dicas úteis:
Enunciado do Trabalho Prático 2 (slides [pdf]):Objectivo: Estender a linguagem CALC com uma expressão de declaração local de identificadores. Fase 1: Considere a linguagem CALCI, uma extensão da linguagem CALC com identificadores e o operador de declaração decl x = exp1 in exp2 end tal como foi descrito nas aulas teóricas da disciplina. Estenda a
gramática que desenvolveu no trabalho 1 com este operador. num: integer -> CALCI
id: string -> CALCI
add: CALCI x CALCI -> CALCI
sub: CALCI x CALCI -> CALCI
mul: CALCI x CALCI -> CALCI
div: CALCI x CALCI -> CALCI
decl: string x CALCI x CALCI -> CALCI
Implemente de seguida um interpretador para CALCI, usando
ambientes seguindo a técnica apresentada nas aulas teóricas.Fase 2: Generalize a construção decl de modo a que esta suporte declarações multiplas na forma decl id1 = exp1 id2 = exp2 ... idn = expn in E endFase 3: Gere o código CIL de modo a implementar a declaração de identificadores na máquina virtual mono. Para tal utilize a directiva .locals init (int32 var0)para a declaração de variáveis no inicio do ficheiro. Enunciado do Trabalho Prático 3 (slides [pdf]):Objectivo: Estender a linguagem CALCI com operacões imperativas. Fase 1: Considere a linguagem CALCSTATE, uma extensão da linguagem CALCI com as seguintes expressões e comandos
E ::=
E = E
E > E
E & E
not E
var(E)
!E
S ::=
E := E
while E do S end
if E then S else S end
S ; S
decl id1 = E1 id2 = E2 ... idn = En in S end
print(E)
Estenda e adapte a
gramática que desenvolveu no trabalho 2 com estes
novos operadores. Note que agora a linguagem tem DUAS categorias sintacticas
diferentes, para expressões e comandos (EXP e COM). Um programa
é um fragmento fechado da categoria sintáctica COM.
Note tambem que a declaração é
agora um comando e não uma expressão. num: integer -> EXP
id: string -> EXP
add: EXP x EXP -> EXP
sub: EXP x EXP -> EXP
mul: EXP x EXP -> EXP
div: EXP x EXP -> EXP
and: EXP x EXP -> EXP (* E & E *)
not: EXP -> EXP
eq: EXP x EXP -> EXP (* E = E *)
gt: EXP x EXP -> EXP (* E > E *)
var: EXP -> EXP
deref: EXP -> EXP (* !E *)
assign: EXP x EXP -> COM
decl: string x EXP x COM -> COM
while: EXP x COM -> COM
if: EXP x COM x COM -> COM
seq: COM x COM -> COM (* S ; S *)
print: EXP -> COM
Implemente também classes Java para representar os vários
tipos de valores
manipulados pelo interpretador, da forma requerida pela semântica
da linguagem: inteiros, booleanos e referências.Implemente de seguida um interpretador para CALCSTATE, adaptando o modelo de ambiente e memória apresentado nas aulas teóricas e a função de interpretação semântica respectiva da forma que achar mais eficiente. Sugestão: Uma célula de memória pode ser representada por um objecto com métodos set e get. Não implemente nenhum mecanismo de detecção de erros de execução, pelo que um programa pode abortar miseravelmente com uma excepção não tratada! Por exemplo, o programa decl
x = var(2)
y = 3
in
print (x+y)
end
"estoira" na operação de soma, pois
o identificador decl
x = var(0)
in
while (100 > !x) do
x := !x + 1;
print ( !x )
end
end
imprime os números de 1 a 100.Fase 2: Implemente o compilador para esta linguagem. Enunciado do Trabalho Prático 4:Objectivo: Estender a linguagem do trabalho 3 com as operações de abstracção funcional e procedimental. Serão introduzidas expressões sintácticas diferentes para funções (fun) e procedimentos (proc). A sintaxe concreta das mesmas será a seguinte:E ::= ...
(fun x1,x2,...,xn => E)
(proc x1,x2,...,xn => C)
E(E1,E2,...,En)
do C return E end
decl x1=E1, ...,xn=En in E end
C ::= ...
P(E1,E2,...,En)
decl x1=E1, ...,xn=En in C end
A expressão do C return E end tem a seguinte semântica: executar o comando
C e depois avaliar a expressão E, a qual produz o valor
de do C return E end.A expressão decl em que o corpo é uma expressão tem o mesmo significado que na linguagem do exercício 2. Ou seja, voltamos a poder considerar expressões com declarações locais, alem de comandos com declarações locais. Pretende-se também que as declarações possam ser recursivas. Defina os construtores da sintaxe abstracta convenientes e defina as funções de interpretação necessárias. A técnica de interpretação deverá usar fechos (closures), tal como explicado nas aulas teóricas. Eis um exemplo de programa (para ilustrar as construções): decl
Acum = (proc r,v => r := !r + v)
inc = (proc j => Acum (j, 1))
looper = (fun x,f =>
decl
i = var(0)
s = var(0)
in
do
while (!i < x) do
Acum(s,f(!i)) ;
inc(i)
end
return (!s) end
end)
google = (fun x => x * x)
in
print (looper(10,google))
end
Enunciado do trabalho final :versão inicial (1.0), 22 de Novembro 2005: [pdf]
|