|
|
(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]]
| |