/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:    fsc_file.lex
dates:   11 mar. 2005	
Purpose: grammar's fsc file syntax
		 puts grammar's attributes into yacco2's symbol table 
		 and into a global dictionary of threads for consolidated processing.
Note: use of |?| to trap errors: even overruns. 
Possible Errors:
Err_no_of_native_Ts_in_list_not_equal LR1_err_no_of_threads_in_list_not_equal
Err_epsilon_pass_thru LR1_err_epsilon_pass_thru_no_Ts
Err_already_defined_in_fsc_file
Err_transitive_kw_not_present LR1_err_transitive_value_bad
symbol table errors

Err_grammar_name_kw_not_present LR1_err_grammar_name_value_not_present
Err_namespace_kw_not_present LR1_err_namespace_value_not_present
Err_threadname_kw_not_present LR1_err_threadname_value_not_present
Err_monolithic_kw_not_present LR1_err_monolithic_value_bad
Err_filename_kw_not_present LR1_err_filename_value_not_present
Err_no_of_T_kw_not_present LR1_err_no_of_T_does_not_match_T_alphabet
Err_no_of_T_value_not_present LR1_err_list_of_terminals_kw_not_present
Err_no_of_terminals_not_present
Err_bad_T_in_list LR1_err_end_list_native_T_kw_not_present
Err_list_of_transitive_threads_kw_not_present
Err_no_of_threads_not_present
Err_no_sym_defs_present LR1_err_end_list_of_transitive_threads_kw_not_present
*/
/@
@i "/usr/local/yacco2/copyright.w"
@** |fsc_file| stand alone Grammar.\fbreak
Parses the ``first set control''  files outputed from each grammar.
This is the fodder of \O2's linker to generate the first sets per thread.
It puts the grammar's attributes into yacco2's symbol table 
and into a global dictionary of threads for consolidation processing.
See \O2{}linker documentation on the real lowdown.\fbreak
\fbreak
\fbreak
Linker's control language.\fbreak
\let\setuplistinghook = \relax
\listing{"/usr/local/yacco2/diagrams+etc/intro4.txt"}
\fbreak
@/
fsm	
(fsm-id "fsc_file.lex",fsm-filename fsc_file,fsm-namespace NS_fsc_file
,fsm-class Cfsc_file{
  user-prefix-declaration
#include "yacco2_stbl.h"
extern std::vector<NS_yacco2_terminals::table_entry*> GRAMMAR_DICTIONARY;
extern std::vector<NS_yacco2_terminals::table_entry*> T_DICTIONARY;
extern std::map<std::string, std::vector<std::string> > USED_THREADS_LIST;
  ***
  user-declaration
    public:
    std::string fully_qualified_th_name_;
    char transitive_;
    char monolithic_;
    NS_yacco2_terminals::T_c_string* grammar_file_name_;
    NS_yacco2_terminals::T_c_string* name_space_name_;
    NS_yacco2_terminals::T_c_string* thread_name_;
    NS_yacco2_terminals::T_c_string* file_name_;
    NS_yacco2_terminals::T_c_string* fsm_comments_;
    NS_yacco2_terminals::T_int_no* no_of_T_;
    std::vector<int> list_of_Ts_;
    NS_yacco2_terminals::T_int_no* no_native_T_;
    std::vector<NS_yacco2_terminals::thread_attributes*> list_of_transitive_threads_;
    std::vector<NS_yacco2_terminals::thread_attributes*> list_of_used_threads_;
    NS_yacco2_terminals::T_int_no* no_threads_;
    NS_yacco2_terminals::T_int_no* used_no_threads_;
    std::vector<std::string>* used_threads_;
  ***
}
,fsm-version	"1.0",fsm-date "11 Mar 2005",fsm-debug "false"
,fsm-comments	"\\Olinker's ``fsc'' control file parser.")
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Rfsc_file  (
lhs{
  op
   Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
   using namespace NS_yacco2_k_symbols;
   int no_T = fsm->no_native_T_->no();
   int sze_T = fsm->list_of_Ts_.size();
	if(sze_T !=no_T){
		CAbs_lr1_sym* sym = new Err_no_of_native_Ts_in_list_not_equal(sze_T);
		sym->set_rc(*fsm->no_native_T_,__FILE__,__LINE__);
		ADD_TOKEN_TO_ERROR_QUEUE(*sym);
		return;
	}
	int no_th = fsm->no_threads_->no();
    int sze_th = fsm->list_of_transitive_threads_.size();
	if(sze_th != no_th){
		CAbs_lr1_sym* sym = new Err_no_of_threads_in_list_not_equal(sze_th);
		sym->set_rc(*fsm->no_threads_,__FILE__,__LINE__);
		ADD_TOKEN_TO_ERROR_QUEUE(*sym);
		return;
	}
   if(fsm->monolithic_ == 'n'){// pass epsilon pass thru: thread grammar only
     if((no_T == 0) && (no_th == 0)){
		    CAbs_lr1_sym* sym = new Err_epsilon_pass_thru;
            sym->set_rc(*fsm->no_native_T_,__FILE__,__LINE__);
            ADD_TOKEN_TO_ERROR_QUEUE(*sym);
            rule_info__.parser__->set_stop_parse(true);
            return;     
     }
     if((no_T == 1) && (no_th == 0)){
       int transience = fsm->list_of_Ts_[0];
       if(transience == 7){// \transienceoperator operator
		    CAbs_lr1_sym* sym = new Err_epsilon_pass_thru_no_Ts;
            sym->set_rc(*fsm->no_native_T_,__FILE__,__LINE__);
            ADD_TOKEN_TO_ERROR_QUEUE(*sym);
            rule_info__.parser__->set_stop_parse(true);
            return;
       }     
     }
   }
      
    using namespace yacco2_stbl;
	T_sym_tbl_report_card report_card;
	find_sym_in_stbl(report_card,*fsm->fully_qualified_th_name_.c_str());
	if(report_card.action_ == T_sym_tbl_report_card::fnd){// crted by another fsc file
	  if(report_card.tbl_entry_->defined_ == true){// probably dup fsc file
		    CAbs_lr1_sym* sym = new Err_already_defined_in_fsc_file;
            sym->set_rc(*fsm->thread_name_,__FILE__,__LINE__);
            ADD_TOKEN_TO_ERROR_QUEUE(*sym);
            rule_info__.parser__->set_stop_parse(true);
            return;
	  }
	  report_card.tbl_entry_->defined_ = true;
	  th_in_stbl* th_in_tbl = (th_in_stbl*)report_card.tbl_entry_->symbol_;
	  thread_attributes* th_entry = th_in_tbl->thread_in_stbl();
	  th_entry->transitive_ = fsm->transitive_;
	  th_entry->grammar_file_name_ = fsm->grammar_file_name_;
	  th_entry->name_space_name_ = fsm->name_space_name_;
	  th_entry->thread_name_ = fsm->thread_name_;
	  th_entry->monolithic_ = fsm->monolithic_;
	  th_entry->file_name_ = fsm->file_name_;
	  th_entry->fsm_comments_ = fsm->fsm_comments_;
	  if(!fsm->list_of_Ts_.empty())
		 copy(fsm->list_of_Ts_.begin()
		        ,fsm->list_of_Ts_.end()
		        ,back_inserter(th_entry->list_of_Ts_));
	  if(!fsm->list_of_transitive_threads_.empty())
		  copy(fsm->list_of_transitive_threads_.begin()
		      ,fsm->list_of_transitive_threads_.end()
		      ,back_inserter(th_entry->list_of_transitive_threads_));
	  return;
	}
	  thread_attributes* th_id = 
		  new thread_attributes(fsm->fully_qualified_th_name_.c_str()
		  ,fsm->transitive_
		  ,fsm->grammar_file_name_
		  ,fsm->name_space_name_
		  ,fsm->thread_name_
		  ,fsm->monolithic_
		  ,fsm->file_name_
		  ,fsm->list_of_Ts_
		  ,fsm->list_of_transitive_threads_
                  ,fsm->fsm_comments_);
	  th_in_stbl* t = new th_in_stbl(th_id);
	  add_sym_to_stbl(report_card
		             ,*fsm->fully_qualified_th_name_.c_str()
		             ,*t
		             ,table_entry::defed
		             ,table_entry::thread);
	  	if(report_card.status_ != T_sym_tbl_report_card::okay){
	  	  t->stbl_idx(report_card.pos_);
          report_card.err_entry_->set_rc(*th_id,__FILE__,__LINE__);
          ADD_TOKEN_TO_ERROR_QUEUE(*report_card.err_entry_);
          rule_info__.parser__->set_stop_parse(true);
          return;
	  }
      GRAMMAR_DICTIONARY.push_back(report_card.tbl_entry_);
      th_id->th_enum_ = GRAMMAR_DICTIONARY.size()-1;

      ADD_TOKEN_TO_PRODUCER_QUEUE(*yacco2::PTR_LR1_eog__);   
      ADD_TOKEN_TO_PRODUCER_QUEUE(*yacco2::PTR_LR1_eog__);  
  ***
  }
){
  -> Rtransitive_phrase
	Rgrammar_name_phrase
	Rnamespace_phrase
	Rthreadname_phrase
	Rmonolithic_phrase
	Rfilename_phrase
	Rno_of_T_phrase
	Rlist_of_native_terminals_phrase
	Rlist_of_transitive_threads_phrase
	Rlist_of_used_threads_phrase
	Rfsm_comments_phrase
	    eog
}

Rtransitive_phrase  (){
  ->  Rtransitive  Rtransitive_value
}
Rtransitive  (){
  -> "transitive"
  ->  |?| { 
    op
      CAbs_lr1_sym* sym = new Err_transitive_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rtransitive_value  (){
  -> identifier {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      T_identifier* k = sf->p1__;
      if(k->identifier()->size() != 1){
        CAbs_lr1_sym* sym = new Err_transitive_value_bad;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        ADD_TOKEN_TO_ERROR_QUEUE(*sym);
        rule_info__.parser__->set_stop_parse(true);
        return;
      }
	  char c = (*k->identifier())[0];
      if(c == 'n' || c == 'y'){
		fsm->transitive_ = c;
		return;      
      }
        CAbs_lr1_sym* sym = new Err_transitive_value_bad;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        ADD_TOKEN_TO_ERROR_QUEUE(*sym);
        rule_info__.parser__->set_stop_parse(true);
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_transitive_value_bad;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rgrammar_name_phrase  (){
  ->  Rgrammar_name  Rgrammar_name_value
}

Rgrammar_name  (){
  -> "grammar-name"
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_grammar_name_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rgrammar_name_value  (){
  -> "c-string" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->grammar_file_name_ = sf->p1__; 
    ***			
    }
  ->  |?| { 
    op
      CAbs_lr1_sym* sym = new Err_grammar_name_value_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rnamespace_phrase  (){
  ->  Rnamespace  Rnamespace_value
}

Rnamespace  (){
  -> "#name-space"
  ->  |?| { 
    op
      CAbs_lr1_sym* sym = new Err_namespace_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rnamespace_value  (){
  -> "c-string" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->name_space_name_ = sf->p1__; 
    ***			
    }
  ->  |?| { 
    op
      CAbs_lr1_sym* sym = new Err_namespace_value_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rthreadname_phrase  (){
  ->  Rthreadname  Rthreadname_value
}

Rthreadname  (){
  -> "thread-name"
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_threadname_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rthreadname_value  (){
  -> "c-string" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->thread_name_ = sf->p1__;
      fsm->fully_qualified_th_name_+= fsm->name_space_name_->c_string()->c_str(); 
      fsm->fully_qualified_th_name_ += "::"; 
      fsm->fully_qualified_th_name_ += fsm->thread_name_->c_string()->c_str();
      T_identifier* th_id = new T_identifier(fsm->fully_qualified_th_name_.c_str()); 
      th_id->set_rc(*fsm->thread_name_,__FILE__,__LINE__);
     string gnm(sf->p1__->c_string()->c_str());
        USED_THREADS_LIST[gnm] = std::vector<string>();
     std::map<std::string, std::vector<std::string> >::iterator i = USED_THREADS_LIST.find(gnm);   
     fsm->used_threads_ = &i->second;
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_threadname_value_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
     ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rmonolithic_phrase  (){
  ->  Rmonolithic  Rmonolithic_value
}

Rmonolithic  (){
  -> "monolithic" 
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_monolithic_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rmonolithic_value  (){
  -> identifier {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      T_identifier* k = sf->p1__;
      if(k->identifier()->size() != 1){
        CAbs_lr1_sym* sym = new Err_monolithic_value_bad;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
       ADD_TOKEN_TO_ERROR_QUEUE(*sym);
        rule_info__.parser__->set_stop_parse(true);
        return;
      }  
	  char c = (*k->identifier())[0];
	  if(c == 'n' || c == 'y'){
			fsm->monolithic_ = c;
			return;      
	  }
      CAbs_lr1_sym* sym = new Err_monolithic_value_bad;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
     ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_monolithic_value_bad;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rfilename_phrase  (){
  ->  Rfilename  Rfilename_value
}

Rfilename  (){
  -> "#file-name"
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_filename_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rfilename_value  (){
  -> "c-string" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->file_name_ = sf->p1__; 
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_filename_value_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rno_of_T_phrase  (){
  ->  Rno_of_T  Rno_of_T_value
}

Rno_of_T  (){
  -> "no-of-T"
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_no_of_T_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rno_of_T_value  (){
  -> "int-no" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->no_of_T_ = sf->p1__;
      // not eq make as a warning but continue parsing
      if(T_DICTIONARY.size() != sf->p1__->no()){
		CAbs_lr1_sym* sym = new Err_bad_T_alphabet;
		sym->set_rc(*sf->p1__,__FILE__,__LINE__);
		ADD_TOKEN_TO_ERROR_QUEUE(*sym);
		rule_info__.parser__->set_stop_parse(true);
      } 
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_no_of_T_value_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rlist_of_native_terminals_phrase  (){
  ->  Rlist_of_native_fset_terminals   
      Rno_of_native_fset_terminals	
      Rfset_terminals_epi	 
	  Rend_list_of_native_fset_terminals
}

Rlist_of_native_fset_terminals  (){
  -> "list-of-native-first-set-terminals" 
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_list_of_terminals_kw_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rno_of_native_fset_terminals  (){
  -> "int-no" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->no_native_T_ = sf->p1__; 
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_no_of_terminals_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rfset_terminals_epi  (){
  -> Rfset_terminals  
  ->  
}

Rfset_terminals  (){
  -> 	Ra_T 
  -> 	Rfset_terminals Ra_T  
}

Ra_T  (){
  -> identifier{
    op
      T_identifier* k = sf->p1__;
      CAbs_lr1_sym* sym = new Err_bad_T_in_list;
      sym->set_rc(*k,__FILE__,__LINE__);
     ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***			
    } 
  -> "tth-in-stbl" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      tth_in_stbl* k = sf->p1__;
      T_attributes* T_att = k->t_in_stbl();
      fsm->list_of_Ts_.push_back(T_att->T_enum_);
    ***			
    } 
}

Rend_list_of_native_fset_terminals  (){
  -> "end-list-of-native-first-set-terminals" 
  -> |?| {
    op
       CAbs_lr1_sym* sym = new Err_end_list_native_T_kw_not_present;
       sym->set_rc(*sf->p1__,__FILE__,__LINE__); 
       ADD_TOKEN_TO_ERROR_QUEUE(*sym);
       rule_info__.parser__->set_stop_parse(true);
    ***			
	}
}

Rlist_of_transitive_threads_phrase  (){
  -> Rlist_of_transitive_threads   
     Rno_of_transitive_threads	 
	 Rtransitive_threads_epi	 
	 Rend_list_of_transitive_threads
}
	 
Rlist_of_transitive_threads  (){
  -> "list-of-transitive-threads"
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_no_list_of_trans_threads_kw;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rno_of_transitive_threads  (){
  -> "int-no" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->no_threads_ = sf->p1__; 
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_no_of_threads_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rtransitive_threads_epi  (){
  -> Rtransitive_threads  
  ->  
}

Rtransitive_threads  (){
  -> 	Ra_th 
  -> 	Rtransitive_threads Ra_th  
}

Ra_th  (){
  -> identifier{
    op
 	  Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      T_identifier* k = sf->p1__;

      	using namespace yacco2_stbl;
		T_sym_tbl_report_card report_card;
		thread_attributes* th = new thread_attributes(k->identifier()->c_str());
		th->set_rc(*k,__FILE__,__LINE__);
        fsm->list_of_transitive_threads_.push_back(th);
		th_in_stbl* t = new th_in_stbl(th);
		add_sym_to_stbl(report_card
		               ,*k->identifier()->c_str()
		               ,*t
		               ,table_entry::used
		               ,table_entry::thread);
	  	if(report_card.status_ != T_sym_tbl_report_card::okay){
	  	  t->stbl_idx(report_card.pos_);
          report_card.err_entry_->set_rc(*k,__FILE__,__LINE__);
          ADD_TOKEN_TO_ERROR_QUEUE(*report_card.err_entry_);
          rule_info__.parser__->set_stop_parse(true);
          return;
		}
        GRAMMAR_DICTIONARY.push_back(report_card.tbl_entry_);
        th->th_enum_ = GRAMMAR_DICTIONARY.size()-1;

    ***			
    } 
  -> "th-in-stbl"{
    op
 	  Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      th_in_stbl* k = sf->p1__;
      thread_attributes* th = k->thread_in_stbl();
      fsm->list_of_transitive_threads_.push_back(th);

      	using namespace yacco2_stbl;
		T_sym_tbl_report_card report_card;
		find_sym_in_stbl(report_card,*th->fully_qualified_th_name_.c_str());
	  	if(report_card.status_ != T_sym_tbl_report_card::okay){
          report_card.err_entry_->set_rc(*k,__FILE__,__LINE__);
          ADD_TOKEN_TO_ERROR_QUEUE(*report_card.err_entry_);
          rule_info__.parser__->set_stop_parse(true);
          return;
		}
		if(report_card.action_ == T_sym_tbl_report_card::fnd){// crted by another fsc file
		  report_card.tbl_entry_->used_ = true;
		  return;
		}
		if(report_card.action_ == T_sym_tbl_report_card::not_fnd){
		  CAbs_lr1_sym* sym = new Err_no_sym_defs_present;
          sym->set_rc(*k,__FILE__,__LINE__);
          ADD_TOKEN_TO_ERROR_QUEUE(*sym);
          rule_info__.parser__->set_stop_parse(true);
          return;
		}
    ***			
    } 
}

Rend_list_of_transitive_threads  (){
  -> "end-list-of-transitive-threads" 
  -> |?| { 
    op
       CAbs_lr1_sym* sym = new Err_end_list_of_transitive_threads_kw_not_present;
       sym->set_rc(*sf->p1__,__FILE__,__LINE__); 
       ADD_TOKEN_TO_ERROR_QUEUE(*sym);
       rule_info__.parser__->set_stop_parse(true);
    ***			
	}
}
Rlist_of_used_threads_phrase  (){
  -> Rlist_of_used_threads   
     Rno_of_used_threads	 
	 Rused_threads_epi	 
	 Rend_list_of_used_threads
}
	 
Rlist_of_used_threads  (){
  -> "list-of-used-threads"
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_no_list_of_trans_threads_kw;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rno_of_used_threads  (){
  -> "int-no" {
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->used_no_threads_ = sf->p1__; 
    ***			
    }
  ->  |?| {
    op
      CAbs_lr1_sym* sym = new Err_no_of_threads_not_present;
      sym->set_rc(*sf->p1__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rused_threads_epi  (){
  -> Rused_threads  
  ->  
}

Rused_threads  (){
  -> 	Rb_th 
  -> 	Rused_threads Rb_th  
}

Rb_th  (){
  -> identifier{
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      T_identifier* k = sf->p1__;

      	using namespace yacco2_stbl;
	T_sym_tbl_report_card report_card;
	thread_attributes* th = new thread_attributes(k->identifier()->c_str());
	th->set_rc(*k,__FILE__,__LINE__);
        fsm->list_of_used_threads_.push_back(th);
        std::string::size_type x = th->fully_qualified_th_name_.find("::");
        string tnm;
        string& fqn = th->fully_qualified_th_name_;
        for(int xx=x+2;xx< fqn.size();++xx){
          tnm += fqn[xx];
        }
        fsm->used_threads_->push_back(tnm);
    ***			
    } 
  -> "th-in-stbl"{
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      th_in_stbl* k = sf->p1__;
      thread_attributes* th = k->thread_in_stbl();
      fsm->list_of_used_threads_.push_back(th);
        std::string::size_type x = th->fully_qualified_th_name_.find("::");
        string tnm;
        string& fqn = th->fully_qualified_th_name_;
        for(int xx=x+2;xx< fqn.size();++xx){
          tnm += fqn[xx];
        }
        fsm->used_threads_->push_back(tnm);
    ***			
    } 
}

Rend_list_of_used_threads  (){
  -> "end-list-of-used-threads" 
  -> |?| { 
    op
       CAbs_lr1_sym* sym = new Err_end_list_of_transitive_threads_kw_not_present;
       sym->set_rc(*sf->p1__,__FILE__,__LINE__); 
       ADD_TOKEN_TO_ERROR_QUEUE(*sym);
       rule_info__.parser__->set_stop_parse(true);
    ***			
	}
}
	
Rfsm_comments_phrase  (){
  ->  Rfsm_comments  Rfsm_comments_value
}
Rfsm_comments  (){
  ->  "#fsm-comments"
}
Rfsm_comments_value  (){
  ->  "c-string" {// drain the comment swamp
    op
      Cfsc_file* fsm = (Cfsc_file*) rule_info__.parser__->fsm_tbl__;
      fsm->fsm_comments_ = sf->p1__; 
    ***	
    }
}

}// end of rules
