O objetivo deste laboratório é exercitar a criação de interfaces e classes que as implementam. Vocês farão isso no contexto da implementação de um interpretador, um programa que executa programas.
As construções dos programas que vamos executar serão modeladas como instâncias de classes, mas as construções do programa se dividem em dois tipos mais abstratos, Expressões e Comandos, que iremos modelar com interfaces. A implementação dos métodos dessas interfaces se tornará a implementação do interpretador.
MicroJava é uma linguagem de programação bem simples, mas
relativamente completa, onde pegamos um subconjunto de Java
contendo expressões aritméticas simples (soma, subtração,
multiplicação, divisão), variáveis e atribuição (mas sem declarações
e tipos; todas as variáveis são do tipo double
), entrada e
saída simples através de comandos readDouble
e println
, testes
if
e laços while
. Por exemplo, o programa MicroJava
abaixo calcula o fatorial de um número pedido na entrada e o
mostra na saída:
Reparem que não é necessário declarar as variávieis x
e fact
, muito
menos declarar classes e métodos. Um programa MicroJava é simplesmente uma
sequência de comandos MicroJava.
Nesse laboratório vocês irão implementar classes que modelam a estrutura
de um programa MicroJava, e métodos para executar expressões e comandos MicroJava.
As estruturas de um programa MicroJava se dividem em dois grupos, expressões
e comandos, então comece definindo as interfaces Expressao
e
Comando
, inicialmente vazias.
Agora vamos implementar as classes que modelam expressões. Todas elas devem
implementar a interface Expressao
. Os campos de cada classe estão implícitos
na sua descrição. Não se esqueça de implementar um construtor também. As
classes são:
Num
modela um numeral, e contém o valor do mesmo (um double
). No programa
acima, 0 e 1 são instâncias de Num
.
Var
modela uma variável, e contém o nome da variável. No programa acima, x
e fact
são instâncias de Var
.
Soma
, Sub
, Mul
e Div
modelam as quatro operações aritméticas, e
contêm duas expressões, para o lado esquerdo e o lado direito da
operação. No programa acima, fact * x
é uma instância de Mul
e x - 1
é uma instância de Sub
.
Igual
e Menor
modelam as operações de comparação, e também contêm
expressões para o lado esquerdo e direito da operação. No programa acima,
0 < x
e 0 < fact
são instâncias de Menor
.
LeNumero
modela uma expressão de entrada, e não contém nennum campo.
No programa acima a readDouble()
é uma instância de LeNumero
.
Agora vocês irão adicionar um método
double valor(HashMap<String, Double> vars)
à interface Expressao
,
e implementar esse método para
todas as classes acima. Nas operações de comparação valor()
deve
retornar 0 se a operação for falsa e 1 se for verdadeira, pois MicroJava
não possui valores booleanos. O mapa vars
passado associa nomes de
variáveis aos seus valores. Se uma variável não está nesse mapa então seu
valor é 0.
As classes a seguir modelam os comandos. Todas elas implementam a
interface Comando
. Implemente as classes, declarando seus campos
e seu construtor:
Imprime
modela um comando de escrita, e contém a expressão cujo valor
será escrito. No programa acima, println(fact);
é uma instância de Imprime
.
Atrib
modela um comando de atribuição, e contém o nome da variável a ser
atribuída e a expressão cujo valor será atribuído. No programa acima,
x = readDouble();
, fact = 1;
, fact = fact * x
e x = x - 1
são todos
instâncias de Atrib
.
If
modela um comando if/then/else
, e contém a expressão de teste e
dois comandos, um para a parte then
e outro para a parte else
. Tudo entre
a segunda e a última linhas no programa acima é uma instância de If
.
While
modela um comando while
, e contém um comando para o
corpo do laço e uma expressão para a condição do laço. Tudo entre as linhas
4 e 7 do programa acima é uma instância de While
.
Bloco
modela uma sequência de comandos, e contém um vetor de comandos.
O programa exemplo mostrado no início dessa página é uma instância de Bloco
com dois comandos,
uma atribuição e um if
. O corpo do If
é um bloco com três comandos, uma
atribuição, um while
e um println
, e o corpo do while
é um bloco com
dois comandos, ambos de atribuição.
Finalmente, adicionem um método void executa(HashMap<String, Double> vars)
à
interface Comando
, e implementem esse método para todas as classes
acima. Usem a sua intuição e seus conhecimentos de programação para
pensar sobre como cada comando funciona. Novamente, vars
é um mapa de nomes
de variáveis para seus valores.
Dica: o código abaixo irá te ajudar na implementação do método
valor()
da classe LeNumero
:
O trecho de código a seguir instancia um programa MicroJava com a estrutura
do programa fatorial acima. Note como é passado um bloco vazio para o lado else
do
if
. Copie-o para o scrapbook e execute para ver o resultado:
O trecho de código a seguir calcula a média final das três provas pelas nossas regras de avaliação:
Use o formulário abaixo para enviar o Laboratório 4. O prazo para envio é quarta-feira, dia 19/03/2014.
Última Atualização: 2016-05-18 10:58