/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:    linker_pass3.lex
dates:   10 feb. 2005	
Purpose: Lexical Phase for Yacco2's first set linker
*/
/@
@i "/usr/local/yacco2/copyright.w"
@** |linker_pass3| grammar.\fbreak
Quasi lexical / syntatic Phase for Yacco2's first set linker.\fbreak
Sample of a grammar's First set control file:\fbreak
\listing{"/usr/local/yacco2/diagrams+etc/intro3.txt"}

@/

fsm	
(fsm-id "linker_pass3.lex",fsm-filename linker_pass3,fsm-namespace NS_linker_pass3
,fsm-class Clinker_pass3{
  user-prefix-declaration
#include "linker_id.h"
#include "linker_preamble_code.h"
#include "lint_balls.h"
#include "c_string.h"
#include "angled_string.h"
#include "c_literal.h"
#include "bad_char_set.h"
using namespace NS_yacco2_terminals;	
 ***
  user-declaration
    public:
    bool  chk_filename(const char* Filename,CAbs_lr1_sym* Tok,CAbs_lr1_sym* Err);
    bool  chk_ofilename(const char* Filename,CAbs_lr1_sym* Tok);
    yacco2::CAbs_lr1_sym*  chk_for_overrun();
    std::string t_alphabet_filename_;
    std::string emitfile_filename_;
    T_syntax_code* preamble_srce_;
    std::vector<std::string> grammars_fsc_files_;
    std::vector<std::string> directories_;
  ***
  user-implementation
    bool  Clinker_pass3::chk_ofilename(const char* Filename,CAbs_lr1_sym* Tok){
      std::ofstream fle_chk;
      fle_chk.open(Filename,ios::out);
      if(!fle_chk.good()){
         CAbs_lr1_sym* sym = new Err_bad_filename(Filename);
         sym->set_rc(*Tok,__FILE__,__LINE__);
         parser__->add_token_to_error_queue(*sym);
         parser__->set_stop_parse(true);
         return false;
      }else{
        fle_chk.close();
      }
      return true;
    }
    bool  Clinker_pass3::chk_filename(const char* Filename
	,CAbs_lr1_sym* Tok,CAbs_lr1_sym* Err){
      std::ifstream fle_chk;
      fle_chk.open(Filename);
      if(!fle_chk.good()){
         Err->set_rc(*Tok,__FILE__,__LINE__);
        parser__->add_token_to_error_queue(*Err);
        parser__->set_stop_parse(true);
         return false;
      }else{
        delete Err;
        fle_chk.close();
      }
      return true;
    }
    yacco2::CAbs_lr1_sym* Clinker_pass3::chk_for_overrun(){
	  switch (parser__->current_token()->enumerated_id__){
		case T_Enum::T_LR1_eog_: break;
		default: return 0;		
      }
      yacco2::CAbs_lr1_sym* sym = new Err_end_preamble_kw_not_present;
      sym->set_rc(*parser__->start_token__,__FILE__,__LINE__);
      parser__->set_use_all_shift_off();
      return sym;
    }
  ***
}
,fsm-version	"1.0",fsm-date "9 Feb. 2005",fsm-debug "false"
,fsm-comments	"Lexer: constructing tokens for \\olinker parsing stage.")
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Rlinker_pass3  (
lhs{
  op
    using namespace NS_yacco2_k_symbols;
       ADD_TOKEN_TO_PRODUCER_QUEUE(*yacco2::PTR_LR1_eog__);   
       ADD_TOKEN_TO_PRODUCER_QUEUE(*yacco2::PTR_LR1_eog__);  
  ***
  }
){
  -> Rlint 
		RT_alphabet Rlint RT_alphabet_filename
	 Rlint
		Remitfile Rlint Remitfile_filename	 
	 Rlint
		Rpreamble Rpreamble_code	 
	 Rlint
		R_fsc_files
	 Rlint
	    eog
}

RT_alphabet  (){
  -> ||| "file-of-T-alphabet" NS_linker_id::TH_linker_id
  -> ||| |?| NULL {//catch errors
    op 
      CAbs_lr1_sym* sym = new Err_file_of_T_alphabet_kw_not_present;
      sym->set_rc(*sf->p2__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
      sf->p2__->set_auto_delete(true);
    ***
    }  
  ->  |?| { // error due to no first set to start thread {
    op
      CAbs_lr1_sym* sym = new Err_file_of_T_alphabet_kw_not_present;
      sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

RT_alphabet_filename  (){
  -> ||| "c-string" NS_c_string::TH_c_string{
    op
      Clinker_pass3* fsm = (Clinker_pass3*) rule_info__.parser__->fsm_tbl__;
      const char* fn = sf->p2__->c_string()->c_str(); 
      if(fsm->chk_filename(fn,sf->p2__,
	new Err_T_alphabet_file_does_not_exist) == false) return;
      fsm->t_alphabet_filename_ += fn;
      sf->p2__->set_auto_delete(true);
    ***			
    }
  -> ||| "bad eos" NULL{
    op
      ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
      rule_info__.parser__->set_stop_parse(true);
    ***			
    } 
  -> ||| "bad esc" NULL{
    op
      ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
      rule_info__.parser__->set_stop_parse(true);
   ***			
    } 
  -> ||| |?| NULL {//catch other yacco2_linker_keywords as errors
    op 
      CAbs_lr1_sym* sym = new Err_no_filename_present;
      sym->set_rc(*sf->p2__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
      sf->p2__->set_auto_delete(true);
    ***
    }  
  -> ||| "angled-string" NS_angled_string::TH_angled_string{
    op 
      Clinker_pass3* fsm = (Clinker_pass3*) rule_info__.parser__->fsm_tbl__;
      const char* fn = sf->p2__->angled_string()->c_str(); 
      if(fsm->chk_filename(fn,sf->p2__
	,new Err_T_alphabet_file_does_not_exist) == false) return;
      fsm->t_alphabet_filename_ += fn;
      sf->p2__->set_auto_delete(true);
    ***
    }
  ->  |?| { // error due to no first set to start thread {
    op
      CAbs_lr1_sym* sym = new Err_T_alphabet_file_not_present;
      sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Remitfile  (){
  -> ||| "emitfile" NS_linker_id::TH_linker_id
  -> ||| |?| NULL {//catch other yacco2_linker_keywords as errors
    op 
      CAbs_lr1_sym* sym = new Err_emitfile_kw_not_present;
      sym->set_rc(*sf->p2__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
      sf->p2__->set_auto_delete(true);
    ***
    }  
  ->  |?| { // error due to no first set to start thread {
    op
      CAbs_lr1_sym* sym = new Err_emitfile_kw_not_present;
      sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Remitfile_filename  (){
  -> ||| "c-string" NS_c_string::TH_c_string{
    op
      Clinker_pass3* fsm = (Clinker_pass3*) rule_info__.parser__->fsm_tbl__;
      const char* fn = sf->p2__->c_string()->c_str(); 
      if(fsm->chk_ofilename(fn,sf->p2__) == false) return;
      fsm->emitfile_filename_ += fn;
      sf->p2__->set_auto_delete(true);
    ***			
    }
  -> ||| "bad eos" NULL{
    op
      ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
      rule_info__.parser__->set_stop_parse(true);
    ***			
    } 
  -> ||| "bad esc" NULL{
    op
      ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
      rule_info__.parser__->set_stop_parse(true);
   ***			
    } 
  -> ||| |?| NULL {//catch errors
    op 
      CAbs_lr1_sym* sym = new Err_emitfile_file_not_present;
      sym->set_rc(*sf->p2__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
      sf->p2__->set_auto_delete(true);
    ***
    }  
  -> ||| "angled-string" NS_angled_string::TH_angled_string{
    op 
      Clinker_pass3* fsm = (Clinker_pass3*) rule_info__.parser__->fsm_tbl__;
      const char* fn = sf->p2__->angled_string()->c_str(); 
      if(fsm->chk_ofilename(fn,sf->p2__) == false) return;
      fsm->emitfile_filename_ += fn;
      sf->p2__->set_auto_delete(true);
    ***
    }
  ->  |?| { // error due to no first set to start thread {
    op
      CAbs_lr1_sym* sym = new Err_emitfile_file_not_present;
      sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rpreamble  (){
  -> ||| "preamble" NS_linker_id::TH_linker_id
  -> ||| |?| NULL {//catch other yacco2_linker_keywords as errors
    op 
      CAbs_lr1_sym* sym = new Err_preamble_kw_not_present;
      sym->set_rc(*sf->p2__,__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
      sf->p2__->set_auto_delete(true);
    ***
    }  
  ->  |?| { // error due to no first set to start thread {
    op
      CAbs_lr1_sym* sym = new Err_preamble_kw_not_present;
      sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

Rpreamble_code  (){
  -> ||| "syntax-code" NS_linker_preamble_code::TH_linker_preamble_code{
    op 
      Clinker_pass3* fsm = (Clinker_pass3*) rule_info__.parser__->fsm_tbl__;
      fsm->preamble_srce_ = sf->p2__;
    ***
    }
  -> ||| |?| NULL {//catch returned errors
    op 
      ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }  
  ->  |?| { // error due to no first set to start thread {
    op
      CAbs_lr1_sym* sym = new Err_preamble_srce_code_not_present;
      sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

R_fsc_files  (){
  -> R_fsc_file Rlint
  -> R_fsc_files R_fsc_file Rlint
  ->  |?| { // error due to no first set to start thread {
    op
      CAbs_lr1_sym* sym = new Err_fsc_cntl_file_not_present;
      sym->set_rc(*rule_info__.parser__->current_token(),__FILE__,__LINE__);
      ADD_TOKEN_TO_ERROR_QUEUE(*sym);
      rule_info__.parser__->set_stop_parse(true);
    ***
    }
}

R_fsc_file  (){
  -> ||| "c-string" NS_c_string::TH_c_string{
    op
	  Clinker_pass3* fsm = (Clinker_pass3*) rule_info__.parser__->fsm_tbl__;
      const char* fn = sf->p2__->c_string()->c_str(); 
      if(fsm->chk_filename(fn,sf->p2__
	,new Err_fsc_file_does_not_exist) == false) return;
      fsm->grammars_fsc_files_.push_back(string(fn));
      sf->p2__->set_auto_delete(true);
    ***			
    }
  -> ||| "bad eos" NULL{
    op
      ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
      rule_info__.parser__->set_stop_parse(true);
    ***			
    } 
  -> ||| "bad esc" NULL{
    op
      ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
      rule_info__.parser__->set_stop_parse(true);
   ***			
    } 
  -> ||| "angled-string" NS_angled_string::TH_angled_string{
    op 
      Clinker_pass3* fsm = (Clinker_pass3*) rule_info__.parser__->fsm_tbl__;
      const char* fn = sf->p2__->angled_string()->c_str(); 
      if(fsm->chk_filename(fn,sf->p2__
	,new Err_fsc_file_does_not_exist) == false) return;
      fsm->grammars_fsc_files_.push_back(string(fn));
      sf->p2__->set_auto_delete(true);
    ***
    }
  ->  ||| |?| NULL {
      op
        ADD_TOKEN_TO_ERROR_QUEUE(*sf->p2__);
        rule_info__.parser__->set_stop_parse(true);
      ***
      }
}

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