📄 process.cpp.svn-base
字号:
#include "whale.h"#include "parser.h"#include <stdio.h>#include <iostream>#include <typeinfo>using namespace std;#include "assert.h"#include "process.h"//#include "stl.h"#include "classes.h"#include "utilities.h"#include "ancillary.h"using namespace Whale;//#define DEBUG//#define DEBUG_DATA_MEMBERS_IN_BODIES//#define DEBUG_COMMON_ANCESTORvoid make_built_in_symbols();bool process_class_declarations();bool process_expressions();bool process_expression_proc(NonterminalExpression *expr, ProcessExpressionProcData &proc_data);bool process_expression_proc_ii(NonterminalExpression *expression, ProcessExpressionProcIIData &proc_data);bool process_terminal_type_declaration(TerminalData &terminal, NonterminalTypeExpression *type);bool process_nonterminal_type_declaration(int nn, NonterminalTypeExpression *type);ClassHierarchy::Class *process_external_type_declaration(NonterminalExternalTypeExpression *external_type, NonterminalData *nonterminal);bool process_alternative_type_declaration(AlternativeData &alternative, NonterminalData &nonterminal, int alternative_number, NonterminalTypeExpression *type);ClassHierarchy::Class *process_standalone_type_declaration(NonterminalTypeExpression *type);string default_naming_proc(const char *s);string default_terminal_class_name(const char *s);string default_nonterminal_class_name(const char *s);string default_alternative_class_name(const string &s, int alternative_number);void report_undefined_base_class(ostream &os, Terminal *t);bool identifier_contains_no_hyphens(Terminal *t);ClassHierarchy::Class *process_scope_in_member_name_specification(Terminal *scope, Terminal *id, const pair<int, int> &location);ClassHierarchy::DataMember *process_single_data_member_declaration(Terminal *scope, Terminal *name, int nn, int an, int number_of_iterations);string generate_default_data_member_name(int n);string serialize_external_type_expression(NonterminalExternalTypeExpression &expr);bool apply_common_ancestor_determination_procedure(ClassHierarchy::Class *&dest, ClassHierarchy::Class *src, SymbolNumber sn, ClassHierarchy::DataMember *data_member, Terminal *t);bool process_option_statement(NonterminalOptionStatement &option_statement);pair<char *, AssignmentData::ValueType> process_single_value_in_option_statement(Terminal *t, bool process_escape_sequences_in_string);bool high_level_decode_escape_sequences(Terminal *t, string &s);void make_up_data_member_in_class_symbol();bool process_grammar(){ make_built_in_symbols(); if(!process_class_declarations()) return false; if(!assign_values_to_variables_stage_zero()) return false; if(data.variables.make_up_connection) make_up_data_member_in_class_symbol(); if(!process_expressions()) return false; if(data.terminals.size()<=2) { cout << "The grammar should contain at least one terminal symbol.\n"; return false; } if(data.nonterminals.size()<=1) { cout << "The grammar should contain at least one nonterminal symbol.\n"; return false; } assert(classes.in_global_scope.size()); return true;}void make_built_in_symbols(){ // S' NonterminalData start_symbol_of_augmented_grammar; start_symbol_of_augmented_grammar.name="S'"; start_symbol_of_augmented_grammar.declaration=NULL; start_symbol_of_augmented_grammar.type=0; start_symbol_of_augmented_grammar.is_ancillary=true; start_symbol_of_augmented_grammar.category=NonterminalData::START; data.nonterminals.push_back(start_symbol_of_augmented_grammar); // eof TerminalData eof_terminal; eof_terminal.name="eof"; eof_terminal.type=new ClassHierarchy::Class("TerminalEOF", classes.terminal, NULL); eof_terminal.type->is_abstract=false; data.eof_terminal_number=data.terminals.size(); eof_terminal.type->assigned_to=SymbolNumber::for_terminal(data.eof_terminal_number); data.terminals.push_back(eof_terminal); // error TerminalData error_terminal; error_terminal.name="error"; error_terminal.type=new ClassHierarchy::Class("TerminalError", classes.terminal, NULL); error_terminal.type->is_abstract=false; data.error_terminal_number=data.terminals.size(); error_terminal.type->assigned_to=SymbolNumber::for_terminal(data.error_terminal_number); data.terminals.push_back(error_terminal);}bool process_class_declarations(){ bool flag=true; // Pass 1. Determining how many rules are there for each nonterminal. // It is really vital to do it before all other processing. map<const char *, int, NullTerminatedStringCompare> how_many_rules_for_nonterminal; for(int i=0; i<data.S->statements.size(); i++) if(typeid(*data.S->statements[i])==typeid(NonterminalRuleStatement)) { NonterminalRuleStatement &rule_statement=*dynamic_cast<NonterminalRuleStatement *>(data.S->statements[i]); how_many_rules_for_nonterminal[rule_statement.left->text]++; }#ifdef DEBUG cout << how_many_rules_for_nonterminal << "\n";#endif string start_nonterminal_name; // Pass 2: Making the class hierarchy. It is done without looking // inside the expressions. for(int i=0; i<data.S->statements.size(); i++) { if(typeid(*data.S->statements[i])==typeid(NonterminalTerminalStatement)) { NonterminalTerminalStatement &terminal_statement=*dynamic_cast<NonterminalTerminalStatement *>(data.S->statements[i]); for(int j=0; j<terminal_statement.names.size(); j++) { Terminal *t=terminal_statement.names[j]; int tn=data.find_terminal(t->text); int nn=data.find_nonterminal(t->text); assert(!(tn!=-1 && nn!=-1)); if(tn!=-1) { cout << "Terminal " << t->text << ", "; data.terminals[tn].print_where_it_was_declared(cout); cout << ", cannot be redeclared at "; t->print_location(cout); cout << ".\n"; flag=false; } else if(nn!=-1) { cout << "Attempt to redeclare nonterminal " << t->text << " ("; data.nonterminals[nn].print_where_it_was_declared(cout); cout << ") as terminal at "; t->print_location(cout); cout << ".\n"; flag=false; } else { TerminalData terminal; terminal.name=t->text; terminal.declaration=t; if(process_terminal_type_declaration(terminal, terminal_statement.types[j])) data.terminals.push_back(terminal); else flag=false; } } } else if(typeid(*data.S->statements[i])==typeid(NonterminalNonterminalStatement)) { NonterminalNonterminalStatement &nonterminal_statement=*dynamic_cast<NonterminalNonterminalStatement *>(data.S->statements[i]); bool has_external_tag; if(!strcmp(nonterminal_statement.kw->text, "nonterminal")) has_external_tag=false; else if(!strcmp(nonterminal_statement.kw->text, "external")) has_external_tag=true; else assert(false); for(int j=0; j<nonterminal_statement.names.size(); j++) { Terminal *t=nonterminal_statement.names[j]; NonterminalExternalTypeExpression *external_type=nonterminal_statement.external_types[j]; int tn=data.find_terminal(t->text); int nn=data.find_nonterminal(t->text); assert(!(tn!=-1 && nn!=-1)); if(tn!=-1) { cout << "Attempt to redeclare terminal " << t->text << " ("; data.terminals[tn].print_where_it_was_declared(cout); cout << ") as nonterminal at "; t->print_location(cout); cout << ".\n"; flag=false; } else if(nn!=-1) { cout << "Nonterminal " << t->text << ", "; data.nonterminals[nn].print_where_it_was_declared(cout); cout << ", cannot be redeclared at "; t->print_location(cout); cout << ".\n"; flag=false; } else { int new_nn=data.nonterminals.size(); data.nonterminals.push_back(NonterminalData()); NonterminalData &nonterminal=data.nonterminals[new_nn]; nonterminal.name=t->text; nonterminal.declaration=t; if(!has_external_tag) { nonterminal.category=NonterminalData::NORMAL; if(!process_nonterminal_type_declaration(new_nn, nonterminal_statement.internal_types[j])) flag=false; if(external_type && !process_external_type_declaration(external_type, &nonterminal)) flag=false; } else { nonterminal.category=NonterminalData::EXTERNAL; if(!process_nonterminal_type_declaration(new_nn, NULL)) flag=false; if(!process_external_type_declaration(external_type, &nonterminal)) flag=false; nonterminal.type->template_parameters.push_back(nonterminal.external_type); } // if there were any errors (which have // already been reported by now), // nonterminal.type may be NULL. if(nonterminal.type!=NULL) { int nr=how_many_rules_for_nonterminal[t->text]; if(has_external_tag) nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::WRAPPER; else if(nr<=1) nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::UNKNOWN; else nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::BASE; } } } } else if(typeid(*data.S->statements[i])==typeid(NonterminalClassStatement)) { NonterminalClassStatement &class_statement=*dynamic_cast<NonterminalClassStatement *>(data.S->statements[i]); ClassHierarchy::Class *m=process_standalone_type_declaration(class_statement.expr); if(!m) flag=false; } else if(typeid(*data.S->statements[i])==typeid(NonterminalRuleStatement)) { NonterminalRuleStatement &rule_statement=*dynamic_cast<NonterminalRuleStatement *>(data.S->statements[i]); Terminal *t=rule_statement.left; int tn=data.find_terminal(t->text); int nn=data.find_nonterminal(t->text); assert(!(tn!=-1 && nn!=-1)); int nr=how_many_rules_for_nonterminal[t->text]; assert(nr>0); if(tn!=-1) { cout << "Terminal " << t->text << ", "; data.terminals[tn].print_where_it_was_declared(cout); cout << ", cannot be used in left part of rule at "; t->print_location(cout); cout << ".\n"; flag=false; continue; } else if(nn==-1 && nr==1) { int new_nn=data.nonterminals.size(); data.nonterminals.push_back(NonterminalData()); NonterminalData &nonterminal=data.nonterminals[new_nn]; nonterminal.name=t->text; nonterminal.declaration=t; nonterminal.category=NonterminalData::NORMAL; // creating a single class bool result=process_nonterminal_type_declaration(new_nn, rule_statement.type); if(!result) { flag=false; continue; } nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::SINGLE; AlternativeData alternative; alternative.declaration=rule_statement.left; alternative.type=NULL; alternative.expr=rule_statement.right; // cout << "pushing alternative: " << (void *)rule_statement.right << "\n"; nonterminal.alternatives.push_back(alternative); nonterminal.multiple_alternatives_mode=false; } else if(nn==-1 && nr>1) { int new_nn=data.nonterminals.size(); data.nonterminals.push_back(NonterminalData()); NonterminalData &nonterminal=data.nonterminals[new_nn]; nonterminal.name=t->text; nonterminal.declaration=t; nonterminal.category=NonterminalData::NORMAL; // Creating a base class using a generated name. bool result=process_nonterminal_type_declaration(new_nn, NULL); if(!result) { flag=false; continue; } nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::BASE; AlternativeData alternative; alternative.declaration=rule_statement.left; alternative.expr=rule_statement.right; bool result2=process_alternative_type_declaration(alternative, nonterminal, nonterminal.alternatives.size(), rule_statement.type); if(!result2) { // cout << "pushing alternative: " << (void *)rule_statement.right << "\n"; nonterminal.alternatives.push_back(alternative); flag=false; continue; } assert(!alternative.type->is_abstract); // cout << "pushing alternative: " << (void *)rule_statement.right << "\n"; nonterminal.alternatives.push_back(alternative); nonterminal.multiple_alternatives_mode=true; } else if(nn!=-1) { NonterminalData &nonterminal=data.nonterminals[nn]; assert(nonterminal.category==NonterminalData::NORMAL || nonterminal.category==NonterminalData::EXTERNAL); if(!nonterminal.type) { assert(!flag); } else if(nonterminal.category==NonterminalData::EXTERNAL) { assert(nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::WRAPPER); nonterminal.multiple_alternatives_mode=false; } else if(nr>1) { assert(nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::BASE); nonterminal.multiple_alternatives_mode=true; } else if(rule_statement.type || nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::BASE) { nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::BASE; nonterminal.multiple_alternatives_mode=true; } else if(nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::UNKNOWN) { nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::SINGLE; nonterminal.multiple_alternatives_mode=false; } else assert(false); AlternativeData alternative; alternative.declaration=rule_statement.left; alternative.expr=rule_statement.right; if(nonterminal.multiple_alternatives_mode) { bool result=process_alternative_type_declaration(alternative, nonterminal, nonterminal.alternatives.size(), rule_statement.type); if(!result) { nonterminal.alternatives.push_back(alternative); flag=false; continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -