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 = (ClassDec
) symbolTable.getInGlobal(“A”);
Assume-se
e
O
A
public class Variable {
private
String name;
private Type type;
}
O
class A
private A x;
...
end
if ( methodId.compareTo(“new”) == 0 )
...
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 ClassDec 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
Veja o