⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 semantics.cc

📁 PL/0源码
💻 CC
字号:
//////////////////////////////////////////////////////////////////////////////////  semantics.cc////  Currently, the PL/0 compiler performs the following semantic checks://  - is every identifier declared before use?//  - is no identifier declared more than once in the same scope?//  - is every lhs of an assignment a variable?//  - is every identifier in an expression a variable or constant?//  - is every called identifier a subroutine?//  - is every declared identifier used somewhere? (warn only if not)////  See file attributes.h for the syntax_tree_t classes.//#include "plzero.h"#include "symtab.h"#include "attributes.h"#include <strstream>//////////////////////////////////////////////////////////////////////////////////  Semantics Checking////  Traverse syntax tree, performing semantic checks, creating symbol table//  entries, and inserting references to those entries into identifier leaf//  nodes.  If no errors have been found by the time this routine finishes,//  it should be possible to generate code without additional checks.////  Open and close scopes as appropriate, so that symbol table look_up//  routine works correctly.  When semantic_checks is called by the driver,//  the predefined and global scopes are already open.////  Each node in the syntax tree must implement the check_semantics member//  function which call check_semantics of any children and also checks the//  semantics of the node itself.//void syntax_tree_t::check_semantics(scope_number_t scope){    UNUSED_PARAM(scope);    dump_syntax_tree(this);    die_compiler("Unexpected call to syntax_tree_t::check_semantics");}void st_token_t::check_semantics(scope_number_t scope){    UNUSED_PARAM(scope);}void st_identifier_t::check_semantics(scope_number_t scope){    UNUSED_PARAM(scope);    symbol_entry = symbol_look_up(attributes.text_handle);    if (symbol_entry == NULL)        issue_error(location, "Undefined identifier.");}void st_identifier_t::set_assigned(void){    if (symbol_entry) {        // could be NULL if this was an undefined identifier, in which        // case we've already generated a message        symbol_entry->set_assigned(location);    }}void st_identifier_t::set_used(void){    if (symbol_entry) {        // could be NULL if this was an undefined identifier, in which        // case we've already generated a message        symbol_entry->set_used(location);    }}void st_identifier_t::set_called(void){    if (symbol_entry) {        // could be NULL if this was an undefined identifier, in which        // case we've already generated a message        symbol_entry->set_called(location);    }}void st_number_t::check_semantics(scope_number_t scope){    UNUSED_PARAM(scope);    istrstream ist(token_text(attributes.text_handle).c_str());    ist >> value;}//////////  Return the value of this number.//int st_number_t::get_value(void) const{    return value;}void st_operator_t::check_semantics(scope_number_t scope){    UNUSED_PARAM(scope);    dump_syntax_tree(this);    die_compiler("Unexpected call to st_operator_t::check_semantics");}void st_unary_op_t::check_semantics(scope_number_t scope){    if (operand) operand->check_semantics(scope);    st_identifier_t *ip = dynamic_cast<st_identifier_t *>(operand);        // may fail (return NULL); operand could be a built-up expression    if (ip) {        ip->set_used();    }}void st_binary_op_t::check_semantics(scope_number_t scope){    if (left_operand) left_operand->check_semantics(scope);    if (right_operand) right_operand->check_semantics(scope);    st_identifier_t *ip = dynamic_cast<st_identifier_t *>(left_operand);        // may fail (return NULL); operand could be a built-up expression    if (ip) {        ip->set_used();    }    ip = dynamic_cast<st_identifier_t *>(left_operand);        // may fail (return NULL); operand could be a built-up expression    if (ip) {        ip->set_used();    }}void st_statement_t::check_semantics(scope_number_t scope){    UNUSED_PARAM(scope);    dump_syntax_tree(this);    die_compiler("Unexpected call to st_statement_t::check_semantics");}void st_assignment_t::check_semantics(scope_number_t scope){    if (left_side) left_side->check_semantics(scope);    if (right_side) right_side->check_semantics(scope);    if (left_side) {        // may be NULL if already in error        left_side->set_assigned();    }    st_identifier_t *ip = dynamic_cast<st_identifier_t *>(right_side);        // may fail (return NULL); rhs could be a built-up expression    if (ip) {        ip->set_used();    }    if (next_statement) next_statement->check_semantics(scope);}void st_while_t::check_semantics(scope_number_t scope){    if (condition) condition->check_semantics(scope);    if (body) body->check_semantics(scope);    if (next_statement) next_statement->check_semantics(scope);}void st_if_t::check_semantics(scope_number_t scope){    if (condition) condition->check_semantics(scope);    if (body) body->check_semantics(scope);    if (next_statement) next_statement->check_semantics(scope);}void st_call_t::check_semantics(scope_number_t scope){    if (procedure) {        procedure->check_semantics(scope);        procedure->set_called();    }    if (next_statement) next_statement->check_semantics(scope);}void st_declaration_t::check_semantics(scope_number_t scope){    UNUSED_PARAM(scope);    dump_syntax_tree(this);    die_compiler("Unexpected call to st_declaration_t::check_semantics");}void st_constant_t::check_semantics(scope_number_t scope){    if (identifier) identifier->check_semantics(scope);    if (value) value->check_semantics(scope);    if (identifier && value) {        (void) new se_constant_t(scope,                identifier->get_attributes().text_handle,                location, value->get_value());            // We ignore the returned pointer because the constructor            // automatically adds the symbol to the symbol table.    }    if (next_declaration) next_declaration->check_semantics(scope);}void st_variable_t::check_semantics(scope_number_t scope){    if (identifier) {        (void) new se_variable_t(scope,                identifier->get_attributes().text_handle, location);            // We ignore the returned pointer because the constructor            // automatically adds the symbol to the symbol table.        identifier->check_semantics(scope);            // note that this call has to come *after* the constructor            // call for se_variable_t    }    if (next_declaration) next_declaration->check_semantics(scope);}void st_procedure_t::check_semantics(scope_number_t scope){    scope_number_t  temp_scope = new_scope();    if (identifier) {        (void) new se_procedure_t(scope,                identifier->get_attributes().text_handle,                location, temp_scope);            // We ignore the returned pointer because the constructor            // automatically adds the symbol to the symbol table.    }    if (block) {        open_scope(temp_scope);        if (block) block->check_semantics(temp_scope);        close_scope();    }    if (identifier) identifier->check_semantics(scope);    if (next_declaration) next_declaration->check_semantics(scope);}void st_block_t::check_semantics(scope_number_t scope){    symbol = NULL;    if (declarations) declarations->check_semantics(scope);    if (body) body->check_semantics (scope);    for (symbol_entry_t *p = first_in_scope(scope); p != NULL; p = p->next()) {        //  Look through symbol table records for given scope, and complain        //  if any identifiers have not been used or variables not been set        p->end_of_scope_check();    }    // There really ought to be C++ iterator for the elements of a scope}// End of File

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -