Semantic Analysis/Exercise 01: Difference between revisions

From Wiki**3

< Semantic Analysis
(Redirected page to ist:Semantic Analysis/Exercise 01)
 
(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]]

Latest revision as of 18:08, 6 December 2018