/* Copyright Dave Bone 1998 - 2014 All Rights Reserved. No part of this document may be reproduced without written consent from the author. FILE: mpost_output.lex Dates: 29 Nov. 2005 Purpose: Create Pascal type railroad diagrams per grammar rule. The output file is code for Mpost to generate the diagrams. */ /@ @i "/usr/local/yacco2/copyright.w" @** |mpost_output| Grammar.\fbreak Write out the |cweb|'s representation of the grammar's code and |mpost|'s railroad diagrams. These appropriate files have the grammar's name along with extension ``w'' for |cweave| to compile and extension ``mp'' for |mpost| to draw from. Enjoy the art work. All the grammar's vocabulary are cross referenced to accomodate the grammar writer. The railroad diagrams show left recursion and where the subrule has appropriate syntax directed code, it redraws the subrule with each element's position number below it. This aids in the writing of syntax directed code when individual parameters are referenced by use of the |sf| stack frame structure. Each element within the stack frame has a naming convention of |p#__| where the number sign is the element's position within the subrule sentence relative to 1.\fbreak \fbreak Fodder to this grammar is provided by the tree container doing a prefix traverse. Why a prefix traverse? The parent node allowed me to declare the |mpost| variables before their use.\fbreak Caveat: Grammar c++ comments must observe |cweave| dictums: underscored items like variable names must be enclosed with ${\vert}$ and the number sign ``\#'' must use its literal of backslash \#. Without these observances, |pdftex| will honk. @/ fsm (fsm-id "mpost_output.lex",fsm-filename mpost_output,fsm-namespace NS_mpost_output ,fsm-class Cmpost_output{ constructor MPOST_CWEB_LOAD_XLATE_CHRS(this); *** user-prefix-declaration #include "time.h" #include "o2_externs.h" extern void XLATE_SYMBOLS_FOR_cweave(const char* Sym_to_xlate,char* Xlated_sym); extern void PRT_RULE_S_FIRST_SET(std::ofstream& Ofile,NS_yacco2_terminals::rule_def* Rule_def); extern int MPOST_CWEB_xlated_symbol(AST* Sym,char* Xlated_sym); extern STATES_type LR1_STATES; extern COMMON_LA_SETS_type COMMON_LA_SETS; #include "cweave_fsm_sdc.h" #include "cweave_lhs_sdc.h" #include "cweave_sdc.h" #include "cweave_T_sdc.h" *** user-declaration public: char big_buf_[BIG_BUFFER_32K]; std::map xlated_names_; std::vector no_subrules_per_rule_; std::string gened_date_time_; std::string mp_filename_; std::ofstream omp_file_; std::string w_filename_; std::string w_index_filename_; std::ofstream ow_file_; std::ofstream ow_index_file_; std::ofstream ow_t_file_; std::ofstream ow_err_file_; std::ofstream ow_lrk_file_; std::string grammar_filename_prefix_; std::string fq_filename_noext_; int w_fig_no_; int rule_no_; int subrule_no_; int elem_no_; int no_of_rules_; int no_of_subrules_; std::string rule_name_; std::string elem_name_; rule_def* rule_def_; T_subrule_def* subrule_def_; std::string mp_dimension_; static void MPOST_CWEB_gen_dimension_name(Cmpost_output* Fsm ,std::string& Mp_obj_name,int Dimension); static void MPOST_CWEB_calc_mp_obj_name(Cmpost_output* Fsm ,std::string& Mp_obj_name,int Elem_no); static void MPOST_CWEB_wrt_mp_rhs_elem(Cmpost_output* Fsm ,std::string& Elem_name,std::string& Drw_how); static void MPOST_CWEB_gen_sr_elem_xrefs(Cmpost_output* Fsm ,AST* Subrule_tree); static void MPOST_CWEB_woutput_sr_sdcode(Cmpost_output* Fsm ,T_subrule_def* Subrule_def); static void MPOST_CWEB_wrt_fsm(Cmpost_output* Fsm ,T_fsm_phrase* Fsm_phrase); static void MPOST_CWEB_wrt_rule_s_lhs_sdc(Cmpost_output* Fsm, rule_def* Rule_def); static bool MPOST_CWEB_should_subrule_be_printed(Cmpost_output* Fs ,T_subrule_def* Subrule_def); static void MPOST_CWEB_xref_refered_T(Cmpost_output* Fsm ,refered_T* R_T); static void MPOST_CWEB_xref_refered_rule(Cmpost_output* Fsm ,refered_rule* R_rule); static void MPOST_CWEB_LOAD_XLATE_CHRS(Cmpost_output* Fsm); static void MPOST_CWEB_EMIT_PREFIX_CODE(Cmpost_output* Fsm); static void MPOST_CWEB_wrt_T(Cmpost_output* Fsm ,T_terminals_phrase* T_phrase); static void MPOST_CWEB_wrt_Err(Cmpost_output* Fsm ,T_error_symbols_phrase* Err_phrase); static void MPOST_CWEB_wrt_Lrk(Cmpost_output* Fsm ,T_lr1_k_phrase* Lrk_phrase); std::list rules_for_fs_prt_; static void MPOST_CWEB_crt_rhs_sym_str(state_element* se,std::string* Xlated_str); *** /@ Due to a MS 2005 Visual Studio defficiency, part of the ctor's initialization is included here instead of all being done by |MPOST_CWEB_EMIT_PREFIX_CODE|. The reason is noted in the documentation of |o2externs|. @/ op no_subrules_per_rule_.push_back(0); time_t theTime= time(0); char*cTime= ctime(&theTime); gened_date_time_+= string(cTime); int n= gened_date_time_.find('\n'); gened_date_time_[n]= ' '; mp_dimension_+= " abcdefghijklmnopqrstuvwxyz"; w_fig_no_= 0; rule_def_= 0; subrule_def_= 0; rule_no_= 0; subrule_no_= 0; elem_no_= 0; no_of_rules_= 0; no_of_subrules_= 0; mp_filename_+= grammar_filename_prefix_.c_str(); mp_filename_+= ".mp"; omp_file_.open(mp_filename_.c_str(),ios_base::out|ios::trunc); if(!omp_file_){ CAbs_lr1_sym*sym= new Err_bad_filename(mp_filename_.c_str()); sym->set_who_created(__FILE__,__LINE__); parser__->add_token_to_error_queue(*sym); parser__->set_stop_parse(true); return; } w_filename_+= grammar_filename_prefix_.c_str(); w_filename_+= ".w"; ow_file_.open(w_filename_.c_str(),ios_base::out|ios::trunc); if(!ow_file_){ CAbs_lr1_sym*sym= new Err_bad_filename(w_filename_.c_str()); sym->set_who_created(__FILE__,__LINE__); parser__->add_token_to_error_queue(*sym); parser__->set_stop_parse(true); return; } w_index_filename_+= grammar_filename_prefix_.c_str(); w_index_filename_+= "_idx.w"; ow_index_file_.open(w_index_filename_.c_str(),ios_base::out|ios::trunc); if(!ow_index_file_){ CAbs_lr1_sym*sym= new Err_bad_filename(w_index_filename_.c_str()); sym->set_who_created(__FILE__,__LINE__); parser__->add_token_to_error_queue(*sym); parser__->set_stop_parse(true); return; } KCHARP t_file = "T.w"; ow_t_file_.open(t_file,ios_base::out|ios::trunc); if(!ow_t_file_){ CAbs_lr1_sym*sym= new Err_bad_filename(t_file); sym->set_who_created(__FILE__,__LINE__); parser__->add_token_to_error_queue(*sym); parser__->set_stop_parse(true); return; } KCHARP err_file = "Err.w"; ow_err_file_.open(err_file,ios_base::out|ios::trunc); if(!ow_err_file_){ CAbs_lr1_sym*sym= new Err_bad_filename(err_file); sym->set_who_created(__FILE__,__LINE__); parser__->add_token_to_error_queue(*sym); parser__->set_stop_parse(true); return; } KCHARP lrk_file = "Lrk.w"; ow_lrk_file_.open(lrk_file,ios_base::out|ios::trunc); if(!ow_lrk_file_){ CAbs_lr1_sym*sym= new Err_bad_filename(lrk_file); sym->set_who_created(__FILE__,__LINE__); parser__->add_token_to_error_queue(*sym); parser__->set_stop_parse(true); return; } MPOST_CWEB_EMIT_PREFIX_CODE(this); *** } ,fsm-version "1.0",fsm-date "29 Nov. 2005",fsm-debug "false" ,fsm-comments "Output grammar rules railroad diagrams for mpost that cweb program uses.") @"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T" rules{ Rmpost_output /@ Note how i use the sentence recognition to complete |mpost| figures. The individual figures are defined before their execution. @/ (){ -> Rgrammar_phrase Rks_epi Rfsm_phrase Rks_epi Rparallel_phrase Rks_epi RT_enum_phrase Rks_epi Rlr1_k_phrase Rks_epi Rrc_phrase Rks_epi Rterms_phrase Rks_epi Rerr_phrase Rks_epi Rrule_phrase Rrules Rks_epi eog { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; KCHARP mp_init_vars = "init_variables;"; fsm->omp_file_ << mp_init_vars << endl; KCHARP mp_figure = "beginfig(%i);\n" " drw_rule(%i);\n" "endfig;"; KCHARP sr_figure = "beginfig(%i);\n" " drw_rule_a_rhs(%i,%i);\n" "endfig;"; int rule_no = 1; int fig_no(0); for(;rule_no <= fsm->no_of_rules_;++rule_no){ ++fig_no; sprintf(fsm->big_buf_,mp_figure,fig_no,rule_no); fsm->omp_file_ << fsm->big_buf_ << endl; int no_srs = fsm->no_subrules_per_rule_[rule_no]; int sr_no(1); for(;sr_no <= no_srs;++sr_no){ ++fig_no; sprintf(fsm->big_buf_,sr_figure,fig_no,rule_no,sr_no); fsm->omp_file_ << fsm->big_buf_ << endl; } } KCHARP mp_end = "end;"; fsm->omp_file_ << mp_end << endl; fsm->omp_file_.close(); KCHARP w_fsc_file = "@** First Set Language for \\Olinker.\\fbreak\n" "\\openin 1 = \"%s.fsc\"\n" // macro file open "\\ifeof 1 true\n" // test the result " \\closein 1\n" "\\else\n" " \\closein 1\n" " \\listing{\"%s.fsc\"}" "\\fi"; sprintf(fsm->big_buf_,w_fsc_file,fsm->fq_filename_noext_.c_str() ,fsm->fq_filename_noext_.c_str()); fsm->ow_file_ << fsm->big_buf_ << endl; KCHARP w_lr1_states = "@** Lr1 State Network.\\fbreak\n" "\\statecolumnspace %s"; sprintf(fsm->big_buf_,w_lr1_states," "); fsm->ow_file_ << fsm->big_buf_ << endl; KCHARP w_stateno = // stateno, vectored into symbol, conflict "\\stateno{%i} {%s} {%s}\n" "\\halign{\n" "\\span\\statetemplate\n" "\\statetitle"; char vectored_into[Max_cweb_item_size]; char rule_name[Max_cweb_item_size]; char subrule_sym[Max_cweb_item_size]; char cur_sym[Max_cweb_item_size]; char nxtsym_1[Max_cweb_item_size]; char nxtsym_2[Max_cweb_item_size]; char state_type[Max_cweb_item_size]; char la_set_no[Max_cweb_item_size]; string w_possible_ar_code; KCHARP la_set_no_template = "%i"; KCHARP state_type_template = "%s"; KCHARP three_symbols_string_template = "%s %s %s"; // 3 symbols: current and 2 la KCHARP w_stateno_subrule = "{%s}&\n" // closure or transitive "{%s}&\n" // rule "{%i\\hss}&\n" // rule no "{%i\\hss}&\n" // subrule no "{%i\\hss}&\n" // element pos "{%s}&\n" // current symbol "{%i\\hss}&\n" // born state no "{%i\\hss}&\n" // goto state no "{%i\\hss}&\n" // reduced state no "{%s\\hss}\\cr"; // la set if reduced int fnd_reduced_stateno(0); STATES_ITER_type si = LR1_STATES.begin(); STATES_ITER_type sie = LR1_STATES.end(); for(;si!=sie;++si){// walk the states vectored_into[0] = (char)0; w_possible_ar_code.clear(); state_type[0] = (char)0; state* cur_state = *si; if(cur_state->state_no_ != 1){// state 1 vector into is empty XLATE_SYMBOLS_FOR_cweave (cur_state->entry_symbol_literal(),vectored_into); } switch (cur_state->state_type_){ case 0:{//shift only sprintf(state_type,state_type_template,"\\Shiftonly"); break; } case 1:{ sprintf(state_type,state_type_template,"\\Reduceonly"); break; } case 2:{ sprintf(state_type,state_type_template,"\\ShiftReduce"); break; } case 3:{ sprintf(state_type,state_type_template,"\\MultipleReduces"); break; } case 4:{ sprintf(state_type,state_type_template,"\\ShiftandMultipleReduces"); break; } } w_possible_ar_code.append(vectored_into); if (cur_state->vectored_into_by_elem_ == LR1_PARALLEL_OPERATOR){ // add arbitration code? to |vectored_into| string if (cur_state->arbitrator_name_ != 0){ w_possible_ar_code += "\\ arbitration-code: \\ |"; w_possible_ar_code += cur_state->arbitrator_name_->c_str(); w_possible_ar_code += "|"; }else{ w_possible_ar_code += "\\ arbitration-code: \\ \\epsilon"; } } sprintf(fsm->big_buf_ ,w_stateno ,cur_state->state_no_ ,w_possible_ar_code.c_str()//|vectored_into| ,state_type); fsm->ow_file_ << fsm->big_buf_ << endl; S_VECTORS_ITER_type svi = cur_state->state_s_vector_.begin(); S_VECTORS_ITER_type svie = cur_state->state_s_vector_.end(); string rhs_syms_str; for(;svi!=svie;++svi){ S_VECTOR_ELEMS_ITER_type seli = svi->second.begin(); S_VECTOR_ELEMS_ITER_type selie = svi->second.end(); for(;seli!=selie;++seli){ rhs_syms_str.clear(); state_element* se = *seli; rule_def* rd = se->subrule_def_->its_rule_def(); T_subrule_def* srd = se->subrule_def_; rule_name[0] = (char)0; subrule_sym[0] = (char)0; cur_sym[0] = (char)0; la_set_no[0] = (char)0; XLATE_SYMBOLS_FOR_cweave(rd->rule_name()->c_str(),rule_name); int elem_pos(0); if(se->previous_state_ == 0) elem_pos = 1; elem_pos = MPOST_CWEB_xlated_symbol(se->sr_element_,cur_sym); if(se->goto_state_==0){// reducing subrule sprintf(la_set_no,la_set_no_template,se->common_la_set_idx_+1); }else{// no la set } if (se->reduced_state_ != 0) { fnd_reduced_stateno = se->reduced_state_->state_no_; } else{ // find from merged into fnd_reduced_stateno=-1; if (se->next_state_element_->reduced_state_ != 0){ fnd_reduced_stateno = se->next_state_element_->reduced_state_->state_no_; } } fsm->MPOST_CWEB_crt_rhs_sym_str(se,&rhs_syms_str); sprintf(fsm->big_buf_ ,w_stateno_subrule ,(elem_pos == 1)?"c":"t" ,rule_name ,rd->rule_no() ,srd->subrule_no_of_rule() ,elem_pos ,rhs_syms_str.c_str() ,se->closure_state_->state_no_ ,(se->goto_state_ !=0)?se->goto_state_->state_no_:0 ,fnd_reduced_stateno ,la_set_no ); fsm->ow_file_ << fsm->big_buf_ << endl; } } fsm->ow_file_ << "}" << endl; } KCHARP w_end = "@** Index."; fsm->ow_file_ << w_end << endl; fsm->ow_file_.close(); *** } } Rgrammar_phrase (){ -> "grammar-phrase" } Rks_epi /@ Due to technical problems with the |convertMPtoPDF| macro, the epsilon subrule is drawn with a dot. @/ (){ -> Rks -> } Rks (){ -> Rks Rk -> Rk } Rk (){ -> "cweb-marker" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; WRT_CWEB_MARKER(&fsm->ow_file_,sf->p1__->ast()); *** } } Rfsm_phrase (){ -> "fsm-phrase" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; fsm->MPOST_CWEB_wrt_fsm(fsm,sf->p1__); *** } } Rparallel_phrase (){ -> "parallel-parser-phrase" -> |.| } RT_enum_phrase (){ -> "T-enum-phrase" } Rerr_phrase (){ -> "error-symbols-phrase" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; fsm->MPOST_CWEB_wrt_Err(fsm,sf->p1__); *** } } Rrc_phrase (){ -> "rc-phrase" } Rlr1_k_phrase (){ -> "lr1-k-phrase" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; fsm->MPOST_CWEB_wrt_Lrk(fsm,sf->p1__); *** } } Rterms_phrase (){ -> "terminals-phrase" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; fsm->MPOST_CWEB_wrt_T(fsm,sf->p1__); *** } } Rrule_phrase /@ Define the number of rules for |mpost|. @/ (){ -> "rules-phrase" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; fsm->no_of_rules_ = sf->p1__->rules_alphabet()->size(); KCHARP mp_no_of_rules = "no_of_rules := %i;"; sprintf(fsm->big_buf_,mp_no_of_rules,fsm->no_of_rules_); fsm->omp_file_ << fsm->big_buf_ << endl; *** } } Rrules (){ -> Rks_epi Rrule -> Rrules Rks_epi Rrule } Rrule (){ -> Rrule_def Rsubrules } Rrule_def /@ Define rule for |mpost| and |cweb|. To help the grammar writer, walk the rule's subrules to generate a |cweb| cross-reference per subrule element. Originally this was done at the subrule level to be specific to the subrule entry instead of at the overall rule level. This meant that each subrule had to be redrawn with a |cweb| directive even when there was no syntax directed code present. Just ugly is my take so i follow Occam's dictum. @/ (){ -> "rule-def" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; fsm->rule_def_ = sf->p1__; fsm->rules_for_fs_prt_.push_back(fsm->rule_def_); KCHARP rname = fsm->rule_def_->rule_name()->c_str(); ++fsm->w_fig_no_; ++fsm->rule_no_; fsm->subrule_no_ = 0; KCHARP mp_rule_names = "rule_names[%i].literal := \"%s\";" "rule_names[%i].vname := \"%s\";"; sprintf(fsm->big_buf_,mp_rule_names,fsm->rule_no_,rname,fsm->rule_no_,rname); fsm->omp_file_ << fsm->big_buf_ << endl; T_subrules_phrase* sr_ph = fsm->rule_def_->subrules(); fsm->no_of_subrules_ = sr_ph->no_subrules(); KCHARP mp_rule_s_no_rhs = "rule_s_no_rhs[%i] := %i;"; sprintf(fsm->big_buf_,mp_rule_s_no_rhs ,fsm->rule_no_,fsm->no_of_subrules_); fsm->omp_file_ << fsm->big_buf_ << endl; fsm->no_subrules_per_rule_.push_back(fsm->no_of_subrules_);//[rule \#] KCHARP rule_cweb = "@*2 |@!%s| rule.\\fbreak\n"; sprintf(fsm->big_buf_,rule_cweb,rname); fsm->ow_file_ << fsm->big_buf_; if(fsm->rule_def_->cweb_marker() != 0){ WRT_CWEB_MARKER(&fsm->ow_file_,fsm->rule_def_->cweb_marker()); } KCHARP rule_cweb_diagram = "\\fbreak\n" "\\convertMPtoPDF{%s.%i}{1}{1}\n"; sprintf(fsm->big_buf_,rule_cweb_diagram ,fsm->grammar_filename_prefix_.c_str() ,fsm->w_fig_no_); fsm->ow_file_ << fsm->big_buf_; std::vector* srules = sr_ph->subrules(); std::vector::iterator i = srules->begin(); std::vector::iterator ie = srules->end(); for(;i!=ie;++i){ T_subrule_def* srd = *i; fsm->MPOST_CWEB_gen_sr_elem_xrefs(fsm,srd->subrule_s_tree()); } fsm->MPOST_CWEB_wrt_rule_s_lhs_sdc(fsm,fsm->rule_def_); *** } } Rsubrules (){ -> Rsubrule -> Rsubrules Rsubrule } Rsubrule (){ -> Rsubrule_def Relements } Rsubrule_def (){ -> "subrule-def" { /@ The |eosubrule| T has no meaning in the drawn subrule. It is just a specific end-of-subrule indicator. So it is removed from the rhs element count of the subrule for |mpost| processing so that it does not get drawn. The balance of the logic relates to |cweb|'s document: comments about the subrule and the appropriate |mpost| rendering. One subtlety is the forced drawing of a single subrule that also has a rule's lhs syntax directed code. Normally i save the redrawing of the subrule as the forest and the tree is the same. But having the rule syntax code requires to have the subrule directive. Without it there are 2 code directives back-to-back that honks. @/ op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; ++fsm->w_fig_no_; ++fsm->subrule_no_; fsm->elem_no_ = 0; fsm->subrule_def_ = sf->p1__; int no_elements = fsm->subrule_def_->no_of_elems()-1; if(no_elements == 0) no_elements = 1;// epsilon subrule KCHARP mp_rule_s_subrule_no_elems = "rule_s_subrule_no_elems[%i][%i]:= %i;"; sprintf(fsm->big_buf_,mp_rule_s_subrule_no_elems ,fsm->rule_no_,fsm->subrule_no_,no_elements); fsm->omp_file_ << fsm->big_buf_ << endl; if(fsm->MPOST_CWEB_should_subrule_be_printed(fsm,fsm->subrule_def_) == false) return; KCHARP rname = fsm->rule_def_->rule_name()->c_str(); KCHARP subrule_cweb = "@*3 |%s|'s subrule %i.\\fbreak\n"; if((fsm->rule_def_->rule_lhs() != 0) || (fsm->no_of_subrules_ > 1)){ sprintf(fsm->big_buf_,subrule_cweb,rname,fsm->subrule_no_); fsm->ow_file_ << fsm->big_buf_; } if(fsm->subrule_def_->cweb_marker() != 0){ WRT_CWEB_MARKER(&fsm->ow_file_,fsm->subrule_def_->cweb_marker()); cout << "subrule's cweb marker for rule: " << rname << endl; }else{ cout << "no subrule's cweb marker for rule: " << rname << endl; } KCHARP subrule_cweb_diagram = "\\fbreak" "\\convertMPtoPDF{%s.%i}{1}{1}\n"; if((fsm->rule_def_->rule_lhs() != 0) || (fsm->no_of_subrules_ > 1)){ sprintf(fsm->big_buf_,subrule_cweb_diagram ,fsm->grammar_filename_prefix_.c_str() ,fsm->w_fig_no_); fsm->ow_file_ << fsm->big_buf_; } fsm->MPOST_CWEB_woutput_sr_sdcode(fsm,fsm->subrule_def_); *** } } Relements (){ -> Relement -> Relements Relement } Relement /@ Use of \invisibleshift to make grammar lr(1). @/ (){ -> "refered-T" |.| { /@ Why is there a test for ${\backslash}$" within the T? Glad u asked as |mpost| has problems dealing with this legitimate escape sequence and the double quote sequence within the c string. So this was my 1st attempt to silence the honk. Unfortunately the char(34) |mpost| operator does not convert the 34 into the " character. For the moment i will leave this as is. U will see other attempts like this throughout the grammar. @/ op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; ++fsm->elem_no_; std::string mp_obj_type("Circle_solid"); std::string mp_elem_name(sf->p1__->t_in_stbl()->t_def()->t_name()->c_str()); string::size_type x = mp_elem_name.find("\\\""); if(x != string::npos){ mp_elem_name.clear(); mp_elem_name+= "char(34)"; } fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); *** } -> "refered-rule" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; ++fsm->elem_no_; std::string mp_obj_type("Box_solid"); std::string mp_elem_name(sf->p1__->Rule_in_stbl()-> r_def()->rule_name()->c_str()); fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); *** } -> "eosubrule" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; ++fsm->elem_no_; if(fsm->elem_no_ == 1){// epsilon std::string mp_obj_type("Circle_solid"); std::string mp_elem_name(" "); fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); } *** } -> "refered-T" "refered-T" "called thread eosubrule" { /@ Why is there a re-aligning on the number of |rule_s_subrule_no_elems|? Two reasons: Due to the tree walk being top down, initially the number of items are determined by the |subrule-def| T before processing the actual subrule sentence. Due to the calling of threads, this number gets shrunk as i combine the 3 parts of the called thread into 1 item. Though it looks like a mistake in the emitted |mpost| code, it's a slight inefficiency to manage a nice picture.\fbreak \fbreak This comment hold for the other version of thread call below. @/ op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; KCHARP re_align_nos = "rule_s_subrule_no_elems[%i][%i]:= %i;"; sprintf(fsm->big_buf_,re_align_nos ,fsm->rule_no_,fsm->subrule_no_,3); fsm->omp_file_ << fsm->big_buf_ << "% re-align cnt" << endl; ++fsm->elem_no_; std::string mp_obj_type("Circle_dotted"); std::string mp_elem_name; if(sf->p1__->its_t_def()->enum_id() == T_Enum::T_LR1_parallel_operator_){ mp_elem_name += "|||"; }else{ mp_elem_name += "|t|"; } fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); ++fsm->elem_no_; mp_obj_type.clear(); mp_obj_type += "Circle_dotted"; mp_elem_name.clear(); mp_elem_name += sf->p2__->t_in_stbl()->t_def()->t_name()->c_str(); string::size_type x = mp_elem_name.find("\\\""); if(x != string::npos){ mp_elem_name.erase(); mp_elem_name+= "char(34)"; } fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); ++fsm->elem_no_; mp_elem_name.clear(); mp_obj_type.clear(); mp_obj_type += "Box_dotted"; mp_elem_name += sf->p3__->ns()->identifier()->c_str(); mp_elem_name += "::"; mp_elem_name += sf->p3__->called_thread_name()->identifier()->c_str(); fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); *** } -> "refered-T" "refered-T" "null call thread eosubrule" { op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; KCHARP re_align_nos = "rule_s_subrule_no_elems[%i][%i]:= %i;"; sprintf(fsm->big_buf_,re_align_nos,fsm->rule_no_,fsm->subrule_no_,3); fsm->omp_file_ << fsm->big_buf_ << "% re-align cnt" << endl; ++fsm->elem_no_; std::string mp_obj_type("Circle_dotted"); std::string mp_elem_name; if(sf->p1__->its_t_def()->enum_id() == T_Enum::T_LR1_parallel_operator_){ mp_elem_name += "|||"; }else{ mp_elem_name += "|t|"; } fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); mp_elem_name.clear(); ++fsm->elem_no_; mp_elem_name += sf->p2__->t_in_stbl()->t_def()->t_name()->c_str(); string::size_type x = mp_elem_name.find("\\\""); if(x != string::npos){ mp_elem_name.clear(); mp_elem_name+= "char(34)"; } fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); ++fsm->elem_no_; mp_elem_name.clear(); mp_obj_type.clear(); mp_obj_type += "Box_dotted"; mp_elem_name += "NULL"; fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); *** } -> "refered-T" "refered-T" |.|{ op Cmpost_output* fsm = (Cmpost_output*)rule_info__.parser__->fsm_tbl__; ++fsm->elem_no_; std::string mp_obj_type("Circle_solid"); std::string mp_elem_name(sf->p1__->t_in_stbl()->t_def()->t_name()->c_str()); string::size_type x = mp_elem_name.find("\\\""); if(x != string::npos){ mp_elem_name.erase(); mp_elem_name+= "char(34)"; } fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); ++fsm->elem_no_; mp_obj_type.clear(); mp_obj_type += "Circle_solid"; mp_elem_name.clear(); mp_elem_name += sf->p2__->t_in_stbl()->t_def()->t_name()->c_str(); x = mp_elem_name.find("\\\""); if(x != string::npos){ mp_elem_name.erase(); mp_elem_name+= "char(34)"; } fsm->MPOST_CWEB_wrt_mp_rhs_elem(fsm,mp_elem_name,mp_obj_type); *** } } }// end of rules