/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:		  rule_def_phrase.lex
Dates:		  3 Jun 2004
Purpose:	  parse a rule definition construct
              Verifies if the symbol being defined is duplicate
              within yacco2's symbol table.
              Adds symbol to global symbol table.
Output:       rule_def
              assorted errors
*/
/@
@i "/usr/local/yacco2/copyright.w"
Parse a grammar's rule definition.\fbreak
\fbreak
Example of a rule definition to parse:\fbreak
\listing{"/usr/local/yacco2/diagrams+etc/ruledef.txt"}
@/
fsm	
(fsm-id "rule_def_phrase.lex"
,fsm-filename rule_def_phrase
,fsm-namespace NS_rule_def_phrase
,fsm-class Crule_def_phrase{
  user-prefix-declaration
#include "lint_balls.h"
#include "cweb_or_c_k.h"
#include "identifier.h"
#include "c_string.h"
#include "t_def_delabort_tags.h"
#include "subrules_phrase.h"
#include "rule_lhs_phrase.h"
#include "yacco2_stbl.h"
#include "parallel_monitor_ph.h"
  ***
  user-declaration
    public:
    rule_def* rule_def_;
  ***
  op
      rule_def_ = 0;
  ***
  constructor
      rule_def_ = 0;
  ***
}
,fsm-version "1.0",fsm-date "24 mar 2004",fsm-debug "false"
,fsm-comments "Parse a grammar's rule  definition.")
parallel-parser	
(	
  parallel-thread-function
    TH_rule_def_phrase
  ***
  parallel-la-boundary
    eolr
  ***
)
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Rrule_def_phrase  (){
  -> Rid Rlint Rad_ab_tags 
     Rlint Rrule_cweb_k Rlint
         Ropen_par Rlint
             Rrule_parameters
         Rclose_par Rlint 
         Rrule_body
         {
    op
      Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
      fsm->rule_def_->bld_its_tree();
      RSVP(fsm->rule_def_);
      fsm->rule_def_ = 0;
    ***
    }	
}

Rrule_cweb_k  (){
  -> 
  ->  ||| "cweb-comment" NS_cweb_or_c_k::TH_cweb_or_c_k {
	op
        Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
        T_cweb_comment* k = sf->p2__;
        AST* cwebk_t_ = new AST(*k);
        AST* cweb_t_ = new AST();
        T_cweb_marker* cw = new T_cweb_marker(cweb_t_);
        cw->set_rc(*k,__FILE__,__LINE__);
        fsm->rule_def_->add_cweb_marker(cweb_t_);
        AST::set_content(*cweb_t_,*cw);
        AST::join_pts(*cweb_t_,*cwebk_t_);
	***
	}
  ->  ||| |?| NULL {
      op 
		RSVP(sf->p2__);
		rule_info__.parser__->set_stop_parse(true); 
      ***
      }     
}
Rid  (){
  ->  ||| identifier NS_identifier::TH_identifier {
      op 
        Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
        const char* skey = sf->p2__->identifier()->c_str();
        fsm->rule_def_ = new rule_def(skey);
        rule_in_stbl* ristbl = new rule_in_stbl(*fsm->rule_def_);
        fsm->rule_def_->set_rc(*sf->p2__,__FILE__,__LINE__);
        sf->p2__->set_auto_delete(true);
        T_sym_tbl_report_card report_card;
        using namespace yacco2_stbl;
        add_sym_to_stbl(report_card,*skey,*ristbl,table_entry::defed,table_entry::rule);
	  	if(report_card.status_ != T_sym_tbl_report_card::okay){
			report_card.err_entry_->set_rc(*sf->p2__,__FILE__,__LINE__);
			RSVP(report_card.err_entry_);
			rule_info__.parser__->set_stop_parse(true);
			return;
		}
	  	ristbl->stbl_idx(report_card.pos_);
        report_card.tbl_entry_->defined_ = true;
      ***
      }
  ->  ||| "rule-in-stbl" NULL {// referenced created it, now set defined
      op 
        Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
		using namespace yacco2_stbl;
	    T_sym_tbl_report_card report_card;
	    find_sym_in_stbl(report_card,*sf->p2__->r_def()->rule_name()->c_str());
        if(report_card.action_ == T_sym_tbl_report_card::not_fnd){
			CAbs_lr1_sym* sym = new Err_rule_not_in_stbl;
			sym->set_rc(*rule_info__.parser__->start_token__,__FILE__,__LINE__);
			RSVP(sym);
			rule_info__.parser__->set_stop_parse(true); 
			return;        
        }
         if(report_card.tbl_entry_->defined_ == true){
			CAbs_lr1_sym* sym = new Err_rule_already_defined;
			sym->set_rc(*rule_info__.parser__->start_token__,__FILE__,__LINE__);
			RSVP(sym);
			rule_info__.parser__->set_stop_parse(true); 
			return;        
        }
       fsm->rule_def_ = sf->p2__->r_def();
        report_card.tbl_entry_->defined_ = true;
      ***
      }     
  ->  ||| |?| NULL {// other sym. tbl type entry
      op 
		CAbs_lr1_sym* sym = new Err_stble_has_entry_but_not_a_rule;
		sym->set_rc(*sf->p2__,__FILE__,__LINE__);
		RSVP(sym);
		rule_info__.parser__->set_stop_parse(true); 
		return;
      ***
      }     
  ->  |?| {
      op
        CAbs_lr1_sym* sym = new Err_no_rule_name_present;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
}

Rad_ab_tags  (){
  ->  Rad_ab_tag Rlint  
  ->  Rad_ab_tags Rad_ab_tag Rlint
  ->   
}

Rad_ab_tag  (){
  ->  ||| "#AD" NS_t_def_delabort_tags::TH_t_def_delabort_tags {
      op 
        Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
        if(fsm->rule_def_->autodelete() == true){
			CAbs_lr1_sym* sym = new Err_already_defined_AD;
			sym->set_rc(*sf->p2__,__FILE__,__LINE__);
			RSVP(sym);
			rule_info__.parser__->set_stop_parse(true);
			return;
        }
        fsm->rule_def_->autodelete(true);
      ***
      }
  ->  ||| "#AB" NULL {
      op 
        Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
        if(fsm->rule_def_->autoabort() == true){
			CAbs_lr1_sym* sym = new Err_already_defined_AB;
			sym->set_rc(*sf->p2__,__FILE__,__LINE__);
			RSVP(sym);
			rule_info__.parser__->set_stop_parse(true);
			return;
        }
        fsm->rule_def_->autoabort(true);
      ***
      }
}

Rrule_parameters  (){
  ->  // correct that epsilon works instead of inv shift
  -> Rrule_parameter
  -> Rrule_parameters "," Rrule_parameter
}

Rrule_parameter  (){
  -> ||| |?| NULL{
    op
        CAbs_lr1_sym* sym = new Err_not_lhs_pcnrl_mntr;
        sym->set_rc(*sf->p2__,__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
    ***
  }
    -> ||| "#lhs" NS_identifier::TH_identifier Rlhs_phrase
    -> ||| "#parallel-control-monitor" NULL Rparallel_monitor_phrase

}

Rlhs_phrase  (){
  -> |t| "rule-lhs-phrase" NS_rule_lhs_phrase::PROC_TH_rule_lhs_phrase {
    op
      Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
      fsm->rule_def_->rule_lhs(sf->p2__);
    ***
    }
  -> |t| |?| NULL{ //pass on its error
    op
        RSVP(sf->p2__);
        rule_info__.parser__->set_stop_parse(true);
    ***
  }
}

Rparallel_monitor_phrase  (){
  -> |t| "parallel-monitor-phrase" NS_parallel_monitor_ph::PROC_TH_parallel_monitor_ph {
    op
      Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
      fsm->rule_def_->parallel_mntr(sf->p2__);
    ***
    }
  -> |t| |?| NULL{
    op
        RSVP(sf->p2__);
        rule_info__.parser__->set_stop_parse(true);
    ***
  }
}

Rrule_body  (){
  ->  Ropen_brace Rlint 
        Rsubrules Rlint 
      Rclose_brace Rlint
}

Rsubrules  (){
  ->  ||| "subrules-phrase" NS_subrules_phrase::TH_subrules_phrase{
    op
      Crule_def_phrase* fsm = (Crule_def_phrase*)rule_info__.parser__->fsm_tbl__;
      fsm->rule_def_->subrules(sf->p2__);
      // distribute rule def to its subrules
      std::vector<T_subrule_def*>::iterator i = sf->p2__->subrules()->begin();
      std::vector<T_subrule_def*>::iterator ie = sf->p2__->subrules()->end();
      for(;i != ie;++i){
        T_subrule_def* srd = *i;
        srd->its_rule_def(fsm->rule_def_);
      }
    ***
    }
  -> ||| |?| NULL{
    op
        RSVP(sf->p2__);
        rule_info__.parser__->set_stop_parse(true);
    ***
  }
  ->  |?| { 
      op
        CAbs_lr1_sym* sym = new Err_no_sub_rule_present;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
}

Ropen_par  (){
  ->  |?| { 
      op
        CAbs_lr1_sym* sym = new Err_no_open_parenthesis;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
  ->  "("
}

Rclose_par  (){
  -> |?|  { 
      op
        CAbs_lr1_sym* sym = new Err_no_close_parenthesis;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
  ->  ")"
}

Ropen_brace  (){
  ->  |?| { 
      op
        CAbs_lr1_sym* sym = new Err_no_open_brace;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
  ->  "{"
}

Rclose_brace  (){
  ->  |?| { 
      op
        CAbs_lr1_sym* sym = new Err_no_close_brace;
        sym->set_rc(*sf->p1__,__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
  ->  "}"
}

Rlint  (){
  ->  ||| lint NS_lint_balls::TH_lint_balls
  -> 
}
}// end of rules
