/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:       angled_string.lex
Dates:      2 mar. 2005
Purpose:	angle bracket filename: Eg <yacco2.h>
Returned:	T_angled_string
            Err_bad_eos - meta terminal indicating an improper end-of-string 
                              this occurs on eof,eog, or an eol terminal ending the string
            Err_bad_esc - bad escape sequence. 
Note:       Stripped of its bounding <> for ease of use    
*/
/@
@i "/usr/local/yacco2/copyright.w"
@** |angled_string| Thread.\fbreak
It recognizes 
character sequences of example ${<}$ my disc ${>}$ 
typically used in a c++ include statement or in my case files to be
read either thru my own include statements or from the 
command line.
|esc_seq| thread evaluates the c++ literal character escape sequences buried
inside the angled brackets.
The escape sequences cover the backslash variety  --- 
octal, hex, and character, and
those pesky unicode types. 
Nothing is done with them at present --- only their syntax is
recognized.
The |esc_seq| terminal returned contains the
character string parsed.
The |angled_string| returned contains the enclosed character string
without the bounding angle brackets.
So ${<}$ my disc ${>}$ becomes ``my disc'' without the quotes.
The {\bf empty string} is tollerated. 
It is left to the calling grammar to deal with it.\fbreak
\fbreak
Errors:\fbreak
Caused by either an invalid character escape sequence or an improper closing of the 
|angled_string| --- an end of line or file etc 
before possibly omitted closing
``${>}$'' bracket.
These two conditions are indicated by the 2 error terminals
 |Err_bad_esc| and |Err_bad_eos|.\fbreak
\fbreak
Returned T: |T_angled_string| \fbreak 
@/
fsm	
(fsm-id	"angled_string.lex",fsm-filename angled_string,fsm-namespace NS_angled_string
,fsm-class		Cangled_string {
  user-prefix-declaration
#include "esc_seq.h"
  ***
   user-declaration
    public: 
    char ddd_[1024*32];
    int ddd_idx_;
    void copy_str_into_buffer(std::string* Str);
    void copy_kstr_into_buffer(const char* Str);
  ***
  user-implementation
    void Cangled_string::copy_str_into_buffer(std::string* Str){   
      const char* y = Str->c_str(); 
      int x(0);
      for(;y[x]!=0;++x,++ddd_idx_)ddd_[ddd_idx_] = y[x];
      ddd_[ddd_idx_] = 0;
    }
/@
@*3 |copy_kstr_into_buffer|.
@/

    void Cangled_string::copy_kstr_into_buffer(const char* Str){
      const char* y = Str; 
      int x(0);
      for(;y[x]!=0;++x,++ddd_idx_)ddd_[ddd_idx_] = y[x];
      ddd_[ddd_idx_] = 0;
    }
  ***
  constructor
    ddd_idx_ = 0;
    ddd_[ddd_idx_] = 0;
 ***
  op
    ddd_idx_ = 0;
    ddd_[ddd_idx_] = 0;
  ***
}
,fsm-version	"1.0"	,fsm-date		"17 Juin 2003"
,fsm-debug		"false"	
,fsm-comments	"Angled string lexer: < ... > with c type escape sequences.")
parallel-parser	
(	
  parallel-thread-function
    TH_angled_string
  ***
  parallel-la-boundary
    eolr
  ***
)
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Rangled_string  ()
{	
  -> Ropen_angle |.|{
  op
    Cangled_string* fsm = (Cangled_string*) rule_info__.parser__->fsm_tbl__;
    CAbs_lr1_sym* sym = new T_angled_string((const char*)&fsm->ddd_);
    sym->set_rc(*rule_info__.parser__->start_token__,__FILE__,__LINE__);
    RSVP(sym);
  ***
  }
}

Ropen_angle  (){
  -> "<" {
    op		
      Cangled_string* fsm = (Cangled_string*) rule_info__.parser__->fsm_tbl__;
loop:
	  switch (rule_info__.parser__->current_token()->enumerated_id__){
	  case T_Enum::T_raw_lf_: goto overrun;
	  case T_Enum::T_raw_cr_: goto overrun;
	  case T_Enum::T_LR1_eog_: goto overrun;	
	  case T_Enum::T_raw_gt_than_: goto closestr;
	  case T_Enum::T_raw_back_slash_: goto escseq;
          default: goto other;
          }
    closestr:{ // end of string
          rule_info__.parser__->get_next_token();
        return;// end of angled string
    }
    overrun:{
      CAbs_lr1_sym* sym = new Err_bad_eos;
      sym->set_rc(*rule_info__.parser__->start_token__,__FILE__,__LINE__);
      RSVP(sym);
      rule_info__.parser__->set_stop_parse(true);
      return;
    }
    escseq:{ // what type of escape
      using namespace NS_esc_seq;
      Parser::parse_result result = 
          rule_info__.parser__->start_manually_parallel_parsing(ITH_esc_seq.thd_id__);
      if(result == Parser::erred){
          // in this case, it will not happen: here for education
          rule_info__.parser__->set_abort_parse(true);
          return;
      }
      // process returned token
      Caccept_parse& accept_parm = *rule_info__.parser__->arbitrated_token__;
      CAbs_lr1_sym* rtn_tok = accept_parm.accept_token__;
      int id = rtn_tok->enumerated_id__;
      accept_parm.accept_token__ = 0;
      if(id != T_Enum::T_T_esc_seq_) {
          RSVP(rtn_tok);
          return;
      }
      T_esc_seq* finc = (T_esc_seq*)(rtn_tok);
      fsm->copy_str_into_buffer(finc->esc_data());
      rule_info__.parser__->override_current_token(*accept_parm.la_token__
            ,accept_parm.la_token_pos__);
      delete finc;
goto loop;
    };
    other:{
        fsm->copy_kstr_into_buffer(rule_info__.parser__->current_token()->id__);
          rule_info__.parser__->get_next_token();
goto loop;
      }
    ***
    }
}
}// end of rules
