rustlr/
sd_parserwriter.rs

1#![allow(dead_code)]
2#![allow(unused_variables)]
3#![allow(non_snake_case)]
4#![allow(non_camel_case_types)]
5#![allow(unused_parens)]
6#![allow(unused_mut)]
7#![allow(unused_assignments)]
8#![allow(unused_doc_comments)]
9#![allow(unused_imports)]
10use std::io::{self,Read,Write,BufReader,BufRead};
11use std::collections::HashSet;
12//use std::hash::{Hash,Hasher}; //use std::any::Any;
13use std::fs::File;
14use std::io::prelude::*;
15use std::path::Path;
16//use std::mem;
17use crate::{Statemachine,checkboxexp};
18use crate::Stateaction::*;
19
20
21
22  fn is_lba(t:&str) -> bool {
23   t.trim().starts_with("LBox") && t.contains("Any") && t.contains('<') && t.contains('>')
24  }//is_lba to check type
25
26// decode a grammar label, first return value is type of the label
27// 0=direct
28// 1=boxed
29// 2= &mut   like in e@..@
30// 3= &mut box  like in [e]@..@
31// 4= no distinct label, @..@ without name
32// k = position of argument of rhs 0 = first
33pub fn decode_label(label:&str,k:usize) -> (u8,String)
34{
35  let mut plab = format!("_item{}_",k);
36  if label.len()==0 {return (0,plab);}
37  let mut boxedlabel = false;  // see if named label is of form [x]
38  let findat = label.find('@');
39  let mut ltype = 0;
40  match &findat {
41     None if label.len()>0 /*&& !gsym.label.contains('(')*/ => {
42            let truelabel = checkboxexp(label,&plab);
43            boxedlabel = label.starts_with('[') && (truelabel != label); 
44            plab = String::from(truelabel);
45            if boxedlabel {ltype=1;} /* else {ltype=0;} */
46          },
47    Some(ati) if *ati==0 => { ltype=4; },
48    Some(ati) if *ati>0 => {
49            let rawlabel = label[0..*ati].trim();
50            let truelabel = checkboxexp(rawlabel,&plab);
51            boxedlabel = rawlabel.starts_with('[') && (truelabel != rawlabel);
52            if boxedlabel {ltype=3;} else {ltype=2;}
53            plab = String::from(truelabel);
54          },
55    _ => {},
56  }//match
57  /*
58  if ltype>1
59    {eprintln!("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n");}
60  //if plab.starts_with("NEW") {plab=format!("_item{}_",k);}
61  */
62  (ltype,plab)
63}//decode_label
64
65
66/////////////////////LRSD VERSION//////////////////////////////////////
67   ///// semantic action fn is _rrsemaction_rule_{rule index}
68////////////////////////////////////////////////
69impl Statemachine
70{
71  pub fn writelrsdparser(&mut self, filename:&str)->Result<(),std::io::Error>
72  {
73    let mut absyn = &self.Gmr.Absyntype;
74
75    if self.Gmr.sametype || is_lba(absyn){
76       return self.writelbaparser(filename);
77    }
78    
79    let mut extype = &self.Gmr.Externtype;
80    let lifetime = &self.Gmr.lifetime;
81    let has_lt = lifetime.len()>0 && (absyn.contains(lifetime) || extype.contains(lifetime));
82    let ltopt = if has_lt {format!("<{}>",lifetime)} else {String::from("")};
83    let rlen = self.Gmr.Rules.len();
84
85    let LBC = if self.Gmr.bumpast {"LC"} else {"LBox"};
86    
87    let bltref = if self.Gmr.bumpast {format!("&{} ",&self.Gmr.lifetime)} else {String::new()};
88    
89    // generate action fn's from strings stored in gen-time grammar
90    // these are the _semaction_rule_ri functions.  move function to
91    // pop stack to the closures attached to each runtime rule.
92    // make this a pure function on types defined.
93    let mut actions:Vec<String> = Vec::with_capacity(rlen);
94    
95    for ri in 0..rlen
96    {
97      let lhs = &self.Gmr.Rules[ri].lhs.sym;
98      let lhsi = self.Gmr.Rules[ri].lhs.index; //self.Gmr.Symhash.get(lhs).expect("GRAMMAR REPRESENTATION CORRUPTED");
99      let rettype = &self.Gmr.Symbols[lhsi].rusttype; // return type=rusttype
100      let ltoptr = if has_lt || (lifetime.len()>0 && rettype.contains(lifetime))
101        {format!("<{}>",lifetime)} else {String::from("")};
102
103// first arg to semaction is parser itself. - this is a must.
104      let mut fndef = format!("\nfn _rrsemaction_{}_{}(parser:&mut ZCParser<RetTypeEnum{},{}>",ri,&ltoptr,&ltopt,extype);
105      // now for other arguments
106      // inside actions, can still bind labels to patterns
107      let mut patternactions = String::new();                  
108      for k in 0..self.Gmr.Rules[ri].rhs.len() {
109        let symk= &self.Gmr.Rules[ri].rhs[k]; 
110        let symktype = &self.Gmr.Symbols[symk.index].rusttype;
111        let(labelkind,label) = decode_label(&symk.label,k);
112        if labelkind>1 {
113          if self.Gmr.tracelev>0 { println!("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
114          else {self.Gmr.genlog.push_str("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
115        }
116        let mut fargk = match labelkind {
117          0 => {format!(", mut {}:{}",&label,symktype)},
118          //1 => {format!(", mut {}:{}{}<{}>",&label,&bltref,LBC,symktype)},
119          1 => {
120            if self.Gmr.bumpast {
121              format!(", mut {}:{}{}<{}>",&label,&bltref,LBC,symktype)
122            }
123            else {
124              if self.Gmr.Rules[ri].autogenerated { // if auto-generated type
125                format!(", mut {}:{}",&label,symktype) //.lc inserted by writer
126              }
127              else {
128                //format!(", mut {}:{}LC<{}>",&label,&bltref,symktype)
129                format!(", mut {}:LBox<{}>",&label,symktype)
130              }
131            }// not bumpast
132          },
133          // need to distinguish LC and LBox here!
134          2 => {   // label is a e@..@ pattern
135            let ati = symk.label.find('@').unwrap();
136            patternactions.push_str(&format!("let {} = {}; ",
137                                     &symk.label[ati+1..],&label));
138            format!(", {}:&mut {}",&label,symktype)
139          },
140          3 => {   // label is a [e]@..@ pattern
141            let ati = symk.label.find('@').unwrap();          
142            patternactions.push_str(&format!("let {} = &mut *{}; ",
143                                     &symk.label[ati+1..],&label));
144            // this probably won't be consistent
145            if self.Gmr.bumpast || !self.Gmr.Rules[ri].autogenerated {
146              format!(", mut {}:{}{}<{}>",&label,&bltref,LBC,symktype)
147            }
148            else {
149              format!(", mut {}:{}",&label,symktype)
150            }
151          },
152          _ => {
153            let ati = symk.label.find('@').unwrap();          
154            patternactions.push_str(&format!("let {} = _item{}_; ",
155                                     &symk.label[ati+1..],k));
156            format!(", mut _item{}_:{}",k,symktype)
157          },
158        };//match
159        fndef.push_str(&fargk);
160      }// for each symbol on rhs
161      fndef.push_str(&format!(") -> {} {{ ",rettype));
162      let defaultaction = format!("<{}>::default()}}",rettype);
163      let mut semaction = &self.Gmr.Rules[ri].action; //string that ends w/rbr
164      if semaction.len()>1  {fndef.push_str(&patternactions);}
165      if semaction.len()<=1 {semaction = &defaultaction;}
166      fndef.push_str(&semaction); 
167      actions.push(fndef);
168    } //for ri
169
170    ////// write to file, create Ruleaction closures for each rule
171
172    let mut fd = File::create(filename)?;
173    write!(fd,"//Parser generated by rustlr for grammar {}",&self.Gmr.name)?;
174    write!(fd,"\n    
175#![allow(unused_variables)]
176#![allow(non_snake_case)]
177#![allow(non_camel_case_types)]
178#![allow(unused_parens)]
179#![allow(unused_mut)]
180#![allow(unused_imports)]
181#![allow(unused_assignments)]
182#![allow(dead_code)]
183#![allow(unreachable_patterns)]
184#![allow(irrefutable_let_patterns)]
185use std::rc::Rc;
186use std::cell::RefCell;
187extern crate rustlr;
188use rustlr::{{Tokenizer,TerminalToken,ZCParser,ZCRProduction,Stateaction,decode_action}};\n")?;
189    if self.Gmr.genlex {
190      write!(fd,"use rustlr::{{StrTokenizer,RawToken,LexSource}};
191use std::collections::{{HashMap,HashSet}};\n")?;
192    }
193
194    write!(fd,"{}\n",&self.Gmr.Extras)?; // use clauses and such
195
196    // write static array of symbols
197    write!(fd,"static SYMBOLS:[&'static str;{}] = [",self.Gmr.Symbols.len())?;
198    for i in 0..self.Gmr.Symbols.len()-1
199    {
200      write!(fd,"\"{}\",",&self.Gmr.Symbols[i].sym)?;
201    }
202    write!(fd,"\"{}\"];\n\n",&self.Gmr.Symbols[self.Gmr.Symbols.len()-1].sym)?;
203    // position of symbols must be inline with self.Gmr.Symhash
204
205    // record table entries in a static array
206    let mut totalsize = 0;
207    for i in 0..self.FSM.len() { totalsize+=self.FSM[i].len(); }
208    if self.Gmr.tracelev>1 {println!("{} total state table entries",totalsize);}
209    write!(fd,"static TABLE:[u64;{}] = [",totalsize)?;
210    // generate table to represent FSM
211    let mut encode:u64 = 0;
212    for i in 0..self.FSM.len() // for each state index i
213    {
214      let row = &self.FSM[i];        
215      for key in row.keys()
216      { // see function decode for opposite translation
217        let k = *key; //*self.Gmr.Symhash.get(key).unwrap(); // index of symbol
218        encode = ((i as u64) << 48) + ((k as u64) << 32);
219        match row.get(key) {
220          Some(Shift(statei)) => { encode += (*statei as u64) << 16; },
221          Some(Gotonext(statei)) => { encode += ((*statei as u64) << 16)+1; },
222          Some(Reduce(rulei)) => { encode += ((*rulei as u64) << 16)+2; },
223          Some(Accept) => {encode += 3; },
224          _ => {encode += 4; },  // 4 indicates Error
225        }//match
226        write!(fd,"{},",encode)?;
227      } //for symbol index k
228    }//for each state index i
229    write!(fd,"];\n\n")?;
230
231    // write action functions fn _semaction_rule_{} ..
232    for deffn in &actions { write!(fd,"{}\n",deffn)?; }
233
234    // must know what absyn type is when generating code.
235    write!(fd,"\npub fn make_parser{}() -> ZCParser<RetTypeEnum{},{}>",&ltopt,&ltopt,extype)?; 
236    write!(fd,"\n{{\n")?;
237    write!(fd," let mut parser1:ZCParser<RetTypeEnum{},{}> = ZCParser::new({},{});\n",&ltopt,extype,self.Gmr.Rules.len(),self.FSM.len())?;
238
239
240    // generate rules and Ruleaction delegates to call action fns, cast
241//     write!(fd," let mut rule = ZCRProduction::<RetTypeEnum{},{}>::new_skeleton(\"{}\");\n",&ltopt,extype,"start")?; // dummy for init
242    write!(fd," let mut rule;\n")?; // dummy for init
243    for ri in 0..self.Gmr.Rules.len() 
244    {
245      let lhs = &self.Gmr.Rules[ri].lhs.sym;
246      let lhsi = self.Gmr.Rules[ri].lhs.index; 
247      let rettype = &self.Gmr.Symbols[lhsi].rusttype; // return type=rusttype
248      write!(fd," rule = ZCRProduction::<RetTypeEnum{},{}>::new_skeleton(\"{}\");\n",&ltopt,extype,self.Gmr.Rules[ri].lhs.sym)?;
249      write!(fd," rule.Ruleaction = |parser|{{ ")?;
250
251    // write code to pop stack, decode labels into args. /////////
252      let mut k = self.Gmr.Rules[ri].rhs.len(); //k=len of rhs of rule ri
253      //form if-let labels and patterns as we go...
254      let mut actualargs = Vec::new();
255      while k>0 // k is length of right-hand side, use k-1
256      {
257        let gsym = &self.Gmr.Rules[ri].rhs[k-1]; // rhs syms right to left
258        let (lbtype,poppedlab) = decode_label(&gsym.label,k-1);
259        if lbtype>1 {
260          if self.Gmr.tracelev>0 { println!("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
261          else {self.Gmr.genlog.push_str("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
262        }
263        let symtype=&self.Gmr.Symbols[gsym.index].rusttype;
264        let emsg = format!("FATAL ERROR: '{}' IS NOT A TYPE IN THIS GRAMMAR. DID YOU INTEND TO USE THE -auto OPTION TO GENERATE TYPES?",&symtype);
265        let eindex = self.Gmr.enumhash.get(symtype).expect(&emsg);
266        actualargs.push(format!("{}",&poppedlab));           
267        let stat = match lbtype {
268           0  => {
269             format!("let mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",&poppedlab,&eindex,symtype)
270           },
271           1  |  3 => {
272             if self.Gmr.bumpast {
273               format!("let mut _rr{0}_ = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; let mut {0} = parser.exstate.make(parser.lc({3},_rr{0}_)); ",&poppedlab,&eindex,symtype,k-1)
274             } else {
275               if self.Gmr.Rules[ri].autogenerated { // auto-generated type
276                 format!("let mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",&poppedlab,&eindex,symtype) // lc/lbx determined by ast_writer
277               }
278               else {
279                 format!("let mut _rr{0}_ = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; let mut {0} = parser.lbx({3},_rr{0}_); ",&poppedlab,&eindex,symtype,k-1)
280               }
281             } // not bumpast
282           },
283           2 => {
284             format!("let ref mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",poppedlab,&eindex,symtype)
285           },
286           _ => {
287             format!("let mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",poppedlab,&eindex,symtype)
288           },
289        };
290        write!(fd,"{}",&stat)?;
291        k-=1;
292      } // while k>0
293      // form args
294      let mut aargs = String::new();
295      k = actualargs.len();
296      while k>0
297      {
298        aargs.push(',');
299        aargs.push_str(&actualargs[k-1]);
300        k-=1;
301      }
302      /// formed actual arguments
303    // write code to call action function, then convert to RetTypeEnum
304      let lhsi = self.Gmr.Symhash.get(&self.Gmr.Rules[ri].lhs.sym).expect("GRAMMAR REPRESENTATION CORRUPTED");
305      let fnname = format!("_rrsemaction_{}_",ri);
306      let typei = &self.Gmr.Symbols[*lhsi].rusttype;
307      let enumindex = self.Gmr.enumhash.get(typei).expect("FATAL ERROR: TYPE {typei} NOT USED IN GRAMMAR");
308      write!(fd," RetTypeEnum::Enumvariant_{}({}(parser{})) }};\n",enumindex,&fnname,aargs)?;
309      write!(fd," parser1.Rules.push(rule);\n")?;
310    }// write each rule action
311    
312    
313    write!(fd," parser1.Errsym = \"{}\";\n",&self.Gmr.Errsym)?;
314    // resynch vector
315    for s in &self.Gmr.Resynch {write!(fd," parser1.resynch.insert(\"{}\");\n",s)?;}
316
317    // generate code to load RSM from TABLE
318    write!(fd,"\n for i in 0..{} {{\n",totalsize)?;
319    write!(fd,"   let symi = ((TABLE[i] & 0x0000ffff00000000) >> 32) as usize;\n")?;
320    write!(fd,"   let sti = ((TABLE[i] & 0xffff000000000000) >> 48) as usize;\n")?;
321    write!(fd,"   parser1.RSM[sti].insert(SYMBOLS[symi],decode_action(TABLE[i]));\n }}\n\n")?;
322//    write!(fd,"\n for i in 0..{} {{for k in 0..{} {{\n",rows,cols)?;
323//    write!(fd,"   parser1.RSM[i].insert(SYMBOLS[k],decode_action(TABLE[i*{}+k]));\n }}}}\n",cols)?;
324    write!(fd," for s in SYMBOLS {{ parser1.Symset.insert(s); }}\n\n")?;
325
326    /* // took out 0.2.97
327    if self.Gmr.transform_function.len()>0 {
328      write!(fd," parser1.set_transform_token({});\n\n",&self.Gmr.transform_function)?;
329    }
330    */
331    
332    write!(fd," load_extras(&mut parser1);\n")?;
333    write!(fd," return parser1;\n")?;
334    write!(fd,"}} //make_parser\n\n")?;
335
336/* // took out 0.2.97
337    // write special value extraction functions for transform_function
338    //if self.Gmr.transform_function.len()>0 {
339      let mut already:HashSet<&str> = HashSet::new();
340      for sym in &self.Gmr.Symbols
341      {
342         if sym.terminal && &sym.rusttype!="()" && !already.contains(&sym.rusttype[..]) && &sym.sym!="_WILDCARD_TOKEN_" {
343//println!("processing for {}, type {}",&sym.sym, &sym.rusttype);         
344            already.insert(&sym.rusttype);
345            let ei = self.Gmr.enumhash.get(&sym.rusttype).expect("GRAMMAR CORRUPTED");
346//            let ltm = &self.Gmr.lifetime;
347//            let refform = format!("&{} ",ltm);
348            let needclone = ".clone()"; //if sym.rusttype.starts_with("&") {""} else {".clone()"};
349            
350            write!(fd," fn extract_value_{}{}(x:&RetTypeEnum{}) -> {} {{
351    if let RetTypeEnum::Enumvariant_{}(_v_) = x {{_v_{}}} else {{<{}>::default()}}
352 }}\n",&sym.sym,&ltopt,&ltopt,&sym.rusttype,ei,needclone,&sym.rusttype)?;
353            write!(fd," fn encode_value_{}{}(x:{}) -> RetTypeEnum{} {{ RetTypeEnum::Enumvariant_{}(x) }}\n",&sym.sym,&ltopt,&sym.rusttype,&ltopt,ei)?;
354         }
355      }//for each terminal symbol
356    //}//transform-related
357*/
358
359    //if !self.Gmr.sametype {  // checked at first
360
361      ////// WRITE parse_with and parse_train_with
362      let lexerlt = if has_lt {&ltopt} else {"<'t>"};
363      let lexername = format!("{}lexer{}",&self.Gmr.name,lexerlt);
364      let abindex = *self.Gmr.enumhash.get(absyn).unwrap();
365      write!(fd,"pub fn parse_with{}(parser:&mut ZCParser<RetTypeEnum{},{}>, lexer:&mut {}) -> Result<{},{}>\n{{\n",lexerlt,&ltopt,extype,&lexername,absyn,absyn)?;
366      if self.Gmr.bumpast {
367        write!(fd,"  if lexer.bump.is_some() {{parser.exstate.set(lexer.bump.unwrap());}}\n")?;
368      }//bump
369
370      write!(fd,"  lexer.shared_state = Rc::clone(&parser.shared_state);\n")?;
371      write!(fd,"  if let RetTypeEnum::Enumvariant_{}(_xres_) = parser.parse(lexer) {{\n",abindex)?;
372      write!(fd,"     if !parser.error_occurred() {{Ok(_xres_)}} else {{Err(_xres_)}}\n  }} ")?;
373      write!(fd,"else {{ Err(<{}>::default())}}\n}}//parse_with public function\n",absyn)?;
374      // training version
375      write!(fd,"\npub fn parse_train_with{}(parser:&mut ZCParser<RetTypeEnum{},{}>, lexer:&mut {}, parserpath:&str) -> Result<{},{}>\n{{\n",lexerlt,&ltopt,extype,&lexername,absyn,absyn)?;
376      if self.Gmr.bumpast {
377        write!(fd,"  if lexer.bump.is_some() {{parser.exstate.set(lexer.bump.unwrap());}}\n")?;
378      }//bump
379      write!(fd,"  lexer.shared_state = Rc::clone(&parser.shared_state);\n")?;
380      write!(fd,"  if let RetTypeEnum::Enumvariant_{}(_xres_) = parser.parse_train(lexer,parserpath) {{\n",abindex)?;
381      write!(fd,"     if !parser.error_occurred() {{Ok(_xres_)}} else {{Err(_xres_)}}\n  }} ")?;
382      write!(fd,"else {{ Err(<{}>::default())}}\n}}//parse_train_with public function\n",absyn)?;
383
384
385      ////// WRITE ENUM
386      self.Gmr.gen_enum(&mut fd)?;
387    // }// !sametype
388    
389    ////// WRITE LEXER
390    if self.Gmr.genlex { self.Gmr.genlexer(&mut fd,"from_raw")?; }
391
392    ////// Augment!
393    write!(fd,"fn load_extras{}(parser:&mut ZCParser<RetTypeEnum{},{}>)\n{{\n",&ltopt,&ltopt,extype)?;
394    write!(fd,"}}//end of load_extras: don't change this line as it affects augmentation\n")?;
395    Ok(())
396  }//writelrsdparser
397
398
399
400/////////////////////////////////////////////////////////////////////////////
401///////////////////////////////////////////// for new base_parser
402
403  pub fn writelrsdbaseparser(&mut self, filename:&str)->Result<(),std::io::Error>
404  {
405    let mut absyn = &self.Gmr.Absyntype;
406    let mut extype = &self.Gmr.Externtype;
407    let lifetime = &self.Gmr.lifetime;
408    let has_lt = lifetime.len()>0 && (absyn.contains(lifetime) || extype.contains(lifetime));
409    let ltopt = if has_lt {format!("<{}>",lifetime)} else {String::from("")};
410    let rlen = self.Gmr.Rules.len();
411
412    let LBC = if self.Gmr.bumpast {"LC"} else {"LBox"};
413    
414    let bltref = if self.Gmr.bumpast {format!("&{} ",&self.Gmr.lifetime)} else {String::new()};
415
416      let lexerlt = if has_lt {&ltopt} else {"<'t>"};
417      let lexerlife = if has_lt {lifetime} else {"'t"};
418      let lexername = format!("{}lexer{}",&self.Gmr.name,lexerlt);
419      let abindex = *self.Gmr.enumhash.get(absyn).unwrap();
420    
421    // generate action fn's from strings stored in gen-time grammar
422    // these are the _semaction_rule_ri functions.  move function to
423    // pop stack to the closures attached to each runtime rule.
424    // make this a pure function on types defined.
425    let mut actions:Vec<String> = Vec::with_capacity(rlen);
426    
427    for ri in 0..rlen
428    {
429      let lhs = &self.Gmr.Rules[ri].lhs.sym;
430      let lhsi = self.Gmr.Rules[ri].lhs.index; //self.Gmr.Symhash.get(lhs).expect("GRAMMAR REPRESENTATION CORRUPTED");
431      let rettype = &self.Gmr.Symbols[lhsi].rusttype; // return type=rusttype
432      let ltoptr = if has_lt || (lifetime.len()>0 && rettype.contains(lifetime))
433        {format!("<{}>",lifetime)} else {String::from("")};
434
435// first arg to semaction is parser itself. - this is a must.
436      let mut fndef = format!("\nfn _rrsemaction_{}_<{},TT:Tokenizer<{},RetTypeEnum{}>>(parser:&mut BaseParser<{},RetTypeEnum{},{},TT>",ri,lexerlife,lexerlife,&ltopt,lexerlife,&ltopt,extype);
437      // now for other arguments
438      // inside actions, can still bind labels to patterns
439      let mut patternactions = String::new();                  
440      for k in 0..self.Gmr.Rules[ri].rhs.len() {
441        let symk= &self.Gmr.Rules[ri].rhs[k]; 
442        let symktype = &self.Gmr.Symbols[symk.index].rusttype;
443        let(labelkind,label) = decode_label(&symk.label,k);
444        if labelkind>1 {
445          if self.Gmr.tracelev>0 { println!("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
446          else {self.Gmr.genlog.push_str("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
447        }
448        let mut fargk = match labelkind {
449          0 => {format!(", mut {}:{}",&label,symktype)},
450          //1 => {format!(", mut {}:{}{}<{}>",&label,&bltref,LBC,symktype)},
451          1 => {
452            if self.Gmr.bumpast {
453              format!(", mut {}:{}{}<{}>",&label,&bltref,LBC,symktype)
454            }
455            else {
456              if self.Gmr.Rules[ri].autogenerated { // if auto-generated type
457                format!(", mut {}:{}",&label,symktype) //.lc inserted by writer
458              }
459              else {
460                //format!(", mut {}:{}LC<{}>",&label,&bltref,symktype)
461                format!(", mut {}:LBox<{}>",&label,symktype)
462              }
463            }// not bumpast
464          },
465          // need to distinguish LC and LBox here!
466          2 => {   // label is a e@..@ pattern
467            let ati = symk.label.find('@').unwrap();
468            patternactions.push_str(&format!("let {} = {}; ",
469                                     &symk.label[ati+1..],&label));
470            format!(", {}:&mut {}",&label,symktype)
471          },
472          3 => {   // label is a [e]@..@ pattern
473            let ati = symk.label.find('@').unwrap();          
474            patternactions.push_str(&format!("let {} = &mut *{}; ",
475                                     &symk.label[ati+1..],&label));
476            // this probably won't be consistent
477            if self.Gmr.bumpast || !self.Gmr.Rules[ri].autogenerated {
478              format!(", mut {}:{}{}<{}>",&label,&bltref,LBC,symktype)
479            }
480            else {
481              format!(", mut {}:{}",&label,symktype)
482            }
483          },
484          _ => {
485            let ati = symk.label.find('@').unwrap();          
486            patternactions.push_str(&format!("let {} = _item{}_; ",
487                                     &symk.label[ati+1..],k));
488            format!(", mut _item{}_:{}",k,symktype)
489          },
490        };//match
491        fndef.push_str(&fargk);
492      }// for each symbol on rhs
493      fndef.push_str(&format!(") -> {} {{ ",rettype));
494      let defaultaction = format!("<{}>::default()}}",rettype);
495      let mut semaction = &self.Gmr.Rules[ri].action; //string that ends w/rbr
496      if semaction.len()>1  {fndef.push_str(&patternactions);}
497      if semaction.len()<=1 {semaction = &defaultaction;}
498      fndef.push_str(&semaction); 
499      actions.push(fndef);
500    } //for ri
501
502    ////// write to file, create Ruleaction closures for each rule
503
504    let mut fd = File::create(filename)?;
505    write!(fd,"//Parser generated by rustlr for grammar {}",&self.Gmr.name)?;
506    write!(fd,"\n    
507#![allow(unused_variables)]
508#![allow(non_snake_case)]
509#![allow(non_camel_case_types)]
510#![allow(unused_parens)]
511#![allow(unused_mut)]
512#![allow(unused_imports)]
513#![allow(unused_assignments)]
514#![allow(dead_code)]
515#![allow(unreachable_patterns)]
516#![allow(irrefutable_let_patterns)]
517use std::rc::Rc;
518use std::cell::RefCell;
519extern crate rustlr;
520use rustlr::{{Tokenizer,TerminalToken,BaseParser,BaseProduction,Stateaction,decode_action}};\n")?;
521    if self.Gmr.genlex {
522      write!(fd,"use rustlr::{{StrTokenizer,RawToken,LexSource}};
523use std::collections::{{HashMap,HashSet}};\n")?;
524    }
525
526    write!(fd,"{}\n",&self.Gmr.Extras)?; // use clauses and such
527
528    // write static array of symbols
529    write!(fd,"static SYMBOLS:[&'static str;{}] = [",self.Gmr.Symbols.len())?;
530    for i in 0..self.Gmr.Symbols.len()-1
531    {
532      write!(fd,"\"{}\",",&self.Gmr.Symbols[i].sym)?;
533    }
534    write!(fd,"\"{}\"];\n\n",&self.Gmr.Symbols[self.Gmr.Symbols.len()-1].sym)?;
535    // position of symbols must be inline with self.Gmr.Symhash
536
537    let mut totalsize = 0;
538    for i in 0..self.FSM.len() { totalsize+=self.FSM[i].len(); }
539    if self.Gmr.tracelev>1 {println!("{} total state table entries",totalsize);}
540
541    let mut tfdopt = None;
542    if self.Gmr.tablefile.len()>0 {
543      write!(fd,"use std::fs::File;\n")?;
544      write!(fd,"use std::io::prelude::*;\n")?;
545      write!(fd,"use std::path::Path;\n")?;
546      write!(fd,"use std::io::Read;\n")?;
547      let mut tfd1 = File::create(&self.Gmr.tablefile)?;
548      tfdopt = Some(tfd1);    
549    }
550    else {     // record table entries in a static array
551      write!(fd,"static TABLE:[u64;{}] = [",totalsize)?;
552    }
553
554    // generate table to represent FSM
555    let mut encode:u64 = 0;
556    for i in 0..self.FSM.len() // for each state index i
557    {
558      let row = &self.FSM[i];        
559      for key in row.keys()
560      { // see function decode for opposite translation
561        let k = *key; //*self.Gmr.Symhash.get(key).unwrap(); // index of symbol
562        encode = ((i as u64) << 48) + ((k as u64) << 32);
563        match row.get(key) {
564          Some(Shift(statei)) => { encode += (*statei as u64) << 16; },
565          Some(Gotonext(statei)) => { encode += ((*statei as u64) << 16)+1; },
566          Some(Reduce(rulei)) => { encode += ((*rulei as u64) << 16)+2; },
567          Some(Accept) => {encode += 3; },
568          _ => {encode += 4; },  // 4 indicates Error
569        }//match
570        tfdopt
571	.as_mut()
572	.map_or_else(||{write!(fd,"{},",encode)},
573                     |tfd|{tfd.write_all(&encode.to_be_bytes())})?;
574      } //for symbol index k
575    }//for each state index i
576    if self.Gmr.tablefile.len()==0 { write!(fd,"];\n\n")?; }
577
578    // write action functions fn _semaction_rule_{} ..
579    for deffn in &actions { write!(fd,"{}\n",deffn)?; }
580
581    // must know what absyn type is when generating code.
582    write!(fd,"\npub fn make_parser<{},TT:Tokenizer<{},RetTypeEnum{}>>(tk:TT) -> BaseParser<{},RetTypeEnum{},{},TT>",lexerlife,lexerlife,&ltopt,lexerlife,&ltopt,extype)?;
583        
584    write!(fd,"\n{{\n")?;
585    write!(fd," let mut parser1:BaseParser<{},RetTypeEnum{},{},TT> = BaseParser::new({},{},tk);\n",lexerlife,&ltopt,extype,self.Gmr.Rules.len(),self.FSM.len())?;
586    // generate rules and Ruleaction delegates to call action fns, cast
587    write!(fd," let mut rule;\n")?; // dummy for init
588    for ri in 0..self.Gmr.Rules.len() 
589    {
590      let lhs = &self.Gmr.Rules[ri].lhs.sym;
591      let lhsi = self.Gmr.Rules[ri].lhs.index; 
592      let rettype = &self.Gmr.Symbols[lhsi].rusttype; // return type=rusttype
593      write!(fd," rule = BaseProduction::<{},RetTypeEnum{},{},TT>::new_skeleton(\"{}\");\n",lexerlife,&ltopt,extype,self.Gmr.Rules[ri].lhs.sym)?;
594      write!(fd," rule.Ruleaction = |parser|{{ ")?;
595
596    // write code to pop stack, decode labels into args. /////////
597      let mut k = self.Gmr.Rules[ri].rhs.len(); //k=len of rhs of rule ri
598      //form if-let labels and patterns as we go...
599      let mut actualargs = Vec::new();
600      while k>0 // k is length of right-hand side, use k-1
601      {
602        let gsym = &self.Gmr.Rules[ri].rhs[k-1]; // rhs syms right to left
603        let (lbtype,poppedlab) = decode_label(&gsym.label,k-1);
604        if lbtype>1 {
605          if self.Gmr.tracelev>0 { println!("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
606          else {self.Gmr.genlog.push_str("\nWARNING: @..@ PATTERNS MUST BE IRREFUTABLE WITH THE -lrsd OPTION\n\n");}
607        }
608        let symtype=&self.Gmr.Symbols[gsym.index].rusttype;
609        let emsg = format!("FATAL ERROR: '{}' IS NOT A TYPE IN THIS GRAMMAR. DID YOU INTEND TO USE THE -auto OPTION TO GENERATE TYPES?",&symtype);
610        let eindex = self.Gmr.enumhash.get(symtype).expect(&emsg);
611        actualargs.push(format!("{}",&poppedlab));           
612        let stat = match lbtype {
613           0  => {
614             format!("let mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",&poppedlab,&eindex,symtype)
615           },
616           1  |  3 => {
617             if self.Gmr.bumpast {
618               format!("let mut _rr{0}_ = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; let mut {0} = parser.exstate.make(parser.lc({3},_rr{0}_)); ",&poppedlab,&eindex,symtype,k-1)
619             } else {
620               if self.Gmr.Rules[ri].autogenerated { // auto-generated type
621                 format!("let mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",&poppedlab,&eindex,symtype) // lc/lbx determined by ast_writer
622               }
623               else {
624                 format!("let mut _rr{0}_ = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; let mut {0} = parser.lbx({3},_rr{0}_); ",&poppedlab,&eindex,symtype,k-1)
625               }
626             } // not bumpast
627           },
628           2 => {
629             format!("let ref mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",poppedlab,&eindex,symtype)
630           },
631           _ => {
632             format!("let mut {0} = if let RetTypeEnum::Enumvariant_{1}(_rr_{1})=parser.popstack().value {{ _rr_{1} }} else {{<{2}>::default()}}; ",poppedlab,&eindex,symtype)
633           },
634        };
635        write!(fd,"{}",&stat)?;
636        k-=1;
637      } // while k>0
638      // form args
639      let mut aargs = String::new();
640      k = actualargs.len();
641      while k>0
642      {
643        aargs.push(',');
644        aargs.push_str(&actualargs[k-1]);
645        k-=1;
646      }
647      /// formed actual arguments
648    // write code to call action function, then convert to RetTypeEnum
649      let lhsi = self.Gmr.Symhash.get(&self.Gmr.Rules[ri].lhs.sym).expect("GRAMMAR REPRESENTATION CORRUPTED");
650      let fnname = format!("_rrsemaction_{}_",ri);
651      let typei = &self.Gmr.Symbols[*lhsi].rusttype;
652      let enumindex = self.Gmr.enumhash.get(typei).expect("FATAL ERROR: TYPE {typei} NOT USED IN GRAMMAR");
653      write!(fd," RetTypeEnum::Enumvariant_{}({}(parser{})) }};\n",enumindex,&fnname,aargs)?;
654      write!(fd," parser1.Rules.push(rule);\n")?;
655    }// write each rule action
656    
657    
658    write!(fd," parser1.Errsym = \"{}\";\n",&self.Gmr.Errsym)?;
659    // resynch vector
660    for s in &self.Gmr.Resynch {write!(fd," parser1.resynch.insert(\"{}\");\n",s)?;}
661
662  if self.Gmr.tablefile.len()==0 {
663
664    // generate code to load RSM from TABLE
665    write!(fd,"\n for i in 0..{} {{\n",totalsize)?;
666    write!(fd,"   let symi = ((TABLE[i] & 0x0000ffff00000000) >> 32) as usize;\n")?;
667    write!(fd,"   let sti = ((TABLE[i] & 0xffff000000000000) >> 48) as usize;\n")?;
668    write!(fd,"   parser1.RSM[sti].insert(SYMBOLS[symi],decode_action(TABLE[i]));\n }}\n\n")?;
669   }
670   else { // load from fsm binary file (0.6.1)
671      let mut fsmfile = &self.Gmr.tablefile[..];
672      if let Some(pos) = self.Gmr.tablefile.rfind("/")
673                         .or(self.Gmr.tablefile.rfind('\\')) {
674         fsmfile = &self.Gmr.tablefile[pos+1..];
675      }
676      write!(fd,"let mut tfd = File::open(r\"./src/{}\").or(File::open(r\".\\src\\{}\")).or(File::open(r\"{}\")).expect(r\"Parse Table File {} Not Found\");\n",fsmfile, fsmfile, fsmfile,fsmfile)?;
677      write!(fd,"\n let mut tbuf = [0u8;8];")?;
678      write!(fd,"\n for i in 0..{} {{\n",totalsize)?;
679      write!(fd,"   tfd.read_exact(&mut tbuf).expect(\"File Read Failed\");\n")?;
680      write!(fd,"   let tabi = u64::from_be_bytes(tbuf);\n")?;
681      write!(fd,"   let symi = ((tabi & 0x0000ffff00000000) >> 32) as usize;\n")?;
682      write!(fd,"   let sti = ((tabi & 0xffff000000000000) >> 48) as usize;\n")?;
683      write!(fd,"   parser1.RSM[sti].insert(SYMBOLS[symi],decode_action(tabi));\n }}\n\n")?;
684   } // load fsm from file
685
686
687    write!(fd," for s in SYMBOLS {{ parser1.Symset.insert(s); }}\n\n")?;
688
689    /* // took out 0.2.97
690    if self.Gmr.transform_function.len()>0 {
691      write!(fd," parser1.set_transform_token({});\n\n",&self.Gmr.transform_function)?;
692    }
693    */
694    
695    write!(fd," load_extras(&mut parser1);\n")?;
696    write!(fd," return parser1;\n")?;
697    write!(fd,"}} //make_parser\n\n")?;
698
699      ////// WRITE parse_with and parse_train_with
700
701      write!(fd,"pub fn parse_with{}(parser:&mut BaseParser<{},RetTypeEnum{},{},{}>) -> Result<{},{}>\n{{\n",lexerlt,lexerlife,&ltopt,extype,&lexername,absyn,absyn)?;
702
703      if self.Gmr.bumpast {
704        write!(fd,"  if lexer.bump.is_some() {{parser.exstate.set(lexer.bump.unwrap());}}\n")?;
705      }//bump
706
707      //write!(fd,"  lexer.shared_state = Rc::clone(&parser.shared_state);\n")?;
708      write!(fd,"  parser.tokenizer.shared_state = Rc::clone(&parser.shared_state);\n")?;
709
710      write!(fd,"  if let RetTypeEnum::Enumvariant_{}(_xres_) = parser.parse() {{\n",abindex)?;
711      write!(fd,"     if !parser.error_occurred() {{Ok(_xres_)}} else {{Err(_xres_)}}\n  }} ")?;
712      write!(fd,"else {{ Err(<{}>::default())}}\n}}//parse_with public function\n",absyn)?;
713      // training version
714      write!(fd,"\npub fn parse_train_with{}(parser:&mut BaseParser<{},RetTypeEnum{},{},{}>, parserpath:&str) -> Result<{},{}>\n{{\n",lexerlt,lexerlife,&ltopt,extype,&lexername,absyn,absyn)?;
715
716      if self.Gmr.bumpast {
717        write!(fd,"  if parser.tokenizer.bump.is_some() {{let bb = parser.tokenizer.bump.unwrap(); parser.exstate.set(bb);}}\n")?;
718      }//bump
719      write!(fd,"  parser.tokenizer.shared_state = Rc::clone(&parser.shared_state);\n")?;
720
721      write!(fd,"  if let RetTypeEnum::Enumvariant_{}(_xres_) = parser.parse_train(parserpath) {{\n",abindex)?;
722      write!(fd,"     if !parser.error_occurred() {{Ok(_xres_)}} else {{Err(_xres_)}}\n  }} ")?;
723      write!(fd,"else {{ Err(<{}>::default())}}\n}}//parse_train_with public function\n",absyn)?;
724
725
726      ////// WRITE ENUM
727      self.Gmr.gen_enum(&mut fd)?;
728    // }// !sametype
729    
730    ////// WRITE LEXER
731    if self.Gmr.genlex { self.Gmr.genlexer(&mut fd,"from_raw")?; }
732
733    ////// Augment!
734    write!(fd,"fn load_extras<{},TT:Tokenizer<{},RetTypeEnum{}>>(parser:&mut BaseParser<{},RetTypeEnum{},{},TT>)\n{{\n",lexerlife,lexerlife,&ltopt,lexerlife,&ltopt,extype)?;
735    write!(fd,"}}//end of load_extras: don't change this line as it affects augmentation\n")?;
736    Ok(())
737  }//writelrsdbaseparser
738
739}//impl statemachine
740