📄 codegen.cpp.svn-base
字号:
#include <fstream>#include <list>#include "whale.h"#include "codegen.h"#include "parser.h"#include "utilities.h"#include "first.h"#include "grammar.h"#include "tables.h" // should move table making stuff to some other module#include <stdexcept>using namespace std;using namespace Whale;#include <boost/lexical_cast.hpp>#include <sstream>//#define ANNOUNCE_REDUCE_CODE_GENERATION/* It seems to me that this table is completely unused. *///#define MAKE_TABLE_OF_RULE_BODIESvoid generate_whale_class(FILE *a);void generate_scalar_constants(FILE *a, char *indent, bool it_is_cpp);void generate_table_of_states(FILE *a);void generate_table_of_pointers_to_members(FILE *a);void generate_table_of_rules(FILE *a);void generate_index_entry_to_access_compressed_table(FILE *a, IndexEntry &ie, int mode);void generate_raw_tables(FILE *a, const char *indent, bool it_is_cpp);void generate_classes(FILE *a, const char *indent, int mode);void generate_parse_function(FILE *a);void generate_reduce_code(FILE *a, const char *indent, int rn);ClassHierarchy::DataMember *generate_code_that_copies_single_symbol_from_stack_to_one_or_more_data_members(FILE *a, const char *indent, ClassHierarchy::Class *type, NonterminalExpression *expr, const char *access_to_nonterminal_object, const char *location_in_stack_base, int location_in_stack_offset);void generate_code_that_puts_symbol_to_data_member(FILE *a, const char *indent, const char *access_to_nonterminal_object, ClassHierarchy::DataMember *data_member, int number_of_iterations_in_source, const string &access_to_symbol);void generate_code_that_fills_up_field(FILE *a, const char *indent, const string &access_to_symbol, const string &pointer_to_nonterminal_object, bool null_pointer_possible);void generate_code_that_disposes_of_symbol(FILE *a, const char *indent, const string &access_to_symbol);string expression_that_gets_single_symbol_from_stack(ClassHierarchy::Class *symbol_type, const char *location_in_stack_base, int location_in_stack_offset);void generate_expression_that_gets_single_symbol_from_stack(FILE *a, ClassHierarchy::Class *symbol_type, const char *location_in_stack_base, int location_in_stack_offset);void generate_code_that_initializes_all_remaining_data_members(FILE *a, const char *indent, ClassHierarchy::Class *type, const char *access_to_object, set<ClassHierarchy::DataMember *> &initialized_data_members);int find_creator_somewhere_around_rule(int rn);ClassHierarchy::Class *generate_code_to_establish_connection_to_creator(FILE *a, const char *indent, int creator_nn);void generate_code_to_establish_connection_to_unknown_creator(FILE *a, const char *indent, int nn, int an);void generate_visit_function(ClassHierarchy::Class *m, FILE *a, const char *indent, int mode);void generate_code(){ char *parser_type; if(data.variables.method==Variables::LR1) parser_type="An LR(1) parser"; else if(data.variables.method==Variables::SLR1) parser_type="An SLR(1) parser"; else if(data.variables.method==Variables::LALR1) parser_type="An LALR(1) parser"; else assert(false); string h_file_name=data.file_name+string(".h"); string symbols_file_name=data.file_name+string("_symbols.h"); string cpp_file_name=data.file_name+string(".cpp"); FILE *h_file=fopen(h_file_name.c_str(), "w"); FILE *symbols_file; if(data.variables.generate_symbols_file) symbols_file=fopen(symbols_file_name.c_str(), "w"); FILE *cpp_file=fopen(cpp_file_name.c_str(), "w"); string inclusion_indicator="WHALE_GENERATED_PARSER__"+convert_file_name_to_identifier(h_file_name, 1); fprintf(h_file, FIRST_LINE_FOR_GENERATED_FILES, parser_type); fprintf(cpp_file, FIRST_LINE_FOR_GENERATED_FILES, parser_type); /* symbols file */ if (data.variables.generate_symbols_file) { string inclusion_indicator2="WHALE_GENERATED_PARSER__"+convert_file_name_to_identifier(symbols_file_name, 1); fprintf(symbols_file, "\n#ifndef %s\n", inclusion_indicator2.c_str()); fprintf(symbols_file, "\n#define %s\n", inclusion_indicator2.c_str()); fprintf(symbols_file, "\n#include <iostream>"); fprintf(symbols_file, "\n#include <vector>\n\n"); if (data.variables.xml_support) fprintf(symbols_file, "#include <string>\n\n"); fprintf(symbols_file, "\nnamespace %s\n" "{\n", data.variables.whale_namespace); if (data.variables.xml_support) fprintf(symbols_file, "\n\tstd::string xml_escape(const std::string &);\n\n"); generate_classes(symbols_file, "\t", 1); fprintf(symbols_file, "\n} // namespace %s\n", data.variables.whale_namespace); fprintf(symbols_file, "#endif\n"); fclose(symbols_file); } /* .h */ fprintf(h_file, "\n#ifndef %s\n", inclusion_indicator.c_str()); fprintf(h_file, "\n#define %s\n", inclusion_indicator.c_str()); if(data.variables.code_in_h_before_all) fprintf(h_file, "\n%s\n", data.variables.code_in_h_before_all); fprintf(h_file, "\n#include <iostream>\n"); fprintf(h_file, "#include <vector>\n"); if(data.variables.input_queue) fprintf(h_file, "#include <queue>\n"); if(data.variables.generate_verbose_prints) { fprintf(h_file, "#if WHALE_DEBUG != 0\n"); fprintf(h_file, "#include <typeinfo>\n"); fprintf(h_file, "#endif\n"); } if(data.variables.generate_sanity_checks) fprintf(h_file, "#include <stdexcept>\n"); if (data.variables.xml_support) fprintf(h_file, "#include <string>\n\n"); if (!data.variables.generate_symbols_file) { fprintf(h_file, "\nnamespace %s\n" "{\n", data.variables.whale_namespace); if (data.variables.xml_support) fprintf(h_file, "\n\tstd::string xml_escape(const std::string&);\n\n"); generate_classes(h_file, "\t", 1); fprintf(h_file, "\n} // namespace %s\n", data.variables.whale_namespace); } else { fprintf(h_file, "#include \x22%s\x22\n", symbols_file_name.c_str()); } // change this! Escape sequences should be decoded. if (strlen(data.variables.lexical_analyzer_file) != 0 && string(data.variables.lexical_analyzer_file) != "\"\"") fprintf(h_file, "\n#include %s\n", data.variables.lexical_analyzer_file); if(data.variables.code_in_h) fprintf(h_file, "\n%s\n", data.variables.code_in_h); fprintf(h_file, "\nnamespace %s\n" "{\n", data.variables.whale_namespace); generate_classes(h_file, "\t", 2); generate_whale_class(h_file); fprintf(h_file, "\t\n"); fprintf(h_file, "\ttemplate<class T> std::vector<T> deepen(const T &x)\n"); fprintf(h_file, "\t{\n"); fprintf(h_file, "\t\treturn std::vector<T>(1, x);\n"); fprintf(h_file, "\t}\n"); fprintf(h_file, "\t\n"); fprintf(h_file, "\tstd::ostream &print_terminal_location(std::ostream &os, const Terminal *t);\n"); fprintf(h_file, "\t\n" "} // namespace %s\n", data.variables.whale_namespace); fprintf(h_file, "\n" "typedef %s::Parser %s;\n", data.variables.whale_namespace, data.variables.whale_class); if(data.variables.code_in_h_after_all) fprintf(h_file, "\n%s\n", data.variables.code_in_h_after_all); fprintf(h_file, "\n#endif\n"); fclose(h_file); /* .cpp */ if(data.variables.code_in_cpp_before_all) fprintf(cpp_file, "\n%s\n", data.variables.code_in_cpp_before_all); fprintf(cpp_file, "\n#include \x22%s\x22\n", h_file_name.c_str()); fprintf(cpp_file, "using namespace std;\n"); fprintf(cpp_file, "using namespace %s;\n", data.variables.whale_namespace); fprintf(cpp_file, "\nconst char *%s::Parser::whale_copyright_notice=\n" COPYRIGHT_NOTICE_FOR_GENERATED_FILES ";\n", data.variables.whale_namespace, parser_type); if(data.variables.code_in_cpp) fprintf(cpp_file, "\n%s\n", data.variables.code_in_cpp); // fprintf(cpp_file, "\n");// generate_scalar_constants(cpp_file, "", true); fprintf(cpp_file, "\n"); fprintf(cpp_file, "%s::Terminal::~Terminal()\n", data.variables.whale_namespace); fprintf(cpp_file, "{\n"); if(!data.variables.shallow_destructor) fprintf(cpp_file, " delete[] text;\n"); fprintf(cpp_file, "}\n"); fprintf(cpp_file, "\n"); fprintf(cpp_file, "%s::Nonterminal::~Nonterminal()\n", data.variables.whale_namespace); fprintf(cpp_file, "{\n"); if(!data.variables.shallow_destructor) { fprintf(cpp_file, " for(Symbol *s=first_child; s;)\n"); fprintf(cpp_file, " {\n"); fprintf(cpp_file, " Symbol *current=s;\n"); fprintf(cpp_file, " s=s->next_sibling;\n"); fprintf(cpp_file, " delete current;\n"); fprintf(cpp_file, " }\n"); } fprintf(cpp_file, "}\n"); fprintf(cpp_file, "\n"); generate_parse_function(cpp_file); fprintf(cpp_file, "\n"); fprintf(cpp_file, "void %s::Parser::initialize()\n", data.variables.whale_namespace); fprintf(cpp_file, "{\n"); fprintf(cpp_file, "\tstate_stack.push_back(0);\n"); if(!data.variables.input_queue) { fprintf(cpp_file, "\tinput_symbol=%s;\n", data.variables.get_token_expression.c_str()); if (data.variables.generate_verbose_prints) { fprintf(cpp_file, "\t#if WHALE_DEBUG != 0\n"); fprintf(cpp_file, "\tif (m_debug)\n"); fprintf(cpp_file, "\t\tcout << \x22read token \\x22\x22 << " "input_symbol->symbol_name() << \x22\\x22\\n\x22;\n"); fprintf(cpp_file, "\t#endif\n"); } } else { fprintf(cpp_file, "\tinput_symbols.push(%s);\n", data.variables.get_token_expression.c_str()); if (data.variables.generate_verbose_prints) { fprintf(cpp_file, "\t#if WHALE_DEBUG != 0\n"); fprintf(cpp_file, "\tif (m_debug)\n"); fprintf(cpp_file, "\t\tcout << \x22read token \\x22\x22 << " "input_symbols.back()->symbol_name() << \x22\\x22\\n\x22;\n"); fprintf(cpp_file, "\t#endif\n"); } } fprintf(cpp_file, "}\n"); fprintf(cpp_file, "\n"); fprintf(cpp_file, "%s::Parser::~Parser()\n", data.variables.whale_namespace); fprintf(cpp_file, "{\n"); if (data.variables.code_in_destructor) fprintf(cpp_file, data.variables.code_in_destructor); fprintf(cpp_file, "}\n\n"); fprintf(cpp_file, "\n"); fprintf(cpp_file, "void %s::Parser::report_error(std::ostream &os, const Terminal *t) const\n", data.variables.whale_namespace); fprintf(cpp_file, "{\n"); fprintf(cpp_file, "\tos << \x22Syntax error at \x22;\n"); fprintf(cpp_file, "\tt->print_location(os);\n"); fprintf(cpp_file, "\tos << \x22.\\n\x22;\n"); fprintf(cpp_file, "}\n"); const char *ref_to_input_symbol=(data.variables.input_queue ? "input_symbols.front()" : "input_symbol"); fprintf(cpp_file, "\n"); fprintf(cpp_file, "bool %s::Parser::recover_from_error()\n", data.variables.whale_namespace); fprintf(cpp_file, "{\n"); if(data.variables.generate_verbose_prints) { fprintf(cpp_file, "\t#if WHALE_DEBUG != 0\n"); fprintf(cpp_file, "\tif (m_debug)\n"); fprintf(cpp_file, "\t\tcout << \x22" "Error recovery\\n\x22;\n"); fprintf(cpp_file, "\t#endif\n"); fprintf(cpp_file, "\n"); } fprintf(cpp_file, "\tint stack_pos;\n"); fprintf(cpp_file, "\tint new_state=-1;\n"); fprintf(cpp_file, "\tint number_of_symbols_discarded=0;\n"); fprintf(cpp_file, "\tfor(stack_pos=state_stack.size()-1; stack_pos>=0; stack_pos--)\n"); fprintf(cpp_file, "\t{\n"); fprintf(cpp_file, "\t\tint state=state_stack[stack_pos];\n"); fprintf(cpp_file, "\t\tLRAction lr_action=access_action_table(state, error_terminal_number);\n"); fprintf(cpp_file, "\t\tif(lr_action.is_shift())\n"); fprintf(cpp_file, "\t\t{\n"); fprintf(cpp_file, "\t\t\tnew_state=lr_action.shift_state();\n"); fprintf(cpp_file, "\t\t\tbreak;\n"); fprintf(cpp_file, "\t\t}\n"); if(data.variables.generate_verbose_prints) { fprintf(cpp_file, "\t\t#if WHALE_DEBUG != 0\n"); fprintf(cpp_file, "\t\tif (m_debug)\n"); fprintf(cpp_file, "\t\t\tcout << \x22" "Discard stack\\n\x22;\n"); fprintf(cpp_file, "\t\t#endif\n"); } fprintf(cpp_file, "\t\tnumber_of_symbols_discarded++;\n"); fprintf(cpp_file, "\t}\n"); fprintf(cpp_file, "\tif(new_state==-1) return false;\n"); fprintf(cpp_file, "\t\n"); fprintf(cpp_file, "\tTerminalError *error_token=new TerminalError;\n"); fprintf(cpp_file, "\terror_token->line=%s->line;\n", ref_to_input_symbol); fprintf(cpp_file, "\terror_token->column=%s->column;\n", ref_to_input_symbol); fprintf(cpp_file, "\t\n"); fprintf(cpp_file, "\tfor(unsigned int stack_pos_ii=stack_pos; stack_pos_ii<symbol_stack.size(); stack_pos_ii++)\n"); fprintf(cpp_file, "\t\terror_token->garbage.push_back(symbol_stack[stack_pos_ii]);\n"); fprintf(cpp_file, "\terror_token->error_position=error_token->garbage.size();\n"); fprintf(cpp_file, "\t\n"); fprintf(cpp_file, "\tfor(int j=0; j<number_of_symbols_discarded; j++)\n"); fprintf(cpp_file, "\t{\n"); fprintf(cpp_file, "\t\tstate_stack.pop_back();\n"); fprintf(cpp_file, "\t\tsymbol_stack.pop_back();\n"); fprintf(cpp_file, "\t}\n"); fprintf(cpp_file, "\t\n"); fprintf(cpp_file, "\t// shifting error token.\n"); fprintf(cpp_file, "\tsymbol_stack.push_back(error_token);\n"); fprintf(cpp_file, "\tstate_stack.push_back(new_state);\n"); fprintf(cpp_file, "\t\n"); fprintf(cpp_file, "\tfor(;;)\n"); fprintf(cpp_file, "\t{\n"); fprintf(cpp_file, "\t\tint state=state_stack[state_stack.size()-1];\n"); fprintf(cpp_file, "\t\tLRAction lr_action(access_action_table(state, %s->number()));\n", ref_to_input_symbol); if(data.variables.generate_verbose_prints) { fprintf(cpp_file, "\t\tif(!lr_action.is_error())\n"); fprintf(cpp_file, "\t\t{\n"); fprintf(cpp_file, "\t\t\t#if WHALE_DEBUG != 0\n"); fprintf(cpp_file, "\t\t\tif (m_debug)\n"); fprintf(cpp_file, "\t\t\t\tcout << \x22Recovery complete\\n\x22;\n"); fprintf(cpp_file, "\t\t\t#endif\n"); fprintf(cpp_file, "\t\t\t\treturn true;\n"); fprintf(cpp_file, "\t\t}\n"); } else fprintf(cpp_file, "\t\tif(!lr_action.is_error()) return true;\n"); fprintf(cpp_file, "\t\t\n"); if(data.variables.generate_verbose_prints) { fprintf(cpp_file, "\t\t#if WHALE_DEBUG != 0\n"); fprintf(cpp_file, "\t\tif (m_debug)\n"); fprintf(cpp_file, "\t\t\tcout << \x22" "Discard input\\n\x22;\n"); fprintf(cpp_file, "\t\t#endif\n"); } fprintf(cpp_file, "\t\terror_token->garbage.push_back(%s);\n", ref_to_input_symbol); fprintf(cpp_file, "\t\tif(%s->number()==eof_terminal_number) return false;\n", ref_to_input_symbol); if(!data.variables.input_queue) { fprintf(cpp_file, "\t\tinput_symbol=%s;\n", data.variables.get_token_expression.c_str()); if (data.variables.generate_verbose_prints) { fprintf(cpp_file, "\t\t#if WHALE_DEBUG != 0\n"); fprintf(cpp_file, "\t\tif (m_debug)\n"); fprintf(cpp_file, "\t\t\tcout << \x22read token \\x22\x22 << " "input_symbol->symbol_name() << \x22\\x22\\n\x22;\n"); fprintf(cpp_file, "\t\t#endif\n"); } } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -