// <COMMA*>
let newtok; // will be new strtok
let retoks:Vec<&str> = strtok.split(':').collect();
if retoks.len()>0 && retoks[0].len()>1 && (retoks[0].ends_with('*') || retoks[0].ends_with('+') || retoks[0].ends_with('?')) {
strtok = retoks[0]; // to be changed back to normal a:b
let defaultrelab = format!("_item{}_",i-1-iadjust);
let relabel = if retoks.len()>1 && retoks[1].len()>0 {retoks[1]} else {&defaultrelab};
let mut gsympart = strtok[0..strtok.len()-1].trim(); //no *
if gsympart=="_" {gsympart="_WILDCARD_TOKEN_";}
let errmsg = format!("unrecognized grammar symbol '{}', line {}",gsympart,linenum);
let gsymi = *self.Symhash.get(gsympart).expect(&errmsg);
let newntname = format!("NEWNT{}_{}_{}",gsympart,self.Rules.len(),ntcnt); ntcnt+=1;
let mut newnt = Gsym::new(&newntname,false);
newnt.rusttype = "()".to_owned();
// following means symbols such as -? will not be
// part of ast type unless there is a given label: -?:m
if &self.Symbols[gsymi].rusttype!="()" || (retoks.len()>1 && retoks[1].len()>0) {
newnt.rusttype = if strtok.ends_with('?') {
if self.basictypes.contains(&self.Symbols[gsymi].rusttype[..]) || self.Symbols[gsymi].rusttype.starts_with("Vec") /*self.basictypes.contains(&self.Symbols[gsymi].rusttype[..])*/ {format!("Option<{}>",&self.Symbols[gsymi].rusttype)}
else {format!("Option<LBox<{}>>",&self.Symbols[gsymi].rusttype)}
}
else {format!("Vec<LBox<{}>>",&self.Symbols[gsymi].rusttype)};
}
if !self.enumhash.contains_key(&newnt.rusttype) {
self.enumhash.insert(newnt.rusttype.clone(),ntcx);
ntcx+=1;
}
self.Symbols.push(newnt.clone());
self.Symhash.insert(newntname.clone(),self.Symbols.len()-1);
// add new rules
let mut newrule1 = Grule::new_skeleton(&newntname);
newrule1.lhs.rusttype = newnt.rusttype.clone();
newrule1.precedence = self.Symbols[gsymi].precedence;
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