/*
  Copyright Dave Bone 1998 - 2014 
  All Rights Reserved. 
  No part of this document may be reproduced without written consent from the author.
	
FILE:     o2_sdc.lex
dates:    3 Jan.2003	
Purpose:  Extract yacco2's syntax directed code
conduit:  syntax_code
errors:   Err_no_end_of_code
          Err_comment_overrun
          Err_bad_eos
          Err_bad_esc
          Err_no_syntax_code_present

Note:     A simple test is done as to whether there is any real 
          syntax directed code is inputted:
            only strings, literals, or chrs (not {eol, ws}) are
            considered code.
            
          Due to the overhead of strings and their copy facility,
          I've changed to the raw string copy with a fixed buffer size.
          The saftey and flexibility had too much cost to run:
             approximately 10 seconds of overhead on approximately 100k
             of text. Looking at the way the string was grown out when
             characters were appended to it demanded that I use this approach.  
*/
/@
@i "/usr/local/yacco2/copyright.w"
@** |o2_sdc| Thread.\fbreak
A single crawler of characters scooping up a grammar directive's
syntax directed code.
Added to it is ``cweb'' comment support.
This allows the grammar document to support better
code formatting particularly when
the ``syntax directed code'' is big.
The caveat is the emitted cpp code when
``-p'' option is on contains
the ``cweave'' formatting directives and bypassed when not to
generate the grammar document.
So be warned.
Generate the cpp code without the ``-p'' option
to avoid the c++ errors.
@/
fsm	
(fsm-id	"o2_sdc.lex",fsm-filename o2_sdc,fsm-namespace NS_o2_sdc
,fsm-class	Co2_sdc{
  user-prefix-declaration
#include "cweb_or_c_k.h"
#include "c_string.h"
#include "c_literal.h"
#include "o2_code_end.h"
extern char PRT_SW;
  ***
  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 Co2_sdc::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 Co2_sdc::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;
    parser__->set_use_all_shift_on();
    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();
  ***
  }
,fsm-version "1.0",fsm-date "30 dec 2002",fsm-debug "false"
,fsm-comments	"\\O2's syntax directed code extractor.")
parallel-parser	
(	
  parallel-thread-function
    TH_o2_sdc
  ***
  parallel-la-boundary
    eolr - |+| - |||
  ***
)
@"/usr/local/yacco2/compiler/grammars/yacco2_T_includes.T"

rules{
Ryacco2_syntax_code	(
lhs{
  op
    Co2_sdc* fsm = (Co2_sdc*)rule_info__.parser__->fsm_tbl__;
    CAbs_lr1_sym* sym(0);
    if(fsm->ddd_idx_ == 0){
      sym = new Err_no_syntax_code_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((const char*)&fsm->ddd_);
    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;
    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_no_end_of_code;
      sym->set_rc(*la_sym,__FILE__,__LINE__);
      RSVP(sym);
      rule_info__.parser__->set_stop_parse(true);
    } 
  ***
}
){

  -> ||| "comment" NS_cweb_or_c_k::TH_cweb_or_c_k {
    op
    Co2_sdc* fsm = (Co2_sdc*)rule_info__.parser__->fsm_tbl__;
      T_comment* k = sf->p2__;
      k->set_auto_delete(true);// delete it when it pops from stack
      fsm->copy_str_into_buffer(k->comment_data());
    ***
    }
  -> ||| "cweb-comment" NULL {
    op
    Co2_sdc* fsm = (Co2_sdc*)rule_info__.parser__->fsm_tbl__;
      T_cweb_comment* k = sf->p2__;
      k->set_auto_delete(true);// delete it when it pops from stack
      if(PRT_SW == 'n') return;// bypass the cweve comments in the cpp code
      fsm->copy_str_into_buffer(k->comment_data());
      string fmt("@<More code@>+=\n");
      fsm->copy_str_into_buffer(&fmt);
    ***
    }
  -> ||| "c-string"	NS_c_string::TH_c_string{
    op
    Co2_sdc* fsm = (Co2_sdc*)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->ddd_[fsm->ddd_idx_] = '"';
      ++fsm->ddd_idx_;
      fsm->copy_str_into_buffer(k->c_string());
      fsm->ddd_[fsm->ddd_idx_] = '"';
      ++fsm->ddd_idx_;
      fsm->ddd_[fsm->ddd_idx_] = 0;
    ***			
    } 
  -> ||| "c-literal"	NS_c_literal::TH_c_literal{
    op
    Co2_sdc* fsm = (Co2_sdc*)rule_info__.parser__->fsm_tbl__;
      T_c_literal* k = sf->p2__;
      k->set_auto_delete(true);
      // add back the bounding single quotes
      fsm->ddd_[fsm->ddd_idx_] = '\'';
      ++fsm->ddd_idx_;
      fsm->copy_str_into_buffer(k->c_literal());
      fsm->ddd_[fsm->ddd_idx_] = '\'';
      ++fsm->ddd_idx_;
      fsm->ddd_[fsm->ddd_idx_] = 0;
    ***			
    } 
  -> ||| "#***"	NS_o2_code_end::TH_o2_code_end{
    op
      sf->p2__->set_auto_delete(true);
      rule_info__.parser__->set_use_all_shift_off();
    ***			
    } 
  -> |+| { 
    
    /@
    Add balance of characters to sdcode string: ex. comma.
    Special escape sequences are put back to their original declaration.
    @/
    
    op
    Co2_sdc* fsm = (Co2_sdc*)rule_info__.parser__->fsm_tbl__;
      CAbs_lr1_sym* k = sf->p1__;
		switch (k->enumerated_id__){
			case T_Enum::T_LR1_eog_:{
			    rule_info__.parser__->set_use_all_shift_off();
    				break;
			}
			case T_Enum::T_T_eol_:{
		fsm->copy_kstr_into_buffer("\n");
				break;
			}
			case T_Enum::T_raw_sp_:{
		fsm->copy_kstr_into_buffer(" ");
				break;
			}
			case T_Enum::T_raw_ff_:{
		fsm->copy_kstr_into_buffer("\f");
				break;
			}
			case T_Enum::T_raw_vt_:{
		fsm->copy_kstr_into_buffer("\v");
				break;
			}
			case T_Enum::T_raw_ht_:{
		fsm->copy_kstr_into_buffer("\t");
				break;
			}
			default:{
      fsm->ddd_[fsm->ddd_idx_] = k->id__[0];
      ++fsm->ddd_idx_;
      fsm->ddd_[fsm->ddd_idx_] = 0;
			}
		}
    ***			
    } 
  -> ||| |?| NULL {// errors
    op
       RSVP(sf->p2__);
       rule_info__.parser__->set_stop_parse(true);
    ***			
    } 
}
}// end of rules
