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::collections::{HashMap,HashSet};
11use std::io::{self,Read,Write,BufReader,BufRead};
13use std::fs::File;
14use std::io::prelude::*;
15use std::path::Path;
16use crate::{Grammar,is_alphanum,emptybox,checkboxexp};
17
18type METAASTTYPE = HashMap<usize,(bool,bool,i32,String,Vec<(usize,String,bool,String)>)>;
33
34impl Grammar
37{
38 fn prepare(&mut self) -> String
39 {
40 self.reachability_types();
43
44 let mut ntcx = self.ntcxmax+1;
47 for nt in self.Rulesfor.keys() { if self.Symbols[*nt].rusttype.len()==0 { let reach = self.Reachable.get(nt).unwrap();
52let mut needlt = false;
56 if self.lifetime.len()>0 {
57 for ti in self.haslt_base.iter() {
58 if reach.contains(ti) {needlt = true; break;}
59 }
60 }if needlt {
62 self.Symbols[*nt].rusttype = format!("{}<{}>",&self.Symbols[*nt].sym,&self.lifetime);
63 } else {
64 self.Symbols[*nt].rusttype = self.Symbols[*nt].sym.clone();
65 }self.enumhash.insert(self.Symbols[*nt].rusttype.clone(),ntcx);
67 ntcx+=1;
68 }}let mut toextend = HashMap::new(); let mut extendtargets = HashSet::new();
74
75 for nt in self.Rulesfor.keys() {
77 let addtoextend = self.Symbols[*nt].rusttype.starts_with(':');
80 let mut addtosymhash = false; let mut limit = self.Symbols.len()+1;
82 let mut indirect = true;
83 while (indirect || self.Symbols[*nt].rusttype.contains('@')) && limit>0
84 {
85 indirect = false;
86 addtosymhash = true;
87 let stype = &self.Symbols[*nt].rusttype; let mut symtocopy = ""; let (mut start,mut end) = (0,stype.len());
90 if stype.starts_with(':') || stype.starts_with('@') {
91 symtocopy = stype[1..].trim();
92 } else if let Some(pos1)=stype.find("<@") {
93 if let Some(pos2)=stype[pos1+2..].find('>') {
94 symtocopy = &stype[pos1+2..pos1+2+pos2];
95 start = pos1+1; end = pos1+2+pos2;
96 }
97 } else if let Some(pos1)=stype.find("<:") {
98 if let Some(pos2)=stype[pos1+2..].find('>') {
99 symtocopy = stype[pos1+2..pos1+2+pos2].trim();
100 start = pos1+1; end = pos1+2+pos2;
101 indirect = true; }
103 }
104 if symtocopy.len()>0 {
105 let symi = *self.Symhash.get(symtocopy).unwrap();
106 let mut replacetype = self.Symbols[symi].rusttype.clone();
107 if replacetype.starts_with(':') {indirect = true;}
108 else if addtoextend {
109 toextend.insert(*nt,symi);
110extendtargets.insert(symi);
112 }
113
114 let mut newtype = stype.clone();
117 newtype.replace_range(start..end,&replacetype);
118 self.Symbols[*nt].rusttype = newtype;
119 } limit -= 1;
121 }if addtosymhash && limit>0 {self.enumhash.insert(self.Symbols[*nt].rusttype.clone(),ntcx); ntcx+=1;}
123 else if limit==0 {
124 let msg = format!("CIRCULARITY DETECTED IN PROCESSING TYPE DEPENDENCIES (type {} for nonterminal {}). THIS TYPE WILL BE RESET AND REGENERATED\n",&self.Symbols[*nt].rusttype,&self.Symbols[*nt].sym);
125 if self.tracelev>0 {eprint!("{}",msg);}
126 else { self.genlog.push_str(&msg); }
127 self.Symbols[*nt].rusttype = String::new();
128 }
129 }self.ntcxmax = ntcx;
133 let mut flattentypes = self.flattentypes.clone();
141 for a in self.flattentypes.iter() {
142 let mut acanflatten = true;
143 if !flattentypes.contains(a) {continue;}
144 for b in self.flattentypes.iter() {
145 if a!=b && flattentypes.contains(b) {
146 let areach = self.Reachable.get(a).unwrap();
147 let breach = self.Reachable.get(b).unwrap();
148 if areach.contains(b) && breach.contains(a) {
149 flattentypes.remove(a); flattentypes.remove(b);
150 let msg = format!("WARNING: MUTUALLY RECURSIVE TYPES {} AND {} CANNOT FLATTEN INTO EACHOTHER\n",&self.Symbols[*a].sym,&self.Symbols[*b].sym);
151 if self.tracelev>0 {eprint!("{}",msg);}
152 else {self.genlog.push_str(&msg);}
153 }
154 }
155 }
156 }let mut structasts = METAASTTYPE::new();
159 for (nt,NTrules) in self.Rulesfor.iter() { if NTrules.len()!=1 || extendtargets.contains(nt) || toextend.contains_key(nt) { continue;}
161 let sri = *NTrules.iter().next().unwrap();
162 if self.Rules[sri].lhs.label.len()>0 {continue;}
163 let NT = &self.Symbols[*nt].sym;
164 let lhsymtype = self.Symbols[*nt].rusttype.clone();
165 if !lhsymtype.starts_with(NT) {continue;}
166 let mut canflatten = true;
167 let mut simplestruct = true;
168 for rs in &self.Rules[sri].rhs {
169 if rs.label.len()>0 && !rs.label.starts_with("_item") && !emptybox(&rs.label)
170 { simplestruct = false; break; }
171 } let ntsym = &self.Symbols[*nt];
173 let mut vfields = Vec::new(); let mut rhsi = 0; let mut passthru:i32 = -1; for rsym in self.Rules[sri].rhs.iter_mut() {
177 let expectedlabel = format!("_item{}_",&rhsi);
178 let alreadyislbxlab = rsym.label.len()>1 && rsym.label.starts_with('[') && rsym.label.ends_with(']');
179 let itemlabel = if rsym.label.len()>0 && &rsym.label!=&expectedlabel && !rsym.label.starts_with('@') {
180 passthru=-2; checkboxexp(&rsym.label,&expectedlabel).to_owned()
182 } else {expectedlabel};
183 if rsym.terminal && rsym.precedence!=0 { passthru = -2; }
184 let rsymtype = &self.Symbols[rsym.index].rusttype;
185 let lhsreachable = match self.Reachable.get(&rsym.index) {
187 None => false,
188 Some(rset) => rset.contains(nt),
189 };
190 let needrecursion = lhsreachable && !nonlbxtype(rsymtype);
191 if alreadyislbxlab || needrecursion {
192 if rsymtype==&lhsymtype && passthru==-1 {passthru=rhsi as i32;}
193 else {passthru = -2;}
194 if !self.bumpast && needrecursion {
195 vfields.push((rhsi,itemlabel.clone(),alreadyislbxlab,format!("LBox<{}>",rsymtype)));
196 }
197 else if alreadyislbxlab && !nonlctype(rsymtype) {
198 vfields.push((rhsi,itemlabel.clone(),alreadyislbxlab,format!("LC<{}>",rsymtype)));
199 }
200 }else if rsymtype!="()" || (rsym.label.len()>0 && !rsym.label.starts_with("_item")) { vfields.push((rhsi,itemlabel.clone(),alreadyislbxlab,rsymtype.to_owned()));
203 if rsymtype==&lhsymtype && passthru==-1 {passthru=rhsi as i32;}
204 else {passthru = -2;}
205 } rhsi+=1;
207 } structasts.insert(*nt,(simplestruct,canflatten,passthru,String::new(),vfields));
209 }let mut newsa = HashMap::with_capacity(structasts.len());
214 for (nt,(simplestruct,canflatten,passthru,_,vecfields)) in structasts.iter() {
215 let sri = *self.Rulesfor.get(nt).unwrap().iter().next().unwrap(); let NT = &self.Symbols[*nt].sym;
217 let lhsymtype = self.Symbols[*nt].rusttype.clone();
218 let ntsym = &self.Symbols[*nt];
219
220 let mut havedefault;
221 if let Some(defaultstruct) = self.defaults.get(nt) {
222 havedefault = format!("impl Default for {} {{ fn default()->Self {{ {} }} }}\n#[derive(Debug)]\n",&ntsym.rusttype, defaultstruct);
223 }
224 else {
225 havedefault = String::from("#[derive(Default,Debug)]\n");
226 }
227
228
229 let mut SAST = if !simplestruct {format!("{}pub struct {} {{\n",havedefault,&ntsym.rusttype)}
230 else {format!("{}pub struct {}(",havedefault,&ntsym.rusttype)}; let mut fields = String::new(); let mut vfields = Vec::new(); let mut SACTION = if *simplestruct {format!("{}(",NT)}
235 else {format!("{} {{",NT)};
236
237 let mut viadjust:i32 = 0; for (rhsi,itemlabel,alreadylbx,rsymtype) in vecfields { let rhssymi = self.Rules[sri].rhs[*rhsi].index;
240 if rhssymi==*nt {
241 self.logeprint(&format!("WARNING: TYPE {} CANNOT FLATTEN INTO ITSELF\n",&self.Rules[sri].rhs[*rhsi].sym));
242 }
243 let mut flattened = false;
244 if rhssymi!=*nt && flattentypes.contains(&rhssymi) { match structasts.get(&rhssymi) {
246 Some((simp,true,pthr,_,flatfields)) => { if *pthr<0 && (!simplestruct||*simp) && !self.Rules[sri].rhs[*rhsi].label.starts_with('[') {
248 flattened=true;
249 let mut fi = 0;
250 for (frhsi,flab,albx,ftype) in flatfields {
251 let newlab = format!("{}_{}",itemlabel,flab);
252 let newactionlab = if *simp {format!("{}.{}",itemlabel,fi)}
253 else {format!("{}.{}",itemlabel,flab)};
254 let newindex = rhsi+(viadjust as usize)+fi;
255 if *simplestruct {
256 fields.push_str("pub ");
257 fields.push_str(ftype); fields.push(',');
258 } else {
259 fields.push_str(&format!(" pub {}:{},\n",&newlab,ftype));
260 }
261 let islbxtype = ftype.starts_with("LBox<");
262 if *simplestruct {
263 SACTION.push_str(&newactionlab); SACTION.push(',');
264 }
265 else {
271 SACTION.push_str(&format!("{}:{}, ",&newlab,&newactionlab));
272
273 }
274 vfields.push((newindex,newlab,*albx,ftype.to_owned()));
280 fi+=1;
281 }}},
285 aaa => {
286 }, }}if !flattened {
291 let islbxtype = rsymtype.starts_with("LBox<");
292 let islctype = rsymtype.starts_with("LC<");
293 if *simplestruct {
294 fields.push_str("pub ");
295 fields.push_str(rsymtype); fields.push(',');
296 if islbxtype {
297 SACTION.push_str(&format!("parser.lbx({},{}),",rhsi+(viadjust as usize),itemlabel));
298 }
299 else if islctype {
300 SACTION.push_str(&format!("parser.lc({},{}),",rhsi+(viadjust as usize),itemlabel));
301 }
302 else { SACTION.push_str(itemlabel); SACTION.push(','); }
303 } else { fields.push_str(&format!(" pub {}:{},\n",itemlabel,rsymtype));
305 if islctype {
312 SACTION.push_str(&format!("{}:parser.lc({},{}), ",itemlabel,rhsi+(viadjust as usize),itemlabel));
313 }
314 else if islbxtype {
315 SACTION.push_str(&format!("{}:parser.lbx({},{}), ",itemlabel,rhsi+(viadjust as usize),itemlabel));
316 }
317 else {
318 SACTION.push_str(&format!("{}:{}, ",itemlabel,itemlabel));
319 }
320 }vfields.push((rhsi+(viadjust as usize),itemlabel.to_owned(),*alreadylbx,rsymtype.to_owned()));
322 }}if *simplestruct {
326 fields.push_str(");\n\n"); SACTION.push(')');
327 } else {
328 fields.push_str("}\n\n"); SACTION.push('}');
329 }
330 SACTION.push_str(" }");
331 let mut actbase = augment_action(&self.Rules[sri].action);
332 if !actbase.ends_with('}') && *passthru>=0 {
333 self.Rules[sri].action = format!("{} _item{}_ }}",&actbase,passthru);
334} else if !actbase.ends_with('}') {
336 self.Rules[sri].action = format!("{} {}",&actbase,&SACTION);
337 SAST.push_str(&fields);
338 self.Rules[sri].autogenerated = true;
339 }
340 else {SAST.push_str(&fields);}
341 newsa.insert(*nt,(*simplestruct,*canflatten,*passthru,SAST,vfields));
342 }structasts = newsa;
344
345
346let mut enumasts:HashMap<usize,String> = HashMap::new();
350 let mut ASTS = String::from("\n"); let ltopt = if self.lifetime.len()>0 {format!("<{}>",&self.lifetime)}
353 else {String::new()};
354 let mut groupvariants:HashMap<usize,HashSet<String>> = HashMap::new();
356
357 for (nt,NTrules) in self.Rulesfor.iter() {
360 if structasts.contains_key(nt) {continue;}
361 let nti = *nt;
362 let mut ntsym = &self.Symbols[nti];
363 let willextend = toextend.contains_key(nt);
364 let mut AST = if willextend {String::new()}
366 else {format!("#[derive(Debug)]/*enum*/\npub enum {} {{\n",&ntsym.rusttype)};
367 let NT = &self.Symbols[nti].sym;
368 let mut targetnt = nti;
369 if let Some(ntd) = toextend.get(nt) { targetnt = *ntd;}
370 let groupenums = groupvariants.entry(targetnt).or_default();
372 for ri in NTrules {
377 let mut nolhslabel=false;
378 let mut groupoper = ""; if self.Rules[*ri].lhs.label.len()==0 { nolhslabel = true;
382 let mut lhslab = format!("{}_{}",NT,ri); if self.vargroupnames.len()>0 {
386 let enti = *toextend.get(&nti).unwrap_or(&nti);
387 for rsym in self.Rules[*ri].rhs.iter() {
388 if let Some(gnamei) = self.vargroups.get(&(enti,rsym.index)) {
389 if groupoper.len()==0 { lhslab = self.vargroupnames[*gnamei].clone();
391
392 groupoper = self.Nameslex.get(&rsym.index)
393 .unwrap_or(&self.Symbols[rsym.index].sym);
394
395 }
397 }else if let Some(gnamei) = self.vargroups.get(&(usize::MAX,rsym.index)) {
399 if groupoper.len()==0 { lhslab = self.vargroupnames[*gnamei].clone();
401 groupoper = &self.Symbols[rsym.index].sym;
402 }
403 }if rsym.label.len()>0 && !rsym.label.starts_with("_item") {
406 groupoper = ""; lhslab = format!("{}_{}",NT,ri); break;
409 }}} if groupoper.len()==0 && self.Rules[*ri].rhs.len()>0 && self.Rules[*ri].rhs[0].terminal {
414 let symname = &self.Rules[*ri].rhs[0].sym;
415 if is_alphanum(symname) { lhslab = symname.clone();
417 if self.Rules[*ri].rhs.len()>1 { lhslab.push_str(&format!("_{}",ri)); }
418 }
419 } self.Rules[*ri].lhs.label = lhslab;
421 } let lhsi = self.Rules[*ri].lhs.index; let lhsymtype = self.Symbols[lhsi].rusttype.clone();
424 let enumname = &self.Symbols[*toextend.get(nt).unwrap_or(nt)].sym;
425
426 let mut ACTION =format!("{}::{}",enumname,&self.Rules[*ri].lhs.label);
428 let mut enumvar = format!(" {}",&self.Rules[*ri].lhs.label);
430
431
432 let mut tuplevariant = true;
434 for rs in &self.Rules[*ri].rhs {
435 if rs.label.len()>0 && !rs.label.starts_with("_item") && !emptybox(&rs.label)
436 { tuplevariant = false; break; }
437 } let mut nullenum = false; if self.Rules[*ri].rhs.len()>0 { if tuplevariant {
444 enumvar.push('('); ACTION.push('(');
445 if groupoper.len()>0 {
446 if groupenums.contains(&self.Rules[*ri].lhs.label) {
447 nullenum = true;
449 } else {
450 enumvar.push_str("&'static str,");
451 let toinsert = self.Rules[*ri].lhs.label.clone();
452 groupenums.insert(toinsert);
453 }
454 ACTION.push_str(&format!("\"{}\",",groupoper));
455 }
456 } else {
457 enumvar.push('{'); ACTION.push('{');
458 } }let mut rhsi = 0; let mut viadjust = 0;
462 let mut passthru:i32 = -1; for rsym in self.Rules[*ri].rhs.iter_mut()
464 {
465 let expectedlabel = format!("_item{}_",&rhsi);
466 let alreadyislbxlab =
469 rsym.label.len()>1 && rsym.label.starts_with('[') && rsym.label.ends_with(']');
470 let itemlabel = if rsym.label.len()>0 && &rsym.label!=&expectedlabel && !rsym.label.starts_with('@') {
471 passthru=-2; checkboxexp(&rsym.label,&expectedlabel).to_owned()
473 } else {expectedlabel};
474
475 if rsym.terminal && rsym.precedence!=0 { passthru = -2; }
476 let rsymtype = &self.Symbols[rsym.index].rusttype;
478
479 let mut flattened = false;
480 if !rsym.terminal && flattentypes.contains(&rsym.index) {
481 match structasts.get(&rsym.index) {
482 Some((simp,true,pthr,_,flatfields)) => { if *pthr<0 && !rsym.label.starts_with('['){
484 flattened=true;
485 let mut fi = 0;
486 for (frhsi,flab,albx,ftype) in flatfields {
487 let newlab = format!("{}_{}",itemlabel,flab);
488 let newactionlab = if *simp {format!("{}.{}",itemlabel,fi)}
489 else {format!("{}.{}",itemlabel,flab)};
490 let newindex = rhsi+viadjust+fi;
491
492 if tuplevariant {
493 enumvar.push_str(ftype); enumvar.push(',');
494 ACTION.push_str(&newactionlab); ACTION.push(',');
495 } else {
496 enumvar.push_str(&format!("{}:{},",&newlab,ftype));
497 ACTION.push_str(&format!("{}:{},",&newlab,&newactionlab));
498 }fi+=1;
501 }}},
505 _ => {},
506 }if flattened {rhsi+=1; continue;}
508 }let lhsreachable = match self.Reachable.get(&rsym.index) {
513 None => false,
514 Some(rset) => rset.contains(&lhsi),
515 };
516
517 let needrecursion = lhsreachable && !nonlbxtype(rsymtype);
518 if alreadyislbxlab || needrecursion {
519 let mut lclbx = ""; let semact;
521 if tuplevariant {
522 if !self.bumpast && needrecursion {
523 enumvar.push_str(&format!("LBox<{}>,",rsymtype));
524 lclbx = "lbx";
525 }
526 else if alreadyislbxlab && !nonlctype(rsymtype) {
527 enumvar.push_str(&format!("LC<{}>,",rsymtype));
528 lclbx = "lc";
529 }
530 semact = if lclbx.len()==0 {format!("{},",&itemlabel)} else {format!("parser.{}({},{}),",lclbx,&rhsi, &itemlabel)};
531 } else { if !self.bumpast && needrecursion {
534 enumvar.push_str(&format!("{}:LBox<{}>,",itemlabel,rsymtype));
535 lclbx="lbx";
536 } else if alreadyislbxlab && !nonlctype(rsymtype) {
537 enumvar.push_str(&format!("{}:LC<{}>,",itemlabel,rsymtype));
538 lclbx = "lc";
539 }
540 semact = if lclbx.len()==0 {format!("{0}:{0},",&itemlabel)} else {format!("{}:parser.{}({},{}),",&itemlabel,lclbx,&rhsi, &itemlabel)};
541} ACTION.push_str(&semact);
544 if rsymtype==&lhsymtype && passthru==-1 {passthru=rhsi as i32;}
545 else {passthru = -2;}
546
547 } else if rsymtype!="()" || (rsym.label.len()>0 && !rsym.label.starts_with("_item")) { if tuplevariant {
552 enumvar.push_str(&format!("{},",rsymtype));
553 ACTION.push_str(&format!("{},",&itemlabel));
554 } else {
555 enumvar.push_str(&format!("{}:{},",&itemlabel,rsymtype));
556 ACTION.push_str(&format!("{0}:{0},",&itemlabel));
557 }if rsymtype==&lhsymtype && passthru==-1 {passthru=rhsi as i32;}
560 else {passthru = -2;}
561 }rhsi += 1;
572 }if enumvar.ends_with(',') {
574 enumvar.pop();
575 if tuplevariant {enumvar.push(')');}
576 else {enumvar.push('}');}
577 ACTION.pop();
578 if tuplevariant {ACTION.push(')');}
579 else {ACTION.push('}');}
580 } else if enumvar.ends_with('(') || enumvar.ends_with('{') {
581 enumvar.pop();
584 ACTION.pop();
585 }
586 if ACTION.ends_with('\"') { if tuplevariant {ACTION.push(')');} else {ACTION.push('}');}
588 }
589 ACTION.push_str(" }"); let shouldpush = ntsym.rusttype.starts_with(NT) || toextend.contains_key(nt); let mut actbase = augment_action(&self.Rules[*ri].action);
594 if !actbase.ends_with('}') && passthru>=0 && nolhslabel {
595 self.Rules[*ri].action = format!("{} _item{}_ }}",&actbase,passthru);
596}
598 else
599 if !actbase.ends_with('}') && shouldpush {
600 self.Rules[*ri].action = format!("{} {}",&actbase,&ACTION);
601 if !nullenum {AST.push_str(&enumvar); AST.push_str(",\n");}
602 self.Rules[*ri].autogenerated = true;
603 }
604 else if shouldpush { if !nullenum {AST.push_str(&enumvar); AST.push_str(",\n");}
606 }
608}let mut storedAST;
614 if willextend {
615 let targetnti = toextend.get(&nti).unwrap();
616 storedAST = enumasts.remove(targetnti).unwrap_or(String::new());
617 storedAST.push_str(&AST);
618 enumasts.insert(*targetnti,storedAST);
619 }
620 else { storedAST = enumasts.remove(&nti).unwrap_or(String::new());
622 storedAST = format!("{}{}",&AST,&storedAST);
623 enumasts.insert(nti,storedAST);
624 }
625
626 }for (nt,ntast) in enumasts.iter() {
630 if !self.Symbols[*nt].rusttype.starts_with(&self.Symbols[*nt].sym) {continue;}
631 if let Some(defaultdef) = self.defaults.get(nt) {
632 let mut ast = format!("{}}}\n",ntast);
633 let uselt = if self.lifetime.len()>0 && self.Symbols[*nt].rusttype.contains(&self.lifetime) {<opt} else {""};
635 ast.push_str(&format!("impl{} Default for {} {{ fn default()->Self {{ use {}::*; {} }}\n}}\n\n",uselt,&self.Symbols[*nt].rusttype,&self.Symbols[*nt].sym,defaultdef));
636 ASTS.push_str(&ast);
637 }
638 else
639 if ntast.starts_with("#[derive(Debug)]/*enum*/") { let defaultvar = format!("{}_Nothing",&self.Symbols[*nt].sym);
642 let mut ast = format!("{} {},\n}}\n",ntast,&defaultvar);
643 let uselt = if self.lifetime.len()>0 && self.Symbols[*nt].rusttype.contains(&self.lifetime) {<opt} else {""};
644 ast.push_str(&format!("impl{} Default for {} {{ fn default()->Self {{ {}::{} }} }}\n\n",uselt,&self.Symbols[*nt].rusttype,&self.Symbols[*nt].sym,&defaultvar));
645 ASTS.push_str(&ast);
646 } else { ASTS.push_str(ntast); }
648 }self.Absyntype = self.Symbols[self.topsym].rusttype.clone();
652 self.enumhash.insert(self.Absyntype.clone(), 0);
653
654 for (_,(_,_,_,Sast,_)) in structasts.iter() {
656 ASTS.push_str(Sast);
657 }
658
659 self.sametype = false;
660 self.ntcxmax = ntcx;
661 ASTS
662 }pub fn writeabsyn(&mut self, filename:&str) ->Result<(),std::io::Error>
666 {
667 let ASTS = self.prepare();
668 let mut fd = File::create(filename)?;
670 write!(fd,"//Abstract syntax types generated by rustlr for grammar {}",&self.name)?;
671 write!(fd,"\n
672#![allow(unused_variables)]
673#![allow(non_snake_case)]
674#![allow(non_camel_case_types)]
675#![allow(unused_parens)]
676#![allow(unused_imports)]
677#![allow(dead_code)]
678extern crate rustlr;
679pub use rustlr::LC;
680use rustlr::LBox;\n")?;
681if self.ASTExtras.len()>0 {write!(fd,"\n{}\n",&self.ASTExtras)?;}
683 write!(fd,"{}",&ASTS)?;
684 self.logprint(&format!("Abstract syntax structures created in {}",filename));
685 self.Extras.push_str("use rustlr::LBox;\n");
687 self.Extras.push_str(&format!("use crate::{}_ast::*;\n",&self.name));
689 Ok(())
690 }pub fn reachability(&mut self)
697 {
698 for NT in self.Rulesfor.keys()
699 {
700 self.Reachable.insert(*NT, HashSet::new());
701 } let mut stillopen = true;
704 while stillopen {
705 stillopen = false;
706 for (NT, NTrules) in self.Rulesfor.iter()
707 {
708 let mut symset = HashSet::new(); for ri in NTrules
711 {
712 for sym in &self.Rules[*ri].rhs
713 {
714 let symi = sym.index; symset.insert(symi);
716 if !sym.terminal { for nsymi in self.Reachable.get(&symi).unwrap().iter()
718 {
719 symset.insert(*nsymi);
720 }
721 }
722 } }let ireachable = self.Reachable.get_mut(NT).unwrap();
725 for sym in symset
726 {
727 stillopen = ireachable.insert(sym) || stillopen;
728 }
729 }}}pub fn reachability_types(&mut self)
736 {
737 let mut needtoclose = false;
738 for (NT,NTrules) in self.Rulesfor.iter()
739 {
740 let mut ntreach = self.Reachable.get_mut(NT).unwrap();
741 let nttype = &self.Symbols[*NT].rusttype;
743 if nttype.starts_with(':') {
744 if let Some(othernti)=self.Symhash.get(nttype[1..].trim()) {
745 if ntreach.insert(*othernti) && !needtoclose {needtoclose=true;}
746 let otherreach=self.Reachable.get_mut(othernti).unwrap();
747 if otherreach.insert(*NT) && !needtoclose {needtoclose=true;}
748 }
755 } } while needtoclose {
759 needtoclose = false;
760 for NT in self.Rulesfor.keys()
761 {
762 let ireachable1 = self.Reachable.get(NT).unwrap();
763 let mut symset = HashSet::new(); for ni in ireachable1.iter() { if !self.Symbols[*ni].terminal {
766 let nireachable = self.Reachable.get(ni).unwrap();
767 for nsymi in nireachable.iter() { symset.insert(*nsymi); }
768 }
769 }let ireachable = self.Reachable.get_mut(NT).unwrap(); for sym in symset
772 {
773 if ireachable.insert(sym) && !needtoclose {needtoclose=true;}
774 }
775 }}}}fn augment_action(act0:&str) -> String
843{
844 let act = act0.trim();
845 if act.len()<=1 {return String::new();} let rbpo = act.rfind('}');
847 if let Some(rbp) = rbpo {
848 let ebpo = act[..rbp].rfind("...");
849 if let Some(ebp)=ebpo {
850 let mut act2 = String::from(&act[..ebp]) + " ";
851 return act2;
852 }
853 }
854 else {return String::new();} return String::from(act);
856}
857
858 fn nonlbxtype(ty:&str) -> bool
860 {
861 ty=="String" || (ty.starts_with('&') && !ty.contains("mut")) || ty.starts_with("Vec<LC") || ty.starts_with("Vec<LBox") || ty.starts_with("LBox") || ty.starts_with("Option<LBox") || ((ty.starts_with("HashMap<") || ty.starts_with("HashSet<") || ty.starts_with("BTree")) && (ty.contains("LBox<") || ty.contains("LC<")))
862 }fn nonlctype(ty:&str) -> bool
865 {
866 ty.starts_with("LC<") || ty.starts_with("LBox<") || ty.starts_with("Vec<LC") || ty.starts_with("Vec<LBox") || ty.starts_with("Option<LBox") || ty.starts_with("Option<LC")
867 }