📄 attributes.cc
字号:
////////////////////////////////////////////////////////////////////////////////// attributes.cc - Syntax tree attributes and stack functions.//#include "plzero.h"#include "inpbuf.h"#include <iomanip>#include <strstream>#include "attributes.h"#define PROD_STACK_SIZE 200// Production stack. Used to keep track of locations// of attribute records for productions in progressstatic struct prod_stack_t { attrib_stack_t * lhsSave; attrib_stack_t * rhsSave;} ps [PROD_STACK_SIZE + 1];static attrib_stack_t as[MAX_ATTR_STACK + 1];static prod_stack_t * ps_top = &ps[0]; // highest used production stack entrystatic attrib_stack_t * as_top = &as[0]; // highest used attribute stack entryattrib_stack_t * lhs = &as[0];attrib_stack_t * rhs = &as[0];syntax_tree_t * ast_root = NULL;////////// Start a new production by first saving old values of lhs and rhs,// updating as_top to make room for new right-hand side,// and then updating lhs and rhs//void start_production(int length, int seen_so_far){ if (as_top + length > &as[MAX_ATTR_STACK]) die_compiler ("Attribute stack overflow."); else if (ps_top + 1 > &ps[PROD_STACK_SIZE]) die_compiler ("Production stack overflow."); else { ps_top++; ps_top->lhsSave = lhs; ps_top->rhsSave = rhs; lhs = rhs + seen_so_far; rhs = as_top + 1; as_top += length; }}////////// End a production by restoring the saved values for rhs and lhs,// and using them to calculate the old values of as_top and seen_so_far.//void end_production(int& seen_so_far){ assert(as_top > &as[0]); // attribute stack shouldn't be empty at end of production assert(ps_top > &ps[0]); // prediction stack shouldn't be empty at end of production as_top = rhs - 1; rhs = ps_top->rhsSave; seen_so_far = lhs - rhs + 1; // distance between finished child's lhs and parent's rhs, // plus 1 for the symbol we just finished expanding lhs = ps_top->lhsSave; ps_top--;}////////// Load synthetic attributes of token//void init_token(token_attrib_t attr, int seen_so_far){ (rhs+seen_so_far)->token = attr;}////////// Utility routine to format a pointer as an 8-character zero-filled// ascii string in hex.string p2h(void *p) { ostrstream ost; ost << hex << setfill('0') << setw(8) << (unsigned int)p; return ost.str();}////////////////////////////////////////////////////////////////////////////////// Dump syntax tree to ouput for debugging.//// Dump a node from the syntax tree. If "recurse" is positive, then// recursively dump any of the node's children. "level" is used to indent// the text.//void dump_syntax_tree(syntax_tree_t *node, int recurse/*=1*/, int level/*=0*/){ if (!node || recurse < 0) // Drop if recurse counter expired. return; cout << p2h(node) << " (" << setw(3) << node->get_location().get_lineno() << "." << setw(2) << node->get_location().get_column() << ") "; if (recurse < 1) // Expire non-recurse. recurse--; node->dump_object_data(recurse, level);}////////// Dump a syntax tree node name to stdout. Automatically indents to show// the nested level of the node.//static void dump_name(char *name, int level){ int len; for (len = 0; len < level * 2; len++) cout << " "; cout << name; for (len += strlen(name); len < 24; len++) cout << " ";}////////////////////////////////////////////////////////////////////////////////// Syntax Tree Members://////////// syntax_tree_t: Abstract type for all syntax tree nodes.//syntax_tree_t::syntax_tree_t(location_t loc){ location = loc; code_gen_info = NULL;}////////// Return the location in the source file where the node was created.//location_t syntax_tree_t::get_location(void) const{ return location;}////////// Dump the contents of the node to stdout for debugging.//void syntax_tree_t::dump_object_data(int recurse, int level) const{ UNUSED_PARAM(recurse); dump_name("syntax_tree_t", level);}////////// Destruct a syntax tree node. Other nodes need more elaborate destructors.//syntax_tree_t::~syntax_tree_t(void){}////////// Tokens://st_token_t::st_token_t(token_attrib_t attr) : syntax_tree_t (attr.location){ attributes = attr;}void st_token_t::dump_object_data(int recurse, int level) const{ UNUSED_PARAM(recurse); dump_name("token", level); cout << setw(2) << (int)attributes.get_major() << "." << setw(2) << (int)attributes.get_minor() << "\n";}token_attrib_t st_token_t::get_attributes(void) const{ return attributes;}st_token_t::~st_token_t(void){}////////// Identifiers://st_identifier_t::st_identifier_t(token_attrib_t attr) : st_token_t(attr){ symbol_entry = NULL;}void st_identifier_t::dump_object_data(int recurse, int level) const{ UNUSED_PARAM(recurse); dump_name("identifier", level); cout << setw(2) << (int)attributes.get_major() << "." << setw(2) << (int)attributes.get_minor() << " \"" << attributes.get_text() << "\"\n";}////////// Return a pointer to the symbol table entry for this identifier.//symbol_entry_t *st_identifier_t::get_symbol(void) const{ return symbol_entry;}st_identifier_t::~st_identifier_t(void){}////////// Number Constants://st_number_t::st_number_t(token_attrib_t attr) : st_token_t(attr){ value = 0;}////////// Special constructor for adding number constants into the syntax tree. This// is used mosting in the constant optimization code in optimize.cc//st_number_t::st_number_t(token_attrib_t attr, int n_value) : st_token_t(attr){ value = n_value;}void st_number_t::dump_object_data(int recurse, int level) const{ UNUSED_PARAM(recurse); dump_name("number", level); if (value) { // we've already done the string-to-integer conversion cout << setw(2) << (int)attributes.get_major() << "." << setw(2) << (int)attributes.get_minor() << " " << value << "\n"; } else { // we may not have done the string-to-integer conversion yet cout << setw(2) << (int)attributes.get_major() << "." << setw(2) << (int)attributes.get_minor() << " \"" << attributes.get_text() << "\"\n"; }}st_number_t::~st_number_t(void){}////////// Operators://st_operator_t::st_operator_t(location_t loc, st_token_t *id) : syntax_tree_t(loc){ op = id;}void st_operator_t::dump_object_data(int recurse, int level) const{ dump_name("operator", level); cout << p2h(op) << "\n"; dump_syntax_tree(op, recurse, level+1);}st_operator_t::~st_operator_t(void){ if (op) delete op;}////////// Unary Operators://st_unary_op_t::st_unary_op_t(location_t loc, st_token_t *id, syntax_tree_t *opand) : st_operator_t(loc, id){ operand = opand;}void st_unary_op_t::dump_object_data(int recurse, int level) const{ dump_name("unary_op", level); cout << p2h(op) << p2h(operand) << "\n"; dump_syntax_tree(op, recurse, level+1); dump_syntax_tree(operand, recurse, level+1);}st_unary_op_t::~st_unary_op_t(void){ if (operand) delete operand;}////////// Binary Operators://st_binary_op_t::st_binary_op_t(location_t loc, st_token_t *id, syntax_tree_t *lopand, syntax_tree_t *ropand) : st_operator_t(loc, id){ left_operand = lopand; right_operand = ropand;}void st_binary_op_t::dump_object_data(int recurse, int level) const{ dump_name("binary_op", level); cout << p2h(op) << " " << p2h(left_operand) << " " << p2h(right_operand) << "\n"; dump_syntax_tree(op, recurse, level+1); dump_syntax_tree(left_operand, recurse, level+1); dump_syntax_tree(right_operand, recurse, level+1);}st_binary_op_t::~st_binary_op_t(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -