/*
 File: rules_use_cnt.cpp
 Date and Time: Fri Jan 30 18:55:23 2015 
*/
#include "rules_use_cnt.h"
using namespace NS_yacco2_T_enum;// enumerate
using namespace NS_yacco2_err_symbols;// error symbols
using namespace NS_yacco2_k_symbols;// lrk 
using namespace NS_yacco2_terminals;// terminals
using namespace NS_yacco2_characters;// rc 
using namespace yacco2;// yacco2 library
using namespace NS_rules_use_cnt;// grammar's ns
// first set terminals
fsm_rules_reuse_table_type::fsm_rules_reuse_table_type(){
 no_rules_entries_ = 9;
 per_rule_s_table_[0] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[1] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[2] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[3] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[4] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[5] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[6] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[7] =  new Per_rule_s_reuse_table();
 per_rule_s_table_[8] =  new Per_rule_s_reuse_table();
}
  Crules_use_cnt::
  Crules_use_cnt()
    :yacco2::CAbs_fsm
      ("rules_use_cnt.lex"
      ,"1.0"
      ,"6 July 2007"
      ,false
      ,"Optimization: Count ``rules used'' \n to lower new / delete rule cycles while parsing."
      ,"Fri Jan 30 18:55:23 2015 "
      ,S1_Crules_use_cnt){
    
  }
 
Crules_use_cnt::~Crules_use_cnt(){

  for(int x = 0;x < 9;++x){
   ///delete fsm_rules_reuse_table.per_rule_s_table_[x];
  }
} 

  bool Crules_use_cnt::failed(){
      return false;
  }
  void Crules_use_cnt::op(){
    tok_can<AST*>* can = (tok_can<AST*>*)parser()->token_supplier();
    AST* start_rule_t = can->ast(0);
    AST* t = start_rule_t;
    for(;t != 0;t=AST::get_younger_sibling(*t,1)){
	rule_def* rd = (rule_def*)AST::content(*t);
        AST* use_skeleton_t = bld_rule_s_use_skeleton(t);
	if(use_skeleton_t != 0) rd->rule_use_skeleton(use_skeleton_t);
        if(t != start_rule_t) rules_list_for_use_cnt_.push_back(rd);
    }
    rule_def_ = 0;
    subrule_def_ = 0;
  
}
int Crules_use_cnt::rhs_to_rules_mapping_[14] = {
 -1
 ,0 // subrule 1 for rule 1
 ,1 // subrule 2 for rule 2
 ,1 // subrule 3 for rule 2
 ,2 // subrule 4 for rule 3
 ,3 // subrule 5 for rule 4
 ,4 // subrule 6 for rule 5
 ,4 // subrule 7 for rule 5
 ,5 // subrule 8 for rule 6
 ,6 // subrule 9 for rule 7
 ,7 // subrule 10 for rule 8
 ,7 // subrule 11 for rule 8
 ,8 // subrule 12 for rule 9
 ,8 // subrule 13 for rule 9
}; 
       
   void Crules_use_cnt::mark_recursion_rule_use
	(NS_yacco2_terminals::refered_rule* Refered_rule){
	    using namespace NS_yacco2_terminals;
	    rule_in_stbl* rule_in_tbl = Refered_rule->Rule_in_stbl();
		rule_def* rd = rule_in_tbl->r_def();
		if(rd == rule_def_){
		  rd->recursive(YES);
		  rd->lhs_use_cnt(1);
		}
	}

        AST* Crules_use_cnt::bld_rule_s_use_skeleton(AST* Rule_t){
		using namespace NS_yacco2_T_enum;
		set<int> rules_use_cnt_filter;
		rules_use_cnt_filter.insert(T_Enum::T_T_subrule_def_);  
		rules_use_cnt_filter.insert(T_Enum::T_rule_def_);
		rules_use_cnt_filter.insert(T_Enum::T_refered_rule_);

		tok_can_ast_functor rules_use_walk_functr;
		ast_postfix rules_use_walk(*Rule_t,&rules_use_walk_functr
		,&rules_use_cnt_filter,ACCEPT_FILTER);
		tok_can<AST*> rules_use_can(rules_use_walk);
		int x(0);
		CAbs_lr1_sym* sym = rules_use_can[x];
		rule_def* rd(0);
		AST* lk_rr_t(0);
		AST* rr_t(0);
		AST* sr_t(0);
		AST* lk_sr_t(0);
		AST* r_t(0);
		for(;sym->enumerated_id() != LR1_Eog;++x,sym=rules_use_can[x]){
		  switch(sym->enumerated_id()){
		    case T_Enum::T_rule_def_:{
			if(sr_t == 0) return 0;// no rhs with refered rules
			r_t = new AST(*sym);
			AST::join_pts(*r_t,*sr_t);
			return r_t;
		    }
		    case T_Enum::T_T_subrule_def_:{
			if(rr_t == 0) break;// no refered rules
			AST* srt = new AST(*sym);
			AST::join_pts(*srt,*rr_t);
			lk_rr_t = 0;
			rr_t = 0;
			if(sr_t == 0){
			  sr_t = srt;
			  lk_sr_t = srt;
			}else{
			  AST::join_sts(*lk_sr_t,*srt);
			  lk_sr_t = srt;
			}
			break;
		    }
		    case T_Enum::T_refered_rule_:{
			AST* rrt = new AST(*sym);
			if(rr_t == 0){
			  rr_t = rrt;
			  lk_rr_t = rrt;
			}else{
			  AST::join_sts(*lk_rr_t,*rrt);
			  lk_rr_t = rrt;
			}
			break;
		    }
		  }//switch
		}//for
	    return 0;
	}
  
Rrules_use_cnt::Rrules_use_cnt(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rrules_use_cnt",0,Crules_use_cnt::R_Rrules_use_cnt_,P,false,false){
}

Rrules::Rrules(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rrules",0,Crules_use_cnt::R_Rrules_,P,false,false){
}

Rrule::Rrule(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rrule",0,Crules_use_cnt::R_Rrule_,P,false,false){
}

Rrule_def::Rrule_def(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rrule_def",0,Crules_use_cnt::R_Rrule_def_,P,false,false){
}

void Rrule_def::sr1(){
  struct SF{
   rule_def* p1__;
   State* s1__;
   bool abort1__;
   Rule_s_reuse_entry* rule_s_reuse_entry1__;
  };
  SF* sf = (SF*)rule_info__.parser__->parse_stack__.sf_by_top(1);
  
    Crules_use_cnt* fsm = (Crules_use_cnt*)rule_info__.parser__->fsm_tbl__;
    fsm->rule_def_ = sf->p1__;
    std::list<NS_yacco2_terminals::rule_def* >::iterator i =  fsm->rules_list_for_use_cnt_.begin();
    std::list<NS_yacco2_terminals::rule_def* >::iterator ie =  fsm->rules_list_for_use_cnt_.end();
    for(;i != ie;++i){
	rule_def* for_rule = *i;
        int use_cnt = MAX_USE_CNT_RxR(for_rule,fsm->rule_def_);
	if(for_rule->rhs_use_cnt() < use_cnt){
          for_rule->rhs_use_cnt(use_cnt);
	}
    }
  
}

Rsubrules::Rsubrules(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rsubrules",0,Crules_use_cnt::R_Rsubrules_,P,false,false){
}

Rsubrule::Rsubrule(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rsubrule",0,Crules_use_cnt::R_Rsubrule_,P,false,false){
}

Rsubrule_def::Rsubrule_def(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rsubrule_def",0,Crules_use_cnt::R_Rsubrule_def_,P,false,false){
}

void Rsubrule_def::sr1(){
  struct SF{
   T_subrule_def* p1__;
   State* s1__;
   bool abort1__;
   Rule_s_reuse_entry* rule_s_reuse_entry1__;
  };
  SF* sf = (SF*)rule_info__.parser__->parse_stack__.sf_by_top(1);
  
    Crules_use_cnt* fsm = (Crules_use_cnt*)rule_info__.parser__->fsm_tbl__;
    fsm->subrule_def_ = sf->p1__;
  
}

Rsubrule_s_used_rules_epi::Rsubrule_s_used_rules_epi(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rsubrule_s_used_rules_epi",0,Crules_use_cnt::R_Rsubrule_s_used_rules_epi_,P,false,false){
}

Rsubrule_s_used_rules::Rsubrule_s_used_rules(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rsubrule_s_used_rules",0,Crules_use_cnt::R_Rsubrule_s_used_rules_,P,false,false){
}

void Rsubrule_s_used_rules::sr1(){
  struct SF{
   refered_rule* p1__;
   State* s1__;
   bool abort1__;
   Rule_s_reuse_entry* rule_s_reuse_entry1__;
  };
  SF* sf = (SF*)rule_info__.parser__->parse_stack__.sf_by_top(1);
  
    Crules_use_cnt* fsm = (Crules_use_cnt*)rule_info__.parser__->fsm_tbl__;
    fsm->mark_recursion_rule_use(sf->p1__);
  
}

void Rsubrule_s_used_rules::sr2(){
  struct SF{
   Rsubrule_s_used_rules* p1__;
   State* s1__;
   bool abort1__;
   Rule_s_reuse_entry* rule_s_reuse_entry1__;
   refered_rule* p2__;
   State* s2__;
   bool abort2__;
   Rule_s_reuse_entry* rule_s_reuse_entry2__;
  };
  SF* sf = (SF*)rule_info__.parser__->parse_stack__.sf_by_top(2);
  
    Crules_use_cnt* fsm = (Crules_use_cnt*)rule_info__.parser__->fsm_tbl__;
    fsm->mark_recursion_rule_use(sf->p2__);
  
}

