📄 process.cpp.svn-base
字号:
} else alternative.type=NULL; // cout << "pushing alternative: " << (void *)rule_statement.right << "\n"; nonterminal.alternatives.push_back(alternative); } else assert(false); } else if(typeid(*data.S->statements[i])==typeid(NonterminalPrecedenceStatement)) { // precedence statements are dealt with in precedence.cpp } else if(typeid(*data.S->statements[i])==typeid(NonterminalOptionStatement)) { bool result=process_option_statement(*dynamic_cast<NonterminalOptionStatement *>(data.S->statements[i])); if(!result) flag=false; } else if(typeid(*data.S->statements[i])==typeid(NonterminalStartStatement)) { NonterminalStartStatement &start_statement=dynamic_cast<NonterminalStartStatement&>(*data.S->statements[i]); start_nonterminal_name = start_statement.id->text; } else if(typeid(*data.S->statements[i])==typeid(NonterminalInvalidStatement)) flag=false; else assert(false); } if(!flag) return false; for(int i=0; i<data.nonterminals.size(); i++) { NonterminalData &nonterminal=data.nonterminals[i]; if(nonterminal.is_ancillary) continue; if(nonterminal.name==start_nonterminal_name) data.start_nonterminal_number=i; if(!nonterminal.alternatives.size() && !nonterminal.type->descendants.size()) { assert(nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::UNKNOWN); cout << "Applying a doubtful fix to nonterminal " << nonterminal.name << "\n"; nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::SINGLE; } } return true;}bool process_expressions(){ bool flag=true; for(int i=0; i<data.nonterminals.size(); i++) { if(data.nonterminals[i].is_ancillary) continue; for(int j=0; j<data.nonterminals[i].alternatives.size(); j++) { NonterminalData &nonterminal=data.nonterminals[i]; // this declaration cannot be moved one loop level above, because process_expressions_proc can add nonterminals. AlternativeData &alternative=nonterminal.alternatives[j]; #ifdef DEBUG cout << i << ", " <<j << ": alternative.expr = " << (void *)alternative.expr << "\n"; #endif assert(alternative.expr); ProcessExpressionProcData proc_data(i, j); if(!process_expression_proc(alternative.expr, proc_data)) flag=false; } } if(!flag) return false; map<int, vector<NonterminalExpressionSymbol *> > nonterminals_that_cannot_be_connected_up; for(int i=0; i<data.nonterminals.size(); i++) { NonterminalData &nonterminal=data.nonterminals[i]; if(nonterminal.is_ancillary) continue; for(int j=0; j<nonterminal.alternatives.size(); j++) { AlternativeData &alternative=nonterminal.alternatives[j]; assert(alternative.expr); ProcessExpressionProcIIData proc_data(i, j, nonterminals_that_cannot_be_connected_up); if(!process_expression_proc_ii(alternative.expr, proc_data)) flag=false; } } // A -> a create b C; // B -> a b C; // create operator required here. // C -> c connect_up d; for(map<int, vector<NonterminalExpressionSymbol *> >::const_iterator p=nonterminals_that_cannot_be_connected_up.begin(); p!=nonterminals_that_cannot_be_connected_up.end(); p++) { NonterminalData &nonterminal=data.nonterminals[p->first]; vector<Terminal *> v1, v2; for(int i=0; i<nonterminal.requests_to_connect_up.size(); i++) v1.push_back(nonterminal.requests_to_connect_up[i]->kw); for(int i=0; i<p->second.size(); i++) v2.push_back(p->second[i]->symbol); cout << "Using connect_up operator "; print_a_number_of_terminal_locations(cout, v1, "at"); cout << " requires create operator before any reference to " << "nonterminal " << nonterminal.name << "; appearance" << (v2.size()==1 ? "" : "s") << " of " << nonterminal.name << " "; print_a_number_of_terminal_locations(cout, v2, "at"); cout << " " << (v2.size()==1 ? "is" : "are") << " not preceded by create.\n"; flag=false; } return flag;}bool process_expression_proc(NonterminalExpression *expr, ProcessExpressionProcData &proc_data){ if(typeid(*expr)==typeid(NonterminalExpressionDisjunction)) { NonterminalExpressionDisjunction &expr_d=*dynamic_cast<NonterminalExpressionDisjunction *>(expr); bool iabc_backup=proc_data.inside_anything_but_concatenation; proc_data.inside_anything_but_concatenation=true; bool result1=process_expression_proc(expr_d.expr1, proc_data); bool result2=process_expression_proc(expr_d.expr2, proc_data); proc_data.inside_anything_but_concatenation=iabc_backup; return result1 && result2; } else if(typeid(*expr)==typeid(NonterminalExpressionConjunction)) { NonterminalExpressionConjunction &expr_c=*dynamic_cast<NonterminalExpressionConjunction *>(expr); bool iabc_backup=proc_data.inside_anything_but_concatenation; proc_data.inside_anything_but_concatenation=true; process_expression_proc(expr_c.expr1, proc_data); cout << "Conjunction, used at "; expr_c.op->print_location(cout); cout << ", is not supported.\n"; process_expression_proc(expr_c.expr2, proc_data); proc_data.inside_anything_but_concatenation=iabc_backup; return false; } else if(typeid(*expr)==typeid(NonterminalExpressionConcatenation)) { NonterminalExpressionConcatenation &expr_cat=*dynamic_cast<NonterminalExpressionConcatenation *>(expr); bool result1=process_expression_proc(expr_cat.expr1, proc_data); bool result2=process_expression_proc(expr_cat.expr2, proc_data); return result1 && result2; } else if(typeid(*expr)==typeid(NonterminalExpressionComplement)) { NonterminalExpressionComplement &expr_com=*dynamic_cast<NonterminalExpressionComplement *>(expr); cout << "Complement, used at "; expr_com.op->print_location(cout); cout << ", is not supported.\n"; bool iabc_backup=proc_data.inside_anything_but_concatenation; proc_data.inside_anything_but_concatenation=true; process_expression_proc(expr_com.expr, proc_data); proc_data.inside_anything_but_concatenation=iabc_backup; return false; } else if(typeid(*expr)==typeid(NonterminalExpressionOmittable)) { NonterminalExpressionOmittable &expr_om=*dynamic_cast<NonterminalExpressionOmittable *>(expr); bool iabc_backup=proc_data.inside_anything_but_concatenation; proc_data.inside_anything_but_concatenation=true; bool result=process_expression_proc(expr_om.expr, proc_data); proc_data.inside_anything_but_concatenation=iabc_backup; return result; } else if(typeid(*expr)==typeid(NonterminalExpressionInParentheses)) { NonterminalExpressionInParentheses &expr_p=*dynamic_cast<NonterminalExpressionInParentheses *>(expr); bool result=process_expression_proc(expr_p.expr, proc_data); return result; } else if(typeid(*expr)==typeid(NonterminalExpressionIteration)) { NonterminalExpressionIteration &expr_it=*dynamic_cast<NonterminalExpressionIteration *>(expr); if(proc_data.member_expression) { cout << "Warning: member name specification at "; proc_data.member_expression->t->print_location(cout); cout << " has no effect inside iteration at "; expr_it.sign->print_location(cout); cout << ".\n"; } NonterminalMemberExpression *backup=proc_data.member_expression; proc_data.member_expression=NULL; proc_data.number_of_nested_iterations++; bool iabc_backup=proc_data.inside_anything_but_concatenation; proc_data.inside_anything_but_concatenation=true; bool result=process_expression_proc(expr_it.expr, proc_data); proc_data.inside_anything_but_concatenation=iabc_backup; proc_data.number_of_nested_iterations--; proc_data.member_expression=backup; if(!result) return false; expr_it.local_iterator_number=++proc_data.nonterminal().number_of_iterators; expr_it.body_sn=make_body_symbol(expr_it.expr, proc_data.nn, proc_data.an, expr_it.local_iterator_number, 0, expr_it.sign); expr_it.iterator_nn=make_single_iterator_symbol(expr_it.body_sn, proc_data.nn, proc_data.an, expr_it.local_iterator_number, expr_it.sign); if(typeid(*expr_it.sign)==typeid(TerminalAsterisk)) expr_it.reflexive=true; else if(typeid(*expr_it.sign)==typeid(TerminalPlus)) expr_it.reflexive=false; else assert(false); return true; } else if(typeid(*expr)==typeid(NonterminalExpressionIterationPair)) { NonterminalExpressionIterationPair &expr_it2=*dynamic_cast<NonterminalExpressionIterationPair *>(expr); if(proc_data.member_expression) { cout << "Warning: member name specification at "; proc_data.member_expression->t->print_location(cout); cout << " has no effect inside iteration at "; expr_it2.kw->print_location(cout); cout << ".\n"; } NonterminalMemberExpression *backup=proc_data.member_expression; proc_data.member_expression=NULL; proc_data.number_of_nested_iterations++; bool iabc_backup=proc_data.inside_anything_but_concatenation; proc_data.inside_anything_but_concatenation=true; bool result1=process_expression_proc(expr_it2.expr1, proc_data); bool result2=process_expression_proc(expr_it2.expr2, proc_data); proc_data.inside_anything_but_concatenation=iabc_backup; proc_data.number_of_nested_iterations--; proc_data.member_expression=backup; if(!result1 || !result2) return false; expr_it2.local_iterator_number=++proc_data.nonterminal().number_of_iterators; expr_it2.body1_sn=make_body_symbol(expr_it2.expr1, proc_data.nn, proc_data.an, expr_it2.local_iterator_number, 1, expr_it2.kw); expr_it2.body2_sn=make_body_symbol(expr_it2.expr2, proc_data.nn, proc_data.an, expr_it2.local_iterator_number, 2, expr_it2.kw); expr_it2.iterator_nn=make_pair_iterator_symbol(expr_it2.body1_sn, expr_it2.body2_sn, proc_data.nn, proc_data.an, expr_it2.local_iterator_number, expr_it2.kw); return true; } else if(typeid(*expr)==typeid(NonterminalExpressionEpsilon)) return true; else if(typeid(*expr)==typeid(NonterminalExpressionSymbol)) { NonterminalExpressionSymbol &expr_s=*dynamic_cast<NonterminalExpressionSymbol *>(expr); Terminal *t=expr_s.symbol; int tn=data.find_terminal(t->text); int nn=data.find_nonterminal(t->text); assert(tn==-1 || nn==-1); if(tn==-1 && nn==-1) { cout << "Undefined symbol " << t->text << " at "; t->print_location(cout); cout << ".\n"; return false; } proc_data.symbol_count++; expr_s.number_of_iterations=proc_data.number_of_nested_iterations; ClassHierarchy::Class *internal_class_for_this_symbol; ClassHierarchy::Class *external_class_for_this_symbol; if(tn!=-1) { if(tn==data.eof_terminal_number) { cout << "Warning: explicit use of end-of-file symbol at "; t->print_location(cout); cout << ".\n"; } expr_s.sn=SymbolNumber::for_terminal(tn); internal_class_for_this_symbol=data.terminals[tn].type; external_class_for_this_symbol=NULL; } else if(nn!=-1) { NonterminalData &nonterminal=data.nonterminals[nn]; expr_s.sn=SymbolNumber::for_nonterminal(nn); if(nonterminal.external_type) { internal_class_for_this_symbol=nonterminal.type; external_class_for_this_symbol=nonterminal.external_type; } else { internal_class_for_this_symbol=nonterminal.type; external_class_for_this_symbol=NULL; } } assert(internal_class_for_this_symbol); NonterminalMemberExpression *m_expr=proc_data.member_expression; if(m_expr) m_expr->number_of_affected_symbols++; if(m_expr && m_expr->is_nothing) return true; if(!m_expr && data.variables.default_member_name_is_nothing) return true; if(!m_expr) { ClassHierarchy::Class *class_assigned_to_host_nonterminal=data.get_class_assigned_to_alternative(proc_data.nn, proc_data.an); string s=generate_default_data_member_name(proc_data.symbol_count); triad<ClassHierarchy::Class *, int, int> cnr=class_assigned_to_host_nonterminal->find_data_member_in_direct_relatives(s.c_str()); if(cnr.first) { cout << "Unable to generate default data member name for "; cout << data.full_symbol_name(expr_s.sn, false) << " at "; t->print_location(cout); cout << ", because identifier " << s << " is already in use.\n"; return false; } ClassHierarchy::DataMember *new_data_member=new ClassHierarchy::DataMember; new_data_member->name=s; new_data_member->was_implicitly_declared=true; new_data_member->declared_at=t; new_data_member->number_of_nested_iterations=proc_data.number_of_nested_iterations; if(external_class_for_this_symbol) { new_data_member->type=external_class_for_this_symbol; new_data_member->internal_type_if_there_is_an_external_type=internal_class_for_this_symbol; } else { new_data_member->type=internal_class_for_this_symbol; new_data_member->internal_type_if_there_is_an_external_type=NULL; } classes.put_data_member_to_class(new_data_member, class_assigned_to_host_nonterminal); expr_s.data_member_i=new_data_member; return true; } assert(m_expr); /* What are we going to do is to unify data types. */ /* Consider ( ... symbol ... ) = (member expression) */ /* We have just read _symbol_, and we have access to the */ /* previously read member expression. */ /* internal_class_for_this_symbol and external_class_... are */ /* properties of symbol that doesn't depend upon this */ /* context. m_expr->everything are different properties of */ /* the member expression. We have to modify data members */ /* created by member expression so that they would become */ /* capable of holding our symbol, while retaining all holding*/ /* capabilities they had before. */ // 6 cases to consider. if(m_expr->i_specified && !m_expr->e_specified && !external_class_for_this_symbol) { // the most simple case: just unify the type data
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -