/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:		  rules_phrase_th.lex
Dates:		  3 Jun 2004
Purpose:	  parse rules phrase
              The keeps its own local symbol table: map and list.
              The rule_def_phrase adds symbol to Yacco2's
              global symbol table.
Output:       rules_phrase
*/
/@
@i "/usr/local/yacco2/copyright.w"
@** |rules_phrase_th| Thread.\fbreak
Parse all of the grammar's rules.
The |rule_def_phrase| adds each rule defined to \O2's
global symbol table.
@/
fsm	
(fsm-id "rules_phrase_th.lex"
,fsm-filename rules_phrase_th
,fsm-namespace NS_rules_phrase_th
,fsm-class Crules_phrase_th{
  user-prefix-declaration
#include "ws.h"
#include "eol.h"
#include "c_comments.h"
#include "cweb_or_c_k.h"

#include "rule_def_phrase.h"
#include "o2_externs.h"
  ***
  user-declaration
    public:
    T_rules_phrase* rules_phrase_;
    AST* end_rules_t_;
  ***
  constructor
    rules_phrase_ = 0;
    end_rules_t_ = 0;
 ***
  op
    if(rules_phrase_ != 0){
      delete rules_phrase_;
      rules_phrase_ = 0;
      end_rules_t_ = 0;
    }
    rules_phrase_ = new T_rules_phrase;
    rules_phrase_->set_rc(*parser__->start_token__,__FILE__,__LINE__);
    AST* t = new AST(*rules_phrase_);
    rules_phrase_->phrase_tree(t);
  ***
}
,fsm-version "1.0",fsm-date "22 mar 2004",fsm-debug "false"
,fsm-comments "Parse all of the grammar's rules.")
parallel-parser	
(	
  parallel-thread-function
    TH_rules_phrase_th
  ***
  parallel-la-boundary
    eolr
  ***
)
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Rrules_phrase  (){
  -> Rlint_or_cweb Rrule_defs_phrase Rlint_or_cweb_or_error  {
    op
      Crules_phrase_th* fsm = (Crules_phrase_th*)rule_info__.parser__->fsm_tbl__;
      RSVP(fsm->rules_phrase_);
      fsm->rules_phrase_ = 0;
    ***
    }	
}

Rrule_defs_phrase  (){
  -> Ropen_brace
       Rlint_or_cweb
       Rrule_defs
       Rlint_or_cweb
     Rclose_brace
}

Rrule_defs  (){
  ->  Rrule_def Rlint_or_cweb
  ->  Rrule_defs Rrule_def1 Rlint_or_cweb
}

Rrule_def  (){
  ->  ||| "rule-def" NS_rule_def_phrase::TH_rule_def_phrase {
    op
      Crules_phrase_th* fsm = (Crules_phrase_th*)rule_info__.parser__->fsm_tbl__;
      CAbs_lr1_sym* r = 
	fsm->rules_phrase_->add_r_to_alphabet(sf->p2__,rule_info__.parser__);
      if(r != 0){
        RSVP(r);
        rule_info__.parser__->set_stop_parse(true);
        return;
      }
      AST* rt = sf->p2__->rule_s_tree();
      // ms has a bug so use temporary  
	  AST* t = fsm->rules_phrase_->phrase_tree();
      if(fsm->end_rules_t_ == 0){
         AST::join_pts(*t,*rt);
	  }else{
         AST::join_sts(*fsm->end_rules_t_,*rt);
	  }
      fsm->end_rules_t_ = rt;
    ***
    }
  ->  ||| |?| NULL {
      op
        RSVP(sf->p2__);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
  ->  |?| {
    op
        CAbs_lr1_sym* sym = new Err_no_rule_name_present;
        sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rrule_def1  (){
  ->  ||| "rule-def" NS_rule_def_phrase::TH_rule_def_phrase {
    op
      Crules_phrase_th* fsm = (Crules_phrase_th*)rule_info__.parser__->fsm_tbl__;
      CAbs_lr1_sym* r = fsm->rules_phrase_->add_r_to_alphabet(sf->p2__,rule_info__.parser__);
      if(r != 0){
        RSVP(r);
        rule_info__.parser__->set_stop_parse(true);
        return;
      }
      AST* rt = sf->p2__->rule_s_tree();
      AST::join_sts(*fsm->end_rules_t_,*rt);
      fsm->end_rules_t_ = rt;
    ***
    }
  ->  ||| |+| NULL {
      op
        RSVP(sf->p2__);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
}

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

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

Rlint_or_cweb_or_error  (){
  -> 
  -> |?| {
      op
        CAbs_lr1_sym* sym = new Err_improper_closing_of_rules;
        sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
        RSVP(sym);
        rule_info__.parser__->set_stop_parse(true);
      ***
  }
  -> Rfluffs_or_cweb |.| 
}

Rlint_or_cweb (){
  -> 
  -> Rfluffs_or_cweb
}

Rfluffs_or_cweb  (){
  ->  Rfluff_or_cweb
  ->  Rfluffs_or_cweb Rfluff_or_cweb
}

Rfluff_or_cweb  (){
  ->  ||| ws NS_ws::TH_ws
  ->  ||| comment NULL {
      op
        sf->p2__->set_auto_delete(true);
      ***
      }
  ->  ||| "cweb-comment" NS_cweb_or_c_k::TH_cweb_or_c_k {
      op
       Crules_phrase_th* fsm = (Crules_phrase_th*)rule_info__.parser__->fsm_tbl__;
	   AST* t = fsm->rules_phrase_->phrase_tree();
        T_cweb_comment* k = sf->p2__;
        AST* cwebk_t_ = new AST(*k);
        AST* rt = new AST();
        T_cweb_marker* cw = new T_cweb_marker(rt);
        cw->set_rc(*k,__FILE__,__LINE__);
      AST::set_content(*rt,*cw);
        AST::join_pts(*rt,*cwebk_t_);

       if(fsm->end_rules_t_ == 0){
         AST::join_pts(*t,*rt);
	   }else{
         AST::join_sts(*fsm->end_rules_t_,*rt);
	   }
       fsm->end_rules_t_ = rt;
      ***
      }
  ->  ||| "comment-overrun" NULL {
      op
        RSVP(sf->p2__);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
  ->  ||| eol NS_eol::TH_eol 
}
}// end of rules