void check_stmt(tree t) { for( ; t != NULL; t = t->next ) { switch (t->kind) { case If: case Elseif: if( check_expr(t->first) != Boolean ) { print_error("Invalid IF statement.", t); } check_stmt(t->second); check_stmt(t->third); continue; case Else: check_stmt(t->first); continue; case Exit: if(check_expr(t->first) != Boolean) { print_error("exit when must produce a boolean.", t); } continue; case Assign: if(t->first->kind == Obracket | check_expr(t->first) != check_expr(t->second)) { print_error("Invalid assignment statement.", t); } continue; case For: new_scope(); declare_var(id_name(t->first->value), Integer); if(check_expr(t->second->first) != Integer | check_expr(t->second->second) != Integer)//TODO or add a range check print_error("Invalid range.", t->second); check_stmt(t->third); end_scope(); continue; case Declaration:; if(t->second->kind == Array) { for(tree cur = t->first; cur != NULL; cur = cur->next) declare_array(id_name(cur->value), t->second->second->kind); } else { for(tree cur = t->first; cur != NULL; cur = cur->next) declare_var(id_name(cur->value), t->second->kind); } continue; case Declare: new_scope(); check_stmt(t->first); check_stmt(t->second); end_scope(); continue; default: print_error("Token of this type not checked by check_stmt.", t); continue; } } }
void check(tree t) { // We can ignore the procedure and its ident check_stmt(t->second); check_stmt(t->third); end_scope(); }
end_fn() { end_scope(); /* Drop all labels */ labtab[1] = labtab[0]; return frame_size; }
fini_symtab() { /* Calling end_scope destroys the type nodes in the symbol table. */ end_scope(); fini_tab( labtab ); fini_tab( symtab ); fini_tab( structtab ); }
end_block() { cur_offset -= end_scope(); }