rustlr 0.3.0

LR/LALR parser generator that can automatically create abstract syntax trees
Documentation


                // <COMMA*> OR <SEMICOLON+>
                let mut newtok3; // will be new strtok
		let septoks:Vec<&str> = strtok.split(':').collect();
		if septoks.len()>0 && septoks[0].len()>2 && (septoks[0].ends_with("*>") || septoks[0].ends_with("+>") {                
                  let (lb,rb) = findmatch(strtok,'<','>');
                  let termi;
                  if lr!=0 && lr+2<rb  {
                    // determine if what's inside <> is valid
                    let termsym = &strtok[lb+1..rb-1]; // like COMMA
                    let termiopt = self.Symhash.get(termsym);
                    if !self.terminal(termsym) {
                      panic!("ERROR ON LINE {}, {} is not a terminal symbol of this grammar\n",linenum,termsym);
                    }
                    termi = *termiopt.unwrap();
                  } else {panic!("MALFORMED EXPRESSION LINE {}\n",linenum);}
                  strtok = septoks[0]; // to the left of :, E<,*>
   	          let defaultrelab3 = format!("_item{}_",i-1-iadjust);
		  let relabel3 = if septoks.len()>1 && septoks[1].len()>0 {septoks[1]} else {&defaultrelab3};
    	          let mut gsympart3 = strtok[0..lb].trim(); //before <,*>
                  if gsympart3=="_" {gsympart3="_WILDCARD_TOKEN_";}
   	          let errmsg = format!("UNRECOGNIZED GRAMMAR SYMBOL '{}', LINE {}\n",gsympart3,linenum);
	          let gsymi = *self.Symhash.get(gsympart3).expect(&errmsg);
		  let newntname3 = format!("NEWSEPNT{}_{}_{}",gsympart3,self.Rules.len(),ntcnt); ntcnt+=1;
	          let mut newnt3 = Gsym::new(&newntname3,false);
                  newnt3.rusttype = "()".to_owned();2
                  if &self.Symbols[gsymi].rusttype!="()" || (septoks.len()>1 && septoks[1].len()>0) {
		     newnt3.rusttype = format!("Vec<LBox<{}>>",&self.Symbols[gsymi].rusttype);
                  } // else rusttype stays ()
	          if !self.enumhash.contains_key(&newnt3.rusttype) {
 		     self.enumhash.insert(newnt.rusttype.clone(),ntcx);
		     ntcx+=1;
		  }
		  self.Symbols.push(newnt3.clone()); // register new nt
		  self.Symhash.insert(newntname3.clone(),self.Symbols.len()-1);
		   // add new rules
		  let mut newrule3 = Grule::new_skeleton(&newntname3);
		  let mut newrule4 = Grule::new_skeleton(&newntname3);
  		  newrule3.lhs.rusttype = newnt3.rusttype.clone();
  		  newrule4.lhs.rusttype = newnt3.rusttype.clone();
                  newrule3.precedence = self.Symbols[gsymi].precedence;
                  //PRECEDENCE SET TO SEPARATOR SYMBOL
                  newrule4.precedence = self.Symbols[termi].precedence;
                  // GENERATE AS FOR <COMMA+>
                  newrule3.rhs.push(self.Symbols[gsymi].clone()); //N-->E
                  newrule4.rhs.push(newnt3.clone());
                  newrule4.rhs.push(self.Symbols[termi].clone());
                  newrule4.rhs.push(self.Symbols[gsymi].clone());//N-->N,E
                  if newnt3.rusttype.starts_with("Vec") {
                    newrule3.action=String::from(" vec![parser.lbx(0,_item0_)] }");                  
                    newrule4.action=String::from(" _item0_.push(parser.lbx(2,_item2_)); _item0_ }");
                  } // else leave at default
		  self.Rules.push(newrule3);
   	          self.Rules.push(newrule4);
		  let mut rulesforset3 = HashSet::with_capacity(2);
		  rulesforset3.insert(self.Rules.len()-2);
		  rulesforset3.insert(self.Rules.len()-1);
                  newtok3 = format!("{}:{}",&newntname3,relabel3);
                  self.Rulesfor.insert(newntname3,rulesforset3);
                  // ANOTHER RULE IS NEEDED IF strtok ends in *>
                  if strtok.ends_with("*>") {  // M --> | N
                    let newntname5 = format!("NEWSEPNT2_{}_{}",self.Rules.len(),ntcnt); ntcnt+=1;
                    let mut newnt5 = Gsym::new(&newntname5,false);
                    newnt5.rusttype = newnt3.rusttype.clone();
		    self.Symhash.insert(newntname5.clone(),self.Symbols.len());
                    self.Symbols.push(newnt5.clone()); // register new nt
                    let mut newrule5 = Grule::new_skeleton(&newntname5);
                    let mut newrule6 = Grule::new_skeleton(&newntname5);
  		    newrule5.lhs.rusttype = newnt5.rusttype.clone();
  		    newrule6.lhs.rusttype = newnt5.rusttype.clone();
                    // 0 precedence for rule, newrule5 has empty rhs
                    newrule6.rhs.push(newnt3.clone());
                    if newnt5.rusttype.starts_with("Vec") {
                       newrule5.action = String::from(" vec![] }");
                       newrule6.action = String::from("_item0_ }");
                    }
		  self.Rules.push(newrule5);
   	          self.Rules.push(newrule6);
		  let mut rulesforset5 = HashSet::with_capacity(2);
		  rulesforset5.insert(self.Rules.len()-2);
		  rulesforset5.insert(self.Rules.len()-1);
                  newtok3 = format!("{}:{}",&newntname5,relabel3);
                  self.Rulesfor.insert(newntname5,rulesforset5);
                  } // *>
                  strtok = &newtok3;
                } // if ends with *> or +>




//////////// copied over stuff

		   if strtok.ends_with('?') {
		     newrule1.rhs.push(self.Symbols[gsymi].clone());
                     if newrule1.lhs.rusttype.starts_with("Option<LBox<") {
		       newrule1.action=String::from(" Some(parser.lbx(0,_item0_)) }"); } else if newrule1.lhs.rusttype.starts_with("Option<") {newrule1.action = String::from(" Some(_item0_) }"); } // else nothing
		   }// end with ?
		   else { // * or +
  		     newrule1.rhs.push(newnt.clone());
		     newrule1.rhs.push(self.Symbols[gsymi].clone());
                     if &newrule1.lhs.rusttype!="()" {
		       newrule1.action = String::from(" _item0_.push(parser.lbx(1,_item1_)); _item0_ }");
                     }
		   } // * or +
		   let mut newrule0 = Grule::new_skeleton(&newntname);
		   newrule0.lhs.rusttype = newnt.rusttype.clone();
		   if strtok.ends_with('+') {
		     newrule0.rhs.push(self.Symbols[gsymi].clone());
                     if &newrule0.lhs.rusttype!="()" {
		       newrule0.action=String::from(" vec![parser.lbx(0,_item0_)] }");
                     }
		   }// ends with +
		   else if strtok.ends_with('*') && &newrule0.lhs.rusttype!="()" {
		     newrule0.action = String::from(" Vec::new() }");
		   }
		   else if strtok.ends_with('?') && &newrule0.lhs.rusttype!="()" {
		     newrule0.action = String::from(" None }");
		   }
                   if self.tracelev>4 {
                     printrule(&newrule0,self.Rules.len());
                     printrule(&newrule1,self.Rules.len()+1);   
                   }                   
		   self.Rules.push(newrule0);
		   self.Rules.push(newrule1);
		   let mut rulesforset = HashSet::with_capacity(2);
		   rulesforset.insert(self.Rules.len()-2);
		   rulesforset.insert(self.Rules.len()-1);
		   newtok = format!("{}:{}",&newntname,relabel);
		   self.Rulesfor.insert(newntname,rulesforset);
		   // change strtok to new form
		   strtok = &newtok;
//println!("2 strtok now {}",strtok);                   
		}// processes RE directive - add new productions