/*
 File: epsilon_rules.cpp
 Date and Time: Fri Jan 30 18:55:10 2015 
*/
#include "epsilon_rules.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_epsilon_rules;// grammar's ns
// first set terminals
fsm_rules_reuse_table_type::fsm_rules_reuse_table_type(){
 no_rules_entries_ = 7;
 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();
}
  Cepsilon_rules::
  Cepsilon_rules()
    :yacco2::CAbs_fsm
      ("epsilon_rules.lex"
      ,"1.0"
      ,"26 sept. 2005"
      ,false
      ,"Determine whether rules are epsilon, derive T, or are pathological."
      ,"Fri Jan 30 18:55:10 2015 "
      ,S1_Cepsilon_rules){
    
  }
 
Cepsilon_rules::~Cepsilon_rules(){

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

  bool Cepsilon_rules::failed(){
      return false;
  }
  void Cepsilon_rules::op(){
    rule_def_ = 0;
	subrule_def_ = 0;
	elem_t_ = 0;
    ip_can_ = (tok_can< AST* >*)parser__->token_supplier__;
  
}
int Cepsilon_rules::rhs_to_rules_mapping_[10] = {
 -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
}; 
       
  AST* Cepsilon_rules::advance_element(AST* Elemt){
	AST* nxt_t = AST::brother(*Elemt);// next element
    for(;;){// bypass thread expression: go to jail ... eosubrule
  using namespace NS_yacco2_T_enum;
	 CAbs_lr1_sym* sym = AST::content(*nxt_t);
	 switch(sym->enumerated_id__){
	   case T_Enum::T_T_identifier_: break;  
       case T_Enum::T_T_2colon_:  break; 
       case T_Enum::T_T_NULL_: break;
       case T_Enum::T_T_cweb_marker_: break; 
       case T_Enum::T_T_cweb_comment_: break; 
       default: return nxt_t;
      } 
	  nxt_t = AST::brother(*nxt_t);// skip thread expr: next element
     }  
  }
  void Cepsilon_rules::deal_with_derives_list(){
  // force cweave to 
  using namespace NS_yacco2_T_enum;
         bool has_list_chged(false);
         std::list<elem_list_type >::iterator i; 
         Read_list:;
            i = derives_list_.begin();
	if(i == derives_list_.end()) return;
	for(;i != derives_list_.end();){ // force cweave
	  elem_list_type& el = *i;
	  CAbs_lr1_sym* rteos = AST::content(*el.elem_t_);// force cweave
	  switch(rteos->enumerated_id__){// force cweave
		case T_Enum::T_refered_rule_:{
		  refered_rule* rr = (refered_rule*)rteos;
		  rule_in_stbl* rstbl = rr->Rule_in_stbl();
		      using namespace yacco2_stbl;
			T_sym_tbl_report_card report_card;
			get_sym_entry_by_sub(report_card,rstbl->stbl_idx());
			if(report_card.status_ == T_sym_tbl_report_card::failure){
			 report_card.err_entry_->set_rc(*rr,__FILE__,__LINE__);						
			 parser__->add_token_to_error_queue(*report_card.err_entry_);
			 return;// caused by problem with sym. tbl
			}
			if(report_card.tbl_entry_->defined_ == false){
			 CAbs_lr1_sym* sym = new Err_used_rule_but_undefined;
			 sym->set_rc(*rr,__FILE__,__LINE__);
			 parser__->add_token_to_error_queue(*sym);
                         // keep pouring them into the error queue
			 has_list_chged = true;// go to next element
			 el.elem_t_ = advance_element(el.elem_t_);
			 ++i;// next sr in derive list
			 break;
		        }			
		        rule_def* r = rr->Rule_in_stbl()->r_def();
		        if(r->epsilon() == YES){
			 has_list_chged = true;
			 el.elem_t_ = advance_element(el.elem_t_);
			 ++i;// next sr in derive list
			 if(el.gen_epsilon_ != EPSILON_NO){
			  el.gen_epsilon_ = EPSILON_MAYBE;
			 }
			 break;
		        }
		  if(r->derive_t() == YES){
			has_list_chged = true;
			el.elem_t_ = advance_element(el.elem_t_);
		    el.gen_epsilon_ = EPSILON_NO;
			++i;// next sr in derive list
			break;
		  }
		  ++i;// indeterminate spot: next pass might free it up so next sr
		  break; 
		}
		case T_Enum::T_T_eosubrule_:{
		  if(el.gen_epsilon_!= EPSILON_NO){
                  el.rule_->epsilon(YES);
                  el.subrule_->epsilon(YES);
                }else{
                  el.subrule_->epsilon(NO);
                  el.rule_->derive_t(YES);
                }
		  has_list_chged = true;
		  i = derives_list_.erase(i);// finished with sr
		  break;
		}
		case T_Enum::T_T_null_call_thread_eosubrule_:{
        	  el.gen_epsilon_ = EPSILON_NO;
                el.subrule_->epsilon(NO);
                  el.rule_->derive_t(YES);
		  has_list_chged = true;
		  i = derives_list_.erase(i);// finished with sr
		  break;
		}
		case T_Enum::T_T_called_thread_eosubrule_:{
		  el.gen_epsilon_ = EPSILON_NO;
                  el.subrule_->epsilon(NO);
                  el.rule_->derive_t(YES);
		  has_list_chged = true;
		  i = derives_list_.erase(i);// finished with sr
		  break;
		}
		case T_Enum::T_refered_T_:{
		  el.gen_epsilon_ = EPSILON_NO;
                  el.subrule_->epsilon(NO);
		  has_list_chged = true;
		  el.elem_t_ = advance_element(el.elem_t_);
		  ++i;// next sr in derive list
		  refered_T* rt = (refered_T*)rteos;
		  break;
		}
		default:{ // lr k 
		  el.gen_epsilon_ = EPSILON_NO;
                  el.subrule_->epsilon(NO);
		  has_list_chged = true;
		  el.elem_t_ = advance_element(el.elem_t_);
		  ++i;// next sr in derive list
		  break;
		}
	  }
	       
	}
	if(derives_list_.empty() == true) return;// kosher grammar
	if(has_list_chged == true){// still o/s but going forward
	  has_list_chged = false;
          goto Read_list;		 
	}
}
	   void Cepsilon_rules::deal_with_undecided_derives_list(){
	     // chk if undefined rules were found: yes out damn spot
	     if(parser__->error_queue()->empty() != true) return;
	   	 // errors: pathological grammar
         std::list<elem_list_type >::iterator 
         i = derives_list_.begin();
		if(i == derives_list_.end()) return;
		for(;i != derives_list_.end();++i){
			  elem_list_type& el = *i;
			  CAbs_lr1_sym* elem = AST::content(*el.elem_t_);
			  CAbs_lr1_sym* sym = new ERR_sick_grammar;
			  sym->set_rc(*elem,__FILE__,__LINE__);
			  parser__->add_token_to_error_queue(*sym);
		 }
	   }
	   
  
Repsilon_rules::Repsilon_rules(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Repsilon_rules",0,Cepsilon_rules::R_Repsilon_rules_,P,false,false){
}

void Repsilon_rules::sr1(){
  
    Cepsilon_rules* fsm = (Cepsilon_rules*)rule_info__.parser__->fsm_tbl__;
	fsm->deal_with_derives_list();
	if(fsm->derives_list_.empty() != true){
	  fsm->deal_with_undecided_derives_list();
	}
  
}

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

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

Rrule_def::Rrule_def(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rrule_def",0,Cepsilon_rules::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);
  
    Cepsilon_rules* fsm = (Cepsilon_rules*)rule_info__.parser__->fsm_tbl__;
    fsm->rule_def_ = sf->p1__;
  
}

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

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

Rsubrule_def::Rsubrule_def(yacco2::Parser* P)
 :CAbs_lr1_sym
  ("Rsubrule_def",0,Cepsilon_rules::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);
  
    Cepsilon_rules* fsm = (Cepsilon_rules*)rule_info__.parser__->fsm_tbl__;
    fsm->subrule_def_ = sf->p1__;
    AST* sr_t = fsm->subrule_def_->subrule_s_tree();
    AST* et = AST::get_spec_child(*sr_t,1);
   fsm->derives_list_.push_back
	(elem_list_type(fsm->rule_def_,fsm->subrule_def_,et));
  
}

