| 
				     | 
				
| (7 intermediate revisions by the same user not shown) | 
| Line 1: | 
Line 1: | 
 | {{TOCright}}
  |  | #REDIRECT [[ist:Semantic Analysis/Exercise 01]]  | 
 | == The Problem (in Portuguese) ==
  |  | 
 | Considere o analisador sintáctico da linguagem Simple (abaixo). Considere que as variáveis só podem ser utilizadas em expressões (ID ou ASSIGN) depois de declaradas (LET); que variáveis com o mesmo nome não podem ser declaradas no mesmo bloco; e que os tokens INT e STRING correspondem a  literais, respectivamente, dos tipos inteiro e cadeia de caracteres.
  |  | 
 |    |  | 
 | Traduza para C (visitor em C++) e valide semanticamente (visitor em C++) a árvore sintáctica abstracta, emitindo mensagens se forem detectados erros de validação semântica. Utilize as classes da CDK (cdk::SymbolTable, nós, etc.) na resolução do problema. Pode ser útil definir outras classes auxiliares de validação de tipos (Symbol, etc.). Nos visitors, implemente apenas os métodos process. O acesso às sub-árvores de nós binários faz-se através dos métodos left() e right() e às sub-árvores de nós unários através do método argument().
  |  | 
 |    |  | 
 | <text>
  |  | 
 | %token tSTART tBLOCK tEND tLET tPRINT tASSIGN
  |  | 
 | %token <str>     tID tSTRING
  |  | 
 | %token <i>       tINT 
  |  | 
 | %type <node>     program block decl instr
  |  | 
 | %type <sequence> decls instrs
  |  | 
 | %right tASSIGN
  |  | 
 | %left '-'
  |  | 
 | %nonassoc tUMINUS
  |  | 
 |    |  | 
 | %%
  |  | 
 | program : tSTART block  { _compiler->ast(new ProgramNode(LINE, $2)); }
  |  | 
 |         ;
  |  | 
 | block   : tBLOCK decls instrs tEND { $$ = new BlockNode(LINE, $2, $3); }
  |  | 
 |         ;
  |  | 
 | decls   : decl                    { $$ = new Sequence(LINE, $1); }
  |  | 
 |         | decls decl              { $$ = new Sequence(LINE, $2, $1); }
  |  | 
 |         ;
  |  | 
 | decl    : tLET tID	            { $$ = new DeclNode(LINE, $2); }
  |  | 
 |         ;
  |  | 
 | instrs  : instr                   { $$ = new Sequence(LINE, $1); }
  |  | 
 |         | instrs instr            { $$ = new Sequence(LINE, $2, $1); }
  |  | 
 |         ;
  |  | 
 | instr   :                ';'      { $$ = new Nil(LINE); }
  |  | 
 |         | block          ';'      { $$ = $1; }
  |  | 
 |         | tPRINT expr    ';'      { $$ = new PrintExpNode(LINE, $2); }
  |  | 
 |         | tPRINT tSTRING ';'      { $$ = new PrintStrNode(LINE, $2); }
  |  | 
 |         ;
  |  | 
 | expr    : tID                     { $$ = new Identifier(LINE, $1); }
  |  | 
 |         | tINT                    { $$ = new Integer(LINE, $1); }
  |  | 
 |         | tID tASSIGN expr        { $$ = new AssignmentNode(LINE, $1, $3); }
  |  | 
 |         | expr '-' expr           { $$ = new SUB(LINE, $1, $3); }
  |  | 
 |         | '-' expr %prec tUMINUS  { $$ = new NEG(LINE, $2); }
  |  | 
 |         ;
  |  | 
 | %%
  |  | 
 | </text>
  |  | 
 |    |  | 
 | A interface pública da tabela de símbolos é a seguinte:
  |  | 
 |    |  | 
 | <cpp>
  |  | 
 | template <typename Symbol>
  |  | 
 | class SymbolTable {
  |  | 
 | public:
  |  | 
 |   // inicia a tabela com um contexto (global)
  |  | 
 |   SymbolTable();
  |  | 
 |    |  | 
 |   // destrói contextos e símbolos (atenção a este aspecto)
  |  | 
 |   ~SymbolTable();
  |  | 
 |    |  | 
 |   // criação de um novo contexto
  |  | 
 |   void push();
  |  | 
 |    |  | 
 |   // destruição do contexto actual
  |  | 
 |   void pop();
  |  | 
 |    |  | 
 |   // definição de um símbolo no contexto actual
  |  | 
 |   bool insert(const char *name, Symbol *symbol);
  |  | 
 |    |  | 
 |   // substituição de dados relativos a um símbolo (contexto actual)
  |  | 
 |   bool replaceLocal(const char *name, Symbol *symbol);
  |  | 
 |    |  | 
 |   // substituição de dados relativos a um símbolo (primeiro contexto onde ocorra)
  |  | 
 |   bool replace(const char *name, Symbol *symbol);
  |  | 
 |    |  | 
 |   // procura um símbolo (contexto actual)
  |  | 
 |   bool findLocal(const char *name, Symbol *symbol);
  |  | 
 |    |  | 
 |   // procura um símbolo (a partir do contexto indicado por from, relativo ao actual)
  |  | 
 |   Symbol *find(const char *name, int from = 0) const;
  |  | 
 | };
  |  | 
 | </cpp>
  |  | 
 |    |  | 
 | == Solution ==
  |  | 
 |    |  | 
 | [[category:Compilers]]  |  | 
 | [[category:Teaching]]
  |  |