/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:		prt_xrefs_docs.lex
Dates:		3 Sept. 2007
Purpose:	Create various xref docs.
*/
/@
@i "/usr/local/yacco2/copyright.w"
@** |prt_xrefs_docs.lex| Grammar.\fbreak
Various cross references:\fbreak
\ptindent{1) used vocabulary symbols referenced against each rule's subrule and position}
\ptindent{2) first set per rule}
\ptindent{3) productions derived lr states}
\ptindent{4) list of reducing lr states}
\ptindent{5) Per state Follow set calculations}
\ptindent{6) Commonized follow sets for reducing subrules}
@/
fsm	
(fsm-id "prt_xrefs_docs.lex",fsm-filename prt_xrefs_docs,fsm-namespace NS_prt_xrefs_docs
,fsm-class Cprt_xrefs_docs{
  user-prefix-declaration
#include "time.h"
#include "o2_externs.h"
#include "prt_sr_elements.h"
extern void PRT_RULE_S_FIRST_SET(std::ofstream& Ofile,NS_yacco2_terminals::rule_def* Rule_def);
extern void XLATE_SYMBOLS_FOR_cweave(const char* Sym_to_xlate,char* Xlated_sym);
extern int MPOST_CWEB_xlated_symbol(AST* Sym,char* Xlated_sym);
extern STATES_type LR1_STATES;
extern COMMON_LA_SETS_type COMMON_LA_SETS;

  ***
  user-declaration
    public:
	  char big_buf_[BIG_BUFFER_32K];		
          set<int> prt_sr_elems_filter_;
	  std::map <int , std::string> xlated_names_;
	  std::map <int , std::list<state_element*> > productions_derived_states_list_;
	  std::vector <state* > reducing_states_list_;
	  std::vector <int> no_subrules_per_rule_;
	  std::string gened_date_time_;
      std::string w_index_filename_;
      std::ofstream ow_index_file_;
      std::string grammar_filename_prefix_;
	  std::string fq_filename_noext_;
      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::list<NS_yacco2_terminals::rule_def*> rules_for_fs_prt_;
   std::map<std::string, std::list<std::string> > xref_of_used_symbols_;
   void add_symbol_to_xref_map(std::string& Key,std::string& Ref);   
   void determine_closure_derived_states();
   void prt_states_follow_set();
   void prt_follow_set_local_yield(follow_element* Fe);
   void prt_follow_set_creators(follow_element* Fe);
   void prt_follow_set_transitions(follow_element* Fe);
   void prt_follow_set_merges(follow_element* Fe);
   void prt_state_s_follow_set_rules(state* Cur_state);
   void prt_common_follow_set_la();
   ***
  user-implementation 
void Cprt_xrefs_docs::determine_closure_derived_states(){
 std::map <int , std::list<state_element*> >::iterator xi;
   std::map <int , std::list<state_element*> >::iterator xie;
   STATES_ITER_type si= LR1_STATES.begin();
    STATES_ITER_type sie= LR1_STATES.end();
    int integerize_the_subrule(0);
    for(;si!=sie;++si){// read states
        state*cur_state= *si;
        using namespace NS_yacco2_T_enum; 
 	S_VECTORS_ITER_type svi = cur_state->state_s_vector_.begin();
	S_VECTORS_ITER_type svie = cur_state->state_s_vector_.end();
	S_VECTORS_ITER_type tvi = cur_state->state_s_vector_.find(-T_Enum::T_T_eosubrule_);
        if(tvi != svie){
            reducing_states_list_.push_back(cur_state);
            goto rd_vector_s_elems;
        }
	tvi = cur_state->state_s_vector_.find(-T_Enum::T_T_called_thread_eosubrule_);
        if(tvi != svie){
            reducing_states_list_.push_back(cur_state);
            goto rd_vector_s_elems;
        }
	tvi = cur_state->state_s_vector_.find(-T_Enum::T_T_null_call_thread_eosubrule_);
        if(tvi != svie){
            reducing_states_list_.push_back(cur_state);
            goto rd_vector_s_elems;
        }
rd_vector_s_elems:;
	for(;svi!=svie;++svi){// rd the same vector's elements
	  S_VECTOR_ELEMS_ITER_type seli = svi->second.begin();
	  S_VECTOR_ELEMS_ITER_type selie = svi->second.end();
	  for(;seli!=selie;++seli){
	    state_element* se = *seli;
	    if(se->previous_state_ != 0) continue;
            integerize_the_subrule = se->subrule_def_->its_grammar_s_pos();
            xi = productions_derived_states_list_.find(integerize_the_subrule);
            if(xi == productions_derived_states_list_.end()){
               productions_derived_states_list_[integerize_the_subrule] = std::list<state_element*>(); 
            }
            xi = productions_derived_states_list_.find(integerize_the_subrule);
            xi->second.push_back(se);
	  }
        }
    }
}
/@
@*3 |add_symbol_to_xref_map|.
@/
    void Cprt_xrefs_docs::add_symbol_to_xref_map(std::string& Key,std::string& Ref){
      std::map<std::string, std::list<std::string> >::iterator i;
	  i = xref_of_used_symbols_.find(Key.c_str());
	  if(i ==xref_of_used_symbols_.end()){
	    xref_of_used_symbols_[Key.c_str()] = std::list<std::string>();
		i = xref_of_used_symbols_.find(Key); 
                std::list<std::string>& xxx = i->second;
		xxx.push_back(string(Ref.c_str()));
		return; 
	  }else{
                std::list<std::string>& xxx = i->second;
		xxx.push_back(string(Ref.c_str()));
	  }	 
	 }
/@
@*3 |prt_follow_set_local_yield|.
@/
   void Cprt_xrefs_docs::prt_follow_set_local_yield(follow_element* Fe){
     KCHARP w_follset_local_yield = 
	    "\\FollSetreducinglocalyield %s"; 
     sprintf(big_buf_,w_follset_local_yield," ");
     ow_index_file_ << big_buf_ << endl;
     KCHARP w_follset_t = 
	    "%s"; 
     char t_name[Max_cweb_item_size];
     FOLLOW_SETS_ITER_type fsi = Fe->follow_set_.begin();
     FOLLOW_SETS_ITER_type fsie = Fe->follow_set_.end();
     for(;fsi != fsie;){// those Tes
       T_in_stbl* t = *fsi;
       t_name[0] = (char)0;
       XLATE_SYMBOLS_FOR_cweave(t->t_def()->t_name()->c_str(),t_name);
       sprintf(big_buf_,w_follset_t,t_name);
       ow_index_file_ << big_buf_;
       ++fsi;
       if(fsi != fsie){
         ow_index_file_ <<"," << endl;
       }else{
         ow_index_file_ <<"." << endl;
       }
     }
     ow_index_file_ << endl;// end it with blank line
   }

/@
@*3 |prt_follow_set_creators|.
@/
   void Cprt_xrefs_docs::prt_follow_set_creators(follow_element* Fe){
    char rule_name[Max_cweb_item_size];
    KCHARP w_follset_start_str = 
        "\\halign{\n"
        "\\span\\FollSettemplate\n"
        "\\FollSettitle";   
     KCHARP w_follset_stateno_rule = 
        "{%s\\rulenameno{%i}}&\n" // rule+rule no
	"{"; // start of the contributors 
 
     KCHARP w_follset_creators =  
	    "\\FollSetcreators{%i}{%i}{%i}"; 
			     
     sprintf(big_buf_,w_follset_start_str,"");
     ow_index_file_ << big_buf_ << endl;
     rule_def* rd = (rule_def*)AST::content(*Fe->rule_def_t_);
     rule_name[0] = (char)0;
     XLATE_SYMBOLS_FOR_cweave(rd->rule_name()->c_str(),rule_name);
     sprintf(big_buf_,w_follset_stateno_rule,rule_name,rd->rule_no());
     ow_index_file_ << big_buf_ << endl;
     SR_ELEMENTS_type::iterator sri = Fe->sr_elements_.begin();
     SR_ELEMENTS_type::iterator srie = Fe->sr_elements_.end();
     for(;sri != srie;++sri){// follow set contributors
      AST* et = *sri;// eos
      AST* pvrt = et->pr_;
      refered_rule* rr = (refered_rule*)AST::content(*pvrt);
      T_subrule_def* srd = rr->its_subrule_def(); 
      rule_def* sr_d = srd->its_rule_def();
      sprintf(big_buf_
	    ,w_follset_creators
			,sr_d->rule_no()
			,srd->subrule_no_of_rule()
			,rr->element_pos());
						
      ow_index_file_ << big_buf_ << endl;
     }
   }
/@
@*3 |prt_follow_set_merges|.
@/
   void Cprt_xrefs_docs::prt_follow_set_merges(follow_element* Fe){
     KCHARP w_overflow_close_and_new_blank_rule = 
        "}\\cr\n"
        "{}&\n" // blank sule name
        "{%s"; // start of new meging list
     KCHARP w_follset_merges = 
        "\\FollSetmerges{%i}"; // state where other follow set rule lies 
     MERGES_ITER_type mi = Fe->merges_.begin();
     MERGES_ITER_type mie = Fe->merges_.end();
     int overflow_limit(10);
     int merge_cnt(0);
     for(;mi != mie;++mi){// transitions
       state* s = *mi;
       ++merge_cnt;
       if(merge_cnt > overflow_limit){
         sprintf(big_buf_,w_overflow_close_and_new_blank_rule," ");
         ow_index_file_ << big_buf_ << endl;
         merge_cnt = 1;
       }
       sprintf(big_buf_,w_follset_merges,s->state_no_);
      ow_index_file_ << big_buf_ << endl;
     }
   }
/@
@*3 |prt_follow_set_transitions|.
@/
   void Cprt_xrefs_docs::prt_follow_set_transitions(follow_element* Fe){
     KCHARP w_follset_transitions = 
        "\\FollSettransition{%i}{%i}"; // rt bnded 
     TRANSITIONS_ITER_type ti = Fe->transitions_.begin();
     TRANSITIONS_ITER_type tie = Fe->transitions_.end();
     for(;ti != tie;++ti){// transitions
       follow_element* tfe = *ti;
       rule_def* rd = (rule_def*)AST::content(*tfe->rule_def_t_);
       sprintf(big_buf_
	    ,w_follset_transitions
	    ,tfe->its_state_->state_no_
	    ,rd->rule_no());
       ow_index_file_ << big_buf_ << endl;
      }
     KCHARP w_follset_end_str = "}%s\\cr";      
     sprintf(big_buf_,w_follset_end_str," ");
     ow_index_file_ << big_buf_ << endl;
     KCHARP w_follset_end_rule = "}%s";      
     sprintf(big_buf_,w_follset_end_rule," ");
     ow_index_file_ << big_buf_ << endl;
   }
/@
@*3 |prt_state_s_follow_set_rules|.
@/
   void Cprt_xrefs_docs::prt_state_s_follow_set_rules(state* Cur_state){
    KCHARP w_follset_stateno = // stateno	
        "\\FollSetstateno{%i}";
    S_FOLLOW_SETS_ITER_type fsi =  Cur_state->state_s_follow_set_map_.begin();
    S_FOLLOW_SETS_ITER_type fsie =  Cur_state->state_s_follow_set_map_.end();
    if(fsi == fsie) return;// nada follow set info in this state
    sprintf(big_buf_,w_follset_stateno,Cur_state->state_no_);
    ow_index_file_ << big_buf_ << endl;
    for(;fsi != fsie;++fsi){// state's follow set info
     follow_element* fe = (*fsi).second;
     prt_follow_set_creators(fe);
     prt_follow_set_merges(fe);
     prt_follow_set_transitions(fe);
     prt_follow_set_local_yield(fe);
    }
   }

/@
@*3 |prt_states_follow_set|.
@/
   void Cprt_xrefs_docs::prt_states_follow_set(){
    KCHARP w_states_follow_sets =	
    "@** Lr1 State's Follow sets and reducing lookahead sets.\\fbreak\n"
    "\\FollSetnotesintro\n"
    "\\fbreak";
    ow_index_file_ << w_states_follow_sets << std::endl;
    STATES_ITER_type si = LR1_STATES.begin();
    STATES_ITER_type sie = LR1_STATES.end();
    for(;si!=sie;++si){// walk the states
      state* cur_state = *si;
      prt_state_s_follow_set_rules(cur_state);
    }
  }
/@
@*3 |prt_common_follow_set_la|.
@/
  void Cprt_xrefs_docs::prt_common_follow_set_la(){
    KCHARP w_common_follow_sets =	
    "@*1 Common Follow sets.\\fbreak\n";
    ow_index_file_ << w_common_follow_sets << std::endl;
    KCHARP w_common_follow_set =	
      "@*2 LA set: %i.\\fbreak\n"
      "\\item{}\n"
      "\\raggedright";
    KCHARP la_set_entry_literal = "%s"; 
    char t_name[Max_cweb_item_size];

    COMMON_LA_SETS_ITER_type i = COMMON_LA_SETS.begin();  
    COMMON_LA_SETS_ITER_type ie = COMMON_LA_SETS.end();
    for(int idx=0;i!=ie;++i,++idx){
     LA_SET_type* la_set = *i;
     sprintf(big_buf_,w_common_follow_set,idx+1);
     ow_index_file_ << big_buf_ << endl;
     LA_SET_ITER_type j = la_set->begin();// list out the T literals 
     LA_SET_ITER_type je = la_set->end(); 
     for(;j!=je;){
	T_in_stbl* tsym = *j;   
        t_name[0] = (char)0;
        XLATE_SYMBOLS_FOR_cweave(tsym->t_def()->t_name()->c_str(),t_name);
 	sprintf(big_buf_,la_set_entry_literal,t_name);
        ow_index_file_ << big_buf_;
        ++j;
        if(j!=je){
         ow_index_file_ << "," << endl;
        }else{
         ow_index_file_ << "." << endl;
        }	
     }
     ow_index_file_ << endl; // close off the items
    }  
  }
  ***
  op
        prt_sr_elems_filter_.insert(T_Enum::T_T_subrule_def_);
        prt_sr_elems_filter_.insert(T_Enum::T_refered_T_);
        prt_sr_elems_filter_.insert(T_Enum::T_T_eosubrule_);
        prt_sr_elems_filter_.insert(T_Enum::T_refered_rule_);
        prt_sr_elems_filter_.insert(T_Enum::T_T_called_thread_eosubrule_);
        prt_sr_elems_filter_.insert(T_Enum::T_T_null_call_thread_eosubrule_);

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]= ' ';

rule_def_= 0;
subrule_def_= 0;
rule_no_= 0;
subrule_no_= 0;
elem_no_= 0;
no_of_rules_= 0;
no_of_subrules_= 0;
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;
}
  ***
}
,fsm-version "1.0",fsm-date "29 Nov. 2005",fsm-debug "false"
,fsm-comments 
"Output xref doc --- \n``first set'' per rule, and referenced symbols.")
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Rprt_xrefs_docs  
(){
  -> Rrules eog {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;

	int rule_no = 1;

    KCHARP w_doc_index =	
        "\\input \"supp-pdf\"\n"
        "\\input \"/usr/local/yacco2/diagrams/o2mac.tex\"\n"
        "\\IDXdoctitle{%s}{%s}";
       char xlate_file[Max_cweb_item_size];
       XLATE_SYMBOLS_FOR_cweave(fsm->w_index_filename_.c_str(),xlate_file);
       sprintf(fsm->big_buf_
 		,w_doc_index
                ,xlate_file
                ,xlate_file
 		);	
    fsm->ow_index_file_ << fsm->big_buf_ << std::endl;
    

    KCHARP w_used_xref_index =	
    "@** Grammar symbols: Used cross reference.\\fbreak\n"
	"Reference of each grammar's symbol used within each rule's productions. The index\n"
	"uses the tripple: rule name, its subrule no, and the symbol's position\n"
	" within the symbol string.";
    fsm->ow_index_file_ << w_used_xref_index << std::endl;
 
      char  key[Max_cweb_item_size];
      char  xlate_key_sym[Max_cweb_item_size];
      char xref_key[Max_cweb_item_size];
      char xlate_sym[Max_cweb_item_size];
      char xlated_rule[Max_cweb_item_size];
      std::map<std::string, std::list<std::string> >::iterator i = 
        fsm->xref_of_used_symbols_.begin();
      std::map<std::string, std::list<std::string> >::iterator ie = 
        fsm->xref_of_used_symbols_.end();
    for(;i != ie;++i){
       strcpy(key,i->first.c_str());
       XLATE_SYMBOLS_FOR_cweave((const char*)key,xlate_key_sym);
	   fsm->ow_index_file_ << "@*2 " << xlate_key_sym << ":.\\fbreak" << endl;       
      std::list<std::string>& xxx = i->second;
      std::list<std::string>::iterator k = xxx.begin();
      std::list<std::string>::iterator ke = xxx.end();
      for(;k != ke;++k){
       strcpy(xref_key,k->c_str());
       XLATE_SYMBOLS_FOR_cweave((const char*)xref_key,xlate_sym);
       fsm->ow_index_file_ << xlate_sym << "\\ \\ " << endl;       
      }
       fsm->ow_index_file_ << "\\fbreak" << endl;       
    }

    KCHARP w_fs_index =	
    "@** Grammar Rules's First Sets.\\fbreak\n";
    fsm->ow_index_file_ << w_fs_index << std::endl;
 
    std::list<rule_def*>::iterator j = fsm->rules_for_fs_prt_.begin();
    std::list<rule_def*>::iterator je = fsm->rules_for_fs_prt_.end();
    for(;j != je;++j){
      PRT_RULE_S_FIRST_SET(fsm->ow_index_file_,*j);
    };
    KCHARP w_lr_state_network =	
    "@*2 LR State Network.\\fbreak\n"
    "\\LRstatenetwork\n";
    KCHARP w_xref_rule_rank_to_literal =	
            "@.R$_{%i}$ --- %s@>\n";
    fsm->ow_index_file_ << w_lr_state_network << std::endl;
    fsm->determine_closure_derived_states();

    std::map <int , std::list<state_element*> >::iterator xi;
    std::map <int , std::list<state_element*> >::iterator xie;

    xi= fsm->productions_derived_states_list_.begin();
    xie = fsm->productions_derived_states_list_.end();
    rule_def* ord(0);
    rule_def* rd(0);

  for(;xi!=xie;++xi){// walk all the derived productions list
      std::list<state_element*>& selist = xi->second;
      std::list<state_element*>::iterator f1st_el = selist.begin();
      state_element* se = (state_element*)*f1st_el;
      T_subrule_def* srd = se->subrule_def_;
      rd = srd->its_rule_def();
      if(ord != rd){
        ord = rd;
        XLATE_SYMBOLS_FOR_cweave(ord->rule_name()->c_str(),xlated_rule);
          KCHARP w_rule_name =	
           "@*3 %s.\\fbreak";
	   sprintf(fsm->big_buf_
 		,w_rule_name
		,xlated_rule
 		);	
           fsm->ow_index_file_ << fsm->big_buf_ << std::endl;
 	   sprintf(fsm->big_buf_
 		,w_xref_rule_rank_to_literal
		,rd->rule_no()
		,xlated_rule
 		);	
           fsm->ow_index_file_ << fsm->big_buf_ << std::endl;
      }
      KCHARP w_subrule =	
           "\\Subrulestartsymstrindent{%i} ";
      sprintf(fsm->big_buf_
 		,w_subrule
		,srd->subrule_no_of_rule()
 		);	
	  fsm->ow_index_file_ << fsm->big_buf_;
// print its rhs elements
           AST* sr_t = srd->subrule_s_tree();

    tok_can_ast_functor sr_elems_walk_functr;
    ast_prefix_1forest prt_sr_elems_walk(*sr_t
        ,&sr_elems_walk_functr,&fsm->prt_sr_elems_filter_,ACCEPT_FILTER);
    tok_can<AST*> prt_sr_elems_can(prt_sr_elems_walk);
	using namespace NS_prt_sr_elements;
	Cprt_sr_elements prt_sr_elements_fsm;
          prt_sr_elements_fsm.ow_index_file_ = &fsm->ow_index_file_;
	Parser prt_sr_elements(prt_sr_elements_fsm,&prt_sr_elems_can,0);
	prt_sr_elements.parse();

	list<state_element*>& dlist = xi->second;
	list<state_element*>::iterator yi = dlist.begin();
	list<state_element*>::iterator yie = dlist.end();
	KCHARP w_subrule_derived_states =	
           "\\Subrulederivedstatesindent ";
	KCHARP w_merged =	"{\\Mergedstate{%i}}";
        std::set<int> chk_merge;
        chk_merge.clear();
	for(;yi!=yie;++yi){// derive state list per closured production
           fsm->ow_index_file_ << w_subrule_derived_states << endl;
	   state_element* se = *yi;
	   state_element* dse = se;
	   for(;dse!=0;dse = dse->next_state_element_){// walk the derived plank
            fsm->ow_index_file_ << dse->self_state_->state_no_;
	    if(dse->next_state_element_ != 0){
             std::set<int>::iterator si = 
                chk_merge.find(dse->next_state_element_->self_state_->state_no_);
	     if(si != chk_merge.end()){
               sprintf(fsm->big_buf_
			,w_merged
			,dse->goto_state_->state_no_
		   );	
	       fsm->ow_index_file_ << fsm->big_buf_ << endl;
	       break;
	     }
	    } 
            chk_merge.insert(dse->self_state_->state_no_);
	    fsm->ow_index_file_ << "\\ \\ " << endl;
	   }
	}
  }

    KCHARP w_list_of_reduced_states =	
    "@*2 List of reducing states.\\fbreak\n"
    "\\Listofreducingstates\n"
    "\\fbreak\n";
    fsm->ow_index_file_ << w_list_of_reduced_states << std::endl;
    fsm->ow_index_file_ << "\\Reducedstatelist" << std::endl;
    std::vector <state* >::iterator ri = fsm->reducing_states_list_.begin();
    std::vector <state* >::iterator rie = fsm->reducing_states_list_.end();
    for(;ri != rie;++ri){
        state* s = *ri;
        fsm->ow_index_file_ << '{' << s->state_no_; 
        switch (s->state_type_){
           case 0:{//shift only
             break;
           }
           case 1:{
             fsm->ow_index_file_ << "\\Reduceonly";
             break;
           }
           case 2:{
             fsm->ow_index_file_ << "\\ShiftReduce";
             break;
           }
           case 3:{
             fsm->ow_index_file_ << "\\MultipleReduces";
             break;
           }
           case 4:{
             fsm->ow_index_file_ << "\\ShiftandMultipleReduces";
             break;
           }
        }
        fsm->ow_index_file_ << "\\ \\ }" << std::endl;
    }
    fsm->prt_states_follow_set();
    fsm->prt_common_follow_set_la();
    fsm->ow_index_file_ << "@** Index." << endl;

fsm->ow_index_file_.close();
  ***
  }
}

Rrules  (){
  -> Rrule
  -> Rrules Rrule
}

Rrule  (){
  -> Rrule_def Rsubrules
}

Rrule_def  
(){
  -> "rule-def" {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    fsm->rule_def_ = sf->p1__;
    fsm->rules_for_fs_prt_.push_back(fsm->rule_def_);
    ++fsm->rule_no_;
    fsm->subrule_no_ = 0;
  ***
  }
}

Rsubrules  (){
  -> Rsubrule
  -> Rsubrules Rsubrule
}

Rsubrule  (){
  -> Rsubrule_def Relements
}

Rsubrule_def  (){
  -> "subrule-def" {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    ++fsm->subrule_no_;
    fsm->elem_no_ = 0;
    fsm->subrule_def_ = sf->p1__;
  ***
  }
}

Relements  (){
  -> Relement
  -> Relements Relement
}

Relement
/@
Use of \invisibleshift to make grammar lr(1).
@/ 
(){
  -> "refered-T" |.| {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    ++fsm->elem_no_;
	string xref_entry;
	const char* xref_pattern = "%s %i.%i";
	sprintf(fsm->big_buf_,xref_pattern
        ,fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	xref_entry += fsm->big_buf_;
	string xref_key(sf->p1__->its_t_def()->t_name()->c_str());
	fsm->add_symbol_to_xref_map(xref_key,xref_entry);		
  ***
  }
  -> "refered-rule" {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    ++fsm->elem_no_;
	string xref_entry;
	const char* xref_pattern = "%s %i.%i";
	sprintf(fsm->big_buf_,xref_pattern,
        fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	xref_entry += fsm->big_buf_;
	string xref_key(sf->p1__->its_rule_def()->rule_name()->c_str());
	fsm->add_symbol_to_xref_map(xref_key,xref_entry);	
  ***
  }
  -> "eosubrule" {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    ++fsm->elem_no_;
    if(fsm->elem_no_ == 1){// epsilon
	  string xref_entry;
	  const char* xref_pattern = "%s %i.%i";
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_entry += fsm->big_buf_;
	  string xref_key("\\emptyrule");
	  fsm->add_symbol_to_xref_map(xref_key,xref_entry);	
	}
  ***
  }
  -> "refered-T" "refered-T" "called thread eosubrule" {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    ++fsm->elem_no_;    
	  string xref_entry;
	  const char* xref_pattern = "%s %i.%i";
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_entry += fsm->big_buf_;
	  string xref_key;
      if(sf->p1__->its_t_def()->enum_id() == T_Enum::T_LR1_parallel_operator_){    
	     xref_key += "|||";
           }else{
	     xref_key += "|t|";
           }
	  fsm->add_symbol_to_xref_map(xref_key,xref_entry);	
    ++fsm->elem_no_;
	  string xref_rtned_entry;
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_rtned_entry += fsm->big_buf_;
	  string xref_rtned_key(sf->p2__->its_t_def()->t_name()->c_str());
	  fsm->add_symbol_to_xref_map(xref_rtned_key,xref_rtned_entry);	
    ++fsm->elem_no_;
	  string xref_thd_entry;
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_thd_entry += fsm->big_buf_;	  
	  string xref_thd_key;
	    xref_thd_key += sf->p3__->ns()->identifier()->c_str();
	    xref_thd_key += "::";
	  xref_thd_key += sf->p3__->called_thread_name()->identifier()->c_str();	  
	  fsm->add_symbol_to_xref_map(xref_thd_key,xref_thd_entry);	
  ***
  }
  -> "refered-T" "refered-T" "null call thread eosubrule" {
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    ++fsm->elem_no_;    
	  string xref_entry;
	  const char* xref_pattern = "%s %i.%i";
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_entry += fsm->big_buf_;
	  string xref_key;
      if(sf->p1__->its_t_def()->enum_id() == T_Enum::T_LR1_parallel_operator_){    
	     xref_key += "|||";
           }else{
	     xref_key += "|t|";
           }
	  fsm->add_symbol_to_xref_map(xref_key,xref_entry);
	
    ++fsm->elem_no_;
	  string xref_rtned_key(sf->p2__->its_t_def()->t_name()->c_str());
	  string xref_rtned_entry;
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_rtned_entry += fsm->big_buf_;
	  fsm->add_symbol_to_xref_map(xref_rtned_key,xref_rtned_entry);	

    ++fsm->elem_no_;
	  string xref_thd_entry;
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_thd_entry += fsm->big_buf_;	  
	  string xref_thd_key("NULL thread");
	  fsm->add_symbol_to_xref_map(xref_thd_key,xref_thd_entry);	
  ***
  }
  -> "refered-T" "refered-T" |.|{
  op
    Cprt_xrefs_docs* fsm = (Cprt_xrefs_docs*)rule_info__.parser__->fsm_tbl__;
    ++fsm->elem_no_;    
	  string xref_entry;
	  const char* xref_pattern = "%s %i.%i";
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_entry += fsm->big_buf_;
	  string xref_key(sf->p1__->its_t_def()->t_name()->c_str());
	  fsm->add_symbol_to_xref_map(xref_key,xref_entry);	
    ++fsm->elem_no_;
	  string xref_2_entry;
	  sprintf(fsm->big_buf_,xref_pattern,
          fsm->rule_def_->rule_name()->c_str(),fsm->subrule_no_,fsm->elem_no_);
	  xref_2_entry += fsm->big_buf_;
	  string xref_2_key(sf->p2__->its_t_def()->t_name()->c_str());
	  fsm->add_symbol_to_xref_map(xref_2_key,xref_2_entry);	
  ***
  }
}

}// end of rules
