/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:     linker_preamble_code.lex
dates:    3 Jan.2003	
Purpose:  Extract linker's preamble code
conduit:  syntax_code
errors:   Err_end_preamble_kw_not_present
          Err_comment_overrun
          Err_bad_eos
          Err_bad_esc
          Err_preamble_srce_code_not_present
              
Correction: no preamble source code present and
            end-preamble consumed with next token eog.
            It should return "no preamble source code present" instead of
            "no end of code" error. 25 Apr. 2005
*/
/@
@i "/usr/local/yacco2/copyright.w"
@** |linker_preamble_code| thread.\fbreak
Extract linker's preamble code.
@/

fsm	
(fsm-id	"linker_preamble_code.lex",fsm-filename linker_preamble_code,fsm-namespace NS_linker_preamble_code
,fsm-class	Clinker_preamble_code{
  user-prefix-declaration
#include "string.h"
#include "c_comments.h"
#include "c_string.h"
#include "c_literal.h"
#include "linker_id.h"
  ***
  user-declaration
    public:
    std::string chrs_; 
    bool empty_sdc_;
  ***
  op
    parser__->set_use_all_shift_on();
    empty_sdc_ = true;
    chrs_.clear();
    CAbs_lr1_sym* sym = parser__->start_token__;
	switch (sym->enumerated_id__){
	  
	  case T_Enum::T_LR1_eog_: break;
	  default: return;		
    }
    parser__->set_use_all_shift_off();
  ***
  constructor
    empty_sdc_ = true;
    chrs_.clear();
  ***
  }
,fsm-version "1.0",fsm-date "30 dec 2002",fsm-debug "false"
,fsm-comments	"\\olinker's lexer of preamble code section:\n similar to Pass3 lexer.")
parallel-parser	
(	
  parallel-thread-function
    TH_linker_preamble_code
  ***
  parallel-la-boundary
eolr
  ***
)
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Rlinker_preamble_code(
lhs{
  op
    Clinker_preamble_code* fsm = (Clinker_preamble_code*)rule_info__.parser__->fsm_tbl__;
    CAbs_lr1_sym* sym(0);
    if(fsm->empty_sdc_ == true){
      sym = new Err_preamble_srce_code_not_present;
      sym->set_rc(*rule_info__.parser__->start_token__,__FILE__,__LINE__);
      RSVP(sym);
      rule_info__.parser__->set_stop_parse(true);
      return;
    }
    sym = new T_syntax_code(fsm->chrs_.c_str());
    sym->set_rc(*rule_info__.parser__->start_token__,__FILE__,__LINE__);
    RSVP(sym);
  ***  
  } 
){
  -> Rchrs
}

Rchrs (){
  -> 	Rchr  
  -> 	Rchrs Rchr  
}

Rchr (
lhs {
  op
    if(rule_info__.parser__->stop_parse__ == true) return;
    if(rule_info__.parser__->use_all_shift__ == false) return;// end-preamble seen
    CAbs_lr1_sym* la_sym = rule_info__.parser__->current_token();
    using namespace NS_yacco2_T_enum;
    using namespace NS_yacco2_terminals;
    // watch for overrun
    if(la_sym->enumerated_id__ == T_Enum::T_LR1_eog_){
      CAbs_lr1_sym* sym = new Err_end_preamble_kw_not_present;
      sym->set_rc(*la_sym,__FILE__,__LINE__);
      RSVP(sym);
      rule_info__.parser__->set_stop_parse(true);
    } 
  ***
}
){
  -> ||| "comment" NS_c_comments::TH_c_comments {
    op
 	  Clinker_preamble_code* fsm = (Clinker_preamble_code*) rule_info__.parser__->fsm_tbl__;
      T_comment* k = sf->p2__;
      k->set_auto_delete(true);// delete it when it pops from stack
      fsm->chrs_ += k->comment_data()->c_str();
    ***
    }
  -> ||| "c-string"	NS_c_string::TH_c_string{
    op
 	  Clinker_preamble_code* fsm = 
	(Clinker_preamble_code*) rule_info__.parser__->fsm_tbl__;
      T_c_string* k = sf->p2__;
      k->set_auto_delete(true);// delete it when it pops from stack
      // add back the bounding double quotes
      fsm->chrs_ += '"';
      fsm->chrs_ += k->c_string()->c_str();
      fsm->chrs_ += '"';
	  fsm->empty_sdc_ = false;
    ***			
    } 
  -> ||| "c-literal"	NS_c_literal::TH_c_literal{
    op
 	  Clinker_preamble_code* fsm = 
		(Clinker_preamble_code*) rule_info__.parser__->fsm_tbl__;
      T_c_literal* k = sf->p2__;
      k->set_auto_delete(true);// delete it when it pops from stack
      // add back the bounding single quotes
      fsm->chrs_ += "'";
      fsm->chrs_ += k->c_literal()->c_str();
      fsm->chrs_ += "'";
	  fsm->empty_sdc_ = false;
    ***			
    } 
  -> ||| "end-preamble" NS_linker_id::TH_linker_id{
    op 
 	  Clinker_preamble_code* fsm = (Clinker_preamble_code*) rule_info__.parser__->fsm_tbl__;
      rule_info__.parser__->set_use_all_shift_off();
      if(fsm->empty_sdc_ == true){
        CAbs_lr1_sym* sym = new Err_preamble_srce_code_not_present;
		sym->set_rc(*rule_info__.parser__->start_token__,__FILE__,__LINE__);
		RSVP(sym);
		rule_info__.parser__->set_stop_parse(true);
		return;
      }
    ***
    }
  -> |+| { // add balance of characters to queue Eg. comma
    op
 	  Clinker_preamble_code* fsm = 
		(Clinker_preamble_code*) rule_info__.parser__->fsm_tbl__;
      CAbs_lr1_sym* k = sf->p1__;
		switch (k->enumerated_id__){
			case T_Enum::T_T_eol_:{
				fsm->chrs_ += "\n";
				break;
			}
			case T_Enum::T_raw_sp_:{
				fsm->chrs_ += " ";
				break;
			}
			case T_Enum::T_raw_ff_:{
				fsm->chrs_ += "\f";
				break;
			}
			case T_Enum::T_raw_vt_:{
      			fsm->chrs_ += "\v";
				break;
			}
			case T_Enum::T_raw_ht_:{
            	fsm->chrs_ += "\t";
				break;
			}
			case T_Enum::T_raw_cr_:{
            	fsm->chrs_ += "\n";
				break;
			}
			case T_Enum::T_raw_lf_:{
				fsm->chrs_ += "\n";
				break;
			}
			default:{
				fsm->chrs_ += *k->id__;
				fsm->empty_sdc_ = false;
				break;
			}
		}
    ***			
    } 
  -> ||| |?| NULL {// errors
    op
       RSVP(sf->p2__);
       rule_info__.parser__->set_stop_parse(true);
    ***			
    } 
  -> ||| "identifier" NULL {
    op
    Clinker_preamble_code* fsm = 
		(Clinker_preamble_code*)rule_info__.parser__->fsm_tbl__;
      T_identifier* k = sf->p2__;
      k->set_auto_delete(true);// delete it when it pops from stack
      fsm->chrs_ += k->identifier()->c_str();
    ***
    }
}
}// end of rules
