O
abstract class MessageSend extends Expr { ... }
class MessageSendToVariable
extends MessageSend { ... }
class MessageSendToSelf extends MessageSend
{ ... }
class MessageSendToSuper extends MessageSend
{ ... }
class MessageSendStatement
extends Statement {
MessageSend messageSend;
public
void gen( PrintWriter out ) {
pw.printIdent("");
// messageSend.genC(pw);
pw.println(";"); }
}
...
}
a = new A();
Na
Os
deve-se
classOf_x.searchMethod(“m”);
classOf_x = symbolTable.getInGlobal(“A”);
Assume-se
e
O
A
public class Variable {
private
String name;
private Type type;
}
O
class A
private A x;
...
end
Ao
x = y;
o
// lexer.getStringValue()
Variable left
= st.getInLocal( lexer.getStringValue()
);
if ( left ==
null ) error.
return new AssignmentStatement( left, expr()
);
Duas
1)
class AssignmentStatement {
private
String leftSide;
private Expr rightSide;
...
}
2) representar x como uma variável, mas criar esta variável ao encontrar x :
// lexer.getStringValue()
retorna “x”
Variable left
= new Variable( lexer.getStringValue() );
return new AssignmentStatement( left, expr()
);
Os
únicos lugares onde deve-se criar objetos de Variable,
InstanceVariable e Parameter
é na declaração das variáveis correspondentes. E nunca se deve representar
variáveis por Strings --- utilize objetos de Variable
e suas subclasses. O mesmo se aplica a KraClass e ao
tipo de variáveis.
Os compiladores sinalizam uma exceção depois de mostrar um erro. Esta exceção deve ser (é) capturada em um bloco try no método compile da classe Compiler. A impressão da pilha de chamadas (com e.printStackTrace()) deve ser utilizada apenas na fase de depuração do compilador e não deve estar presente no compilador entregue ao professor.
Não deve haver uma classe IdList no compilador. A produção IdList na gramática é utilizada para duas coisas diferentes: análise de variáveis de instância e variáveis locais.
Interessante, mas ninguém até agora notou uma terrível inconsistência no nome dos métodos dos analisadores sintáticos que eu apresentei como exemplos. Lembram dos nomes dos métodos ? São expr, ifStat, whileStat, varDec, etc. Absurdamente errado. Estes nomes são substantivos. Métodos designam ações e portanto devem ter nomes verbais. Os nomes corretos seriam analyzeExpr, analyzeIfStat, etc, dizendo "analise uma expressão", ... Naturalmente, utizamos expr no lugar de analyzeExpr por um motivo de economia de digitação. Mas no vosso trabalho vocês não devem repetir este erro em outras classes que não o analisador sintático. O guia de programação recomenda que vocês coloquem nomes significativos nos métodos e isto significa colocar nomes verbais.
Algumas dicas para fazer o trabalho:
Utilize a
classe PW para fazer a tabulação do código gerado corretamente. Esta classe
está no diretório krakatoa\AST. Faça assim: antes de
usar pw, inicialize-a uma única vez com o objeto PrintWriter utilizado para saída
pw.set(out);
pw possui métodos printIdent
e printlnIdent que automaticamente indentam o que você imprime com pw.printIdent ou pw.printlnIdent. Naturalmente, printlnIdent
imprime a string e pula para a próxima linha, enquanto que printIdent
não. Se você quiser aumentar a indentação, utilize pw.add(). Para diminuir, utilize pw.sub(). Teste o seguinte código
PrintWriter out = new PrintWriter( ... );
pw.set(out); // faça
isso uma única vez antes do início da geração de código --- o que já é feito
pelo compilador fornecido.
pw.printIdent(“a = a + 1;”);
pw.add();
pw.printIdent("if");
pw.println(
" a > b"); // código sem indentação,
pois foi escrito com pw.print
e não pw.printIdent
pw.printIdent("then");
pw.add();
// comandos dentro do then devem
ser indentados
pw.printlnIdent("a
= b;");
pw.sub(); //
diminui a indentação: acabou o then
pw.printlnIdent("endif");
pw.sub();
pw.println("Texto
normal, não indentado");
A saída deste código é
a = a + 1;
if a > b
then
a = b;
endif
Texto normal, não indentado
Esta