// /* // See // https://github.com/rust-lang/rust/blob/master/src/grammar/lexer.l // https://github.com/rust-lang/rust/blob/master/src/grammar/parser-lalr.y // https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs // */ extern crate grammar; use std::cmp::Ordering; use grammar::{Associativity,EarleyKind,State,Parser,ParsingTablesTrait,AmbiguityInfo}; use std::env; use std::fs::File; use std::io::prelude::*; use std::rc::Rc; use std::collections::HashMap; use std::fmt::{self,Display,Formatter}; #[derive(Clone,Debug,PartialEq)] enum PatKind { Fixme, Underscore, Ref(Rc), RefMut(Rc), Void, Tuple(Vec), Path(PathKind), EnumEmpty(Rc), Enum(Rc,Vec),//name,tuple BindedIdent(BindKind,String) } #[derive(Clone,Debug,PartialEq)] enum TyKind { Fixme, Underscore, Ref(Rc), RefMut(Rc), RefLifetime(String,bool,Rc),//lifetime,mut,type Void, Path(PathWKind), Tuple(Vec) } #[derive(Clone,Debug,PartialEq)] enum ExprKind { Fixme, Single(Rc), Member(Rc,PathKind),//object, attribute_or_method Index(Rc,Option>),//object, index Call(Rc,Vec),//function,arguments Parentheses(Vec), Infix(Rc,Rc,Rc),//left,symbol,right Ref(Rc), RefMut(Rc), Prefix(Rc,Rc),//symbol,operand Lambda(Vec<(PatKind,Option)>,Option,Rc),//params,optional return,expression Struct(PathKind,Vec<(String,Option)>),//path to struct name, initializations Range(Option>,Option>), Return(Option>), Break(Option)//optional lifetime or ident } #[derive(Clone,Debug,PartialEq)] enum StmtKind { Let(PatKind,Option,Option), Item(Vec,ItemKind),//attributes, item Block(Vec,Rc),//attributes, block Expr(Vec,ExprKind),//attributes, expression Empty } #[derive(Clone,Debug,PartialEq)] enum AttrKind { Documentation(String), Flag(String), Value(String,Rc), Sequence(String,Vec) } //With colons #[derive(Clone,Debug,PartialEq)] enum PathKind { Fixme, Ident(String), Super, Absolute(Rc), FromSelf(Rc), StepIdent(Rc,String), StepSuper(Rc), GenericArgs(Rc,Vec), Literal(Rc) } //Without colons #[derive(Clone,Debug,PartialEq)] enum PathWKind { Fixme, Ident(String), IdentGeneric(String,Vec), Function(String,Vec,Rc), StepIdent(Rc,String), StepIdentGeneric(Rc,String,Vec), StepFunction(Rc,String,Vec,Rc) } //No types #[derive(Clone,Debug,PartialEq)] enum PathNKind { Fixme, Ident(String), AbsoluteIdent(String), FromSelf, AbsoluteSelf, Super, AbsoluteSuper, Step(Rc,String) } #[derive(Clone,Debug,PartialEq)] enum ViewKind { Fixme, Path(PathNKind,Option), All(Option), Selection(Option,Vec), ExternCrate(String,Option)//crate id, as name } #[derive(Clone,Debug,PartialEq)] enum BindKind { Ref, RefMut, Mut } #[derive(Clone,Debug,PartialEq)] enum ItemKind { Fixme, Macro(Rc,Option>,Rc), FN(String, Vec,Vec,Vec<(PatKind,TyLf)>,Option,Vec,Option),//name, lifetimes, generic params, params(pattern,type), return type, block statements, block expression Method(String, Vec,Vec,bool,bool,bool,Option,Vec<(PatKind,TyLf)>,Option,Vec,Option),//name, lifetimes, generic params, has_self, has_ref, has_mut, self_type, params(pattern,type), return type, block statements, block expression Terminal(String,Option>,Vec), Nonterminal(String,Option>,Vec>), View(ViewKind), Enum(String,Vec,Vec,Vec<(String,Vec)>),//name, lifetimes, params, defs Impl(Vec,Vec,Option,TyLf,Vec),//lifetimes, generic params, optional path of trait, type of the thing being implemented, subitems Struct(String,Vec,Vec,Vec<(String,TyLf)>)//name, lifetimes, generic params, fields } #[derive(Clone,Debug,PartialEq)] enum TyLf { Type(TyKind), Lifetime(String) } impl Display for PatKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &PatKind::Fixme => write!(f," FIXME "), &PatKind::Underscore => write!(f,"_"), &PatKind::Ref(ref kind) => write!(f,"& {}",kind), &PatKind::RefMut(ref kind) => write!(f,"&mut {}",kind), &PatKind::Void => write!(f,"()"), &PatKind::Tuple(ref tuple) => write!(f,"({})",tuple.iter().map(|p|p.to_string()).collect::>().join(",")), &PatKind::Path(ref token) => write!(f,"{}",token), &PatKind::EnumEmpty(ref name) => write!(f,"{}",name), &PatKind::Enum(ref name, ref tuple) => write!(f,"{}({})",name,tuple.iter().map(|p|p.to_string()).collect::>().join(",")), &PatKind::BindedIdent(BindKind::Ref, ref string) => write!(f,"ref {}",string), &PatKind::BindedIdent(BindKind::RefMut, ref string) => write!(f,"ref mut {}",string), &PatKind::BindedIdent(BindKind::Mut, ref string) => write!(f,"mut {}",string), } } } impl Display for TyKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &TyKind::Fixme => write!(f," FIXME "), &TyKind::Underscore => write!(f,"_"), &TyKind::Ref(ref kind) => write!(f,"& {}",kind), &TyKind::RefMut(ref kind) => write!(f,"&mut {}",kind), &TyKind::RefLifetime(ref lifetime, true ,ref kind) => write!(f,"&{} mut {}",lifetime,kind), &TyKind::RefLifetime(ref lifetime, false ,ref kind) => write!(f,"&{} {}",lifetime,kind), &TyKind::Void => write!(f,"()"), &TyKind::Path(ref path) => write!(f,"{}",path), &TyKind::Tuple(ref list) => write!(f,"({})",list.iter().map(|t|t.to_string()).collect::>().join(",")), } } } impl Display for ExprKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &ExprKind::Fixme => write!(f," FIXME "), &ExprKind::Single(ref token) => write!(f,"{}",token), &ExprKind::Member(ref kind, ref path) => write!(f,"{}.{}",kind,path), &ExprKind::Index(ref object, None) => write!(f,"{}[]",object), &ExprKind::Index(ref object, Some(ref index)) => write!(f,"{}[{}]",object,index), &ExprKind::Call(ref function, ref arguments) => write!(f,"{}({})",function,arguments.iter().map(|x| x.to_string() ).collect::>().join(",")), &ExprKind::Parentheses(ref list) => write!(f,"({})",list.iter().map(|x| x.to_string() ).collect::>().join(",")), &ExprKind::Infix(ref left,ref symbol,ref right) => write!(f,"{} {} {}",left,symbol,right), &ExprKind::Ref(ref expr) => write!(f,"&{}",expr), &ExprKind::RefMut(ref expr) => write!(f,"&mut {}",expr), &ExprKind::Prefix(ref symbol, ref expr) => write!(f,"{} {}",symbol,expr), &ExprKind::Lambda(ref args, ref ot, ref expr) => write!(f,"|{}|{}{}",args.iter().map(|&(ref pat,ref opt)|match opt{ &None => pat.to_string(), &Some(ref t) => format!("{}:{}",pat,t), }).collect::>().join(","),match ot { &None=>String::from(""), &Some(ref t)=>t.to_string(), },expr), &ExprKind::Struct(ref path, ref initializations) => write!(f,"{}{{{}}}",path,initializations.iter().map(|&(ref s,ref oe)|match oe{ &None => format!("{},",s), &Some(ref e) => format!("{}:{},",s,e), }).collect::>().join("\n")), &ExprKind::Range(Some(ref left),None) => write!(f,"{}..",left), &ExprKind::Range(Some(ref left),Some(ref right)) => write!(f,"{}..{}",left,right), &ExprKind::Range(None,Some(ref right)) => write!(f,"..{}",right), &ExprKind::Range(None,None) => write!(f,".."), &ExprKind::Return(None) => write!(f,"return"), &ExprKind::Return(Some(ref expr)) => write!(f,"return {}",expr), &ExprKind::Break(None) => write!(f,"break"), &ExprKind::Break(Some(ref string)) => write!(f,"break {}",string), } } } impl Display for StmtKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &StmtKind::Let(ref pattern,ref option_type,ref option_expr) => { write!(f,"let {}",pattern).unwrap(); if let &Some(ref t)=option_type { write!(f,":{}",t).unwrap(); } if let &Some(ref e)=option_expr { write!(f,"={}",e).unwrap(); } write!(f,";") }, &StmtKind::Item(ref attrs, ref token) => write!(f,"{}",token), &StmtKind::Block(ref attrs, ref token) => write!(f,"{}",token), &StmtKind::Expr(ref attrs, ref token) => write!(f,"{};",token), &StmtKind::Empty => write!(f,";"), } } } impl AttrKind { fn simple_to_string(&self)->String { match self { &AttrKind::Documentation(ref string) => string.clone(), &AttrKind::Flag(ref string) => string.clone(), &AttrKind::Value(ref string,ref token) => format!("{}={}",string,token), &AttrKind::Sequence(ref string, ref attributes) => format!("{}({})",string,attributes.iter().map(|x|x.simple_to_string()).collect::>().join(",")), } } } impl Display for AttrKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &AttrKind::Documentation(ref string) => write!(f,"{}",string), &AttrKind::Flag(ref string) => write!(f,"#[{}]",string), &AttrKind::Value(ref string,ref token) => write!(f,"#[{}={}]",string,token), &AttrKind::Sequence(ref string, ref attributes) => write!(f,"#[{}({})]",string,attributes.iter().map(|x|x.simple_to_string()).collect::>().join(",")), } } } impl Display for PathKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &PathKind::Fixme => write!(f,"::fixme::"), &PathKind::Ident(ref string) => write!(f,"{}",string), &PathKind::Super => write!(f,"super"), &PathKind::Absolute(ref path) => write!(f,"::{}",path), &PathKind::FromSelf(ref path) => write!(f,"self::{}",path), &PathKind::StepIdent(ref path, ref string) => write!(f,"{}::{}",path,string), &PathKind::StepSuper(ref path) => write!(f,"{}::super",path), &PathKind::GenericArgs(ref path, ref ga) => write!(f,"{}::<{}>",path,ga.iter().map(|x|x.to_string()).collect::>().join(",")), &PathKind::Literal(ref token) => write!(f,"{}",token), } } } impl Display for PathWKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &PathWKind::Fixme => write!(f,"::fixme::"), &PathWKind::Ident(ref string) => write!(f,"{}",string), &PathWKind::IdentGeneric(ref string,ref gens) => write!(f,"{}<{}>",string,gens.iter().map(|g|g.to_string()).collect::>().join(",")), &PathWKind::Function(ref string,ref arguments,ref t_return_type) => write!(f,"{}({}){}",string,arguments.iter().map(|x|x.to_string()).collect::>().join(","),t_return_type), &PathWKind::StepIdent(ref path, ref string) => write!(f,"{}::{}",path,string), &PathWKind::StepIdentGeneric(ref path, ref string, ref gens) => write!(f,"{}::{}<{}>",path,string,gens.iter().map(|g|g.to_string()).collect::>().join(",")), &PathWKind::StepFunction(ref path,ref string,ref arguments,ref t_return_type) => write!(f,"{}::{}({}){}",path,string,arguments.iter().map(|x|x.to_string()).collect::>().join(","),t_return_type), } } } impl Display for PathNKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &PathNKind::Fixme => write!(f,"::fixme::"), &PathNKind::Ident(ref string) => write!(f,"{}",string), &PathNKind::AbsoluteIdent(ref string) => write!(f,"::{}",string), &PathNKind::FromSelf => write!(f,"self"), &PathNKind::AbsoluteSelf => write!(f,"::self"), &PathNKind::Super => write!(f,"super"), &PathNKind::AbsoluteSuper => write!(f,"::super"), &PathNKind::Step(ref path,ref string) => write!(f,"{}::{}",path,string), } } } impl Display for ViewKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &ViewKind::Fixme => write!(f,"view fixme;"), &ViewKind::Path(ref path,None) => write!(f,"use {};",path), &ViewKind::Path(ref path,Some(ref string)) => write!(f,"use {} as {};",path,string), &ViewKind::All(None) => write!(f,"use *;"), &ViewKind::All(Some(ref path)) => write!(f,"use {}::*;",path), &ViewKind::Selection(None,ref list) => write!(f,"use {{{}}};",list.join(",")), &ViewKind::Selection(Some(ref path),ref list) => write!(f,"use {}::{{{}}};",path,list.join(",")), &ViewKind::ExternCrate(ref name, None) => write!(f,"extern crate {};",name), &ViewKind::ExternCrate(ref name, Some(ref string_as)) => write!(f,"extern crate {} as {};",name,string_as), } } } impl Display for ItemKind { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &ItemKind::Fixme => write!(f,"fixme {{ }}"), &ItemKind::Macro(ref name, ref subname, ref token) => write!(f,"{}!{};",name,token),//FIXME &ItemKind::FN(ref name, ref lifetimes, ref gp, ref params, ref oret, ref block_stmts, ref block_expr) => { //write!(f,"fn fixme() {{ }}"), write!(f,"fn {}",name).unwrap(); if (lifetimes.len()>0) || ((gp.len())>0) { //write!(f,"<{}>",gp.join(",")).unwrap(); write!(f,"<{}>",lifetimes.iter().chain(gp.iter()).map(|x|x.clone()).collect::>().join(",")).unwrap(); } write!(f,"({})",params.iter().map(|&(ref p,ref t)| format!("{}:{}",p,t) ).collect::>().join(",")).unwrap(); if let &Some(ref ret)=oret { write!(f,"->{}",ret).unwrap(); } writeln!(f,"{{").unwrap(); for stmt in block_stmts { writeln!(f,"{}",stmt).unwrap(); } if let &Some(ref e)=block_expr { write!(f,"{}",e).unwrap(); } writeln!(f,"}}") }, &ItemKind::Method(ref name, ref lifetimes, ref gp, has_self, q_self_has_ref, q_self_has_mut, ref o_self_type, ref params, ref oret, ref block_stmts, ref block_expr) => { //write!(f,"fn fixme() {{ }}"), write!(f,"fn {}",name).unwrap(); if (lifetimes.len()>0) || (gp.len()>0) { //write!(f,"<{}>",gp.join(",")).unwrap(); write!(f,"<{}>",lifetimes.iter().chain(gp.iter()).map(|x|x.clone()).collect::>().join(",")).unwrap(); } write!(f,"(").unwrap(); if has_self { if q_self_has_ref { write!(f,"&").unwrap(); } if q_self_has_mut { write!(f,"mut ").unwrap(); } write!(f,"self").unwrap(); if let &Some(ref t)=o_self_type { write!(f,":{}",t).unwrap(); } if params.len()>0 { write!(f,",").unwrap(); } } write!(f,"{})",params.iter().map(|&(ref p,ref t)| format!("{}:{}",p,t) ).collect::>().join(",")).unwrap(); if let &Some(ref ret)=oret { write!(f,"->{}",ret).unwrap(); } writeln!(f,"{{").unwrap(); for stmt in block_stmts { writeln!(f,"{}",stmt).unwrap(); } if let &Some(ref e)=block_expr { write!(f,"{}",e).unwrap(); } writeln!(f,"}}") }, &ItemKind::Terminal(_,_,_) => panic!("Should not be printing this"), &ItemKind::Nonterminal(_,_,_) => panic!("Should not be printing this"), &ItemKind::View(ref view) => write!(f,"{}",view), &ItemKind::Enum(ref id, ref lifetimes, ref params, ref defs) => { write!(f,"enum {}",id).unwrap(); if (lifetimes.len()>0) || (params.len()>0) { //write!(f,"({})",params.join(",")).unwrap(); write!(f,"<{}>",lifetimes.iter().chain(params.iter()).map(|x|x.clone()).collect::>().join(",")).unwrap(); } writeln!(f,"{{").unwrap(); for &(ref name,ref tys) in defs { write!(f,"{}",name).unwrap(); if tys.len()>0 { write!(f,"({})",tys.iter().map(|t|t.to_string()).collect::>().join(",")).unwrap(); } writeln!(f,",").unwrap(); } writeln!(f,"}}") }, &ItemKind::Impl(ref lifetimes, ref gp, ref otrait, ref t, ref items) => { write!(f,"impl").unwrap(); if (lifetimes.len()>0) || (gp.len()>0) { //write!(f,"<{}>",gp.join(",")).unwrap(); write!(f,"<{}>",lifetimes.iter().chain(gp.iter()).map(|x|x.clone()).collect::>().join(",")).unwrap(); } if let &Some(ref tr)=otrait { writeln!(f," {} for {} {{",tr,t).unwrap(); } else { writeln!(f," {} {{",t).unwrap(); } for item in items { writeln!(f,"{}",item).unwrap(); } writeln!(f,"}}") }, &ItemKind::Struct(ref name, ref lifetimes, ref gp, ref fields) => { write!(f,"struct {}",name).unwrap(); if (lifetimes.len()>0) || (gp.len()>0) { //write!(f,"<{}>",gp.join(",")).unwrap(); write!(f,"<{}>",lifetimes.iter().chain(gp.iter()).map(|x|x.clone()).collect::>().join(",")).unwrap(); } writeln!(f,"{{").unwrap(); for &(ref name,ref ty) in fields { writeln!(f,"{}:{},",name,ty).unwrap(); } writeln!(f,"}}") }, } } } impl Display for TyLf { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &TyLf::Type(ref t) => write!(f,"{}",t), &TyLf::Lifetime(ref string) => write!(f,"{}",string), } } } impl Display for Token { fn fmt(&self, f:&mut Formatter) -> fmt::Result { match self { &Token::TySum(ref kind) => write!(f,"{}",kind), &Token::Pat(ref kind) => write!(f,"{}",kind), &Token::LitOrPath(ref string) => write!(f,"{}",string), &Token::NonblockExpr(ref expr) => write!(f,"{}",expr), &Token::PathExpr(ref string) => write!(f,"{}",string), &Token::Block(ref stmts, None) => write!(f,"{{{}}}", stmts.iter().map(|s| s.to_string() ).collect::>().join("\n") ), &Token::Block(ref stmts, Some(ref expr)) => write!(f,"{{{} {}}}", stmts.iter().map(|s| s.to_string() ).collect::>().join("\n") , expr), &Token::Equal => write!(f,"="), &Token::Lit(ref token) => write!(f,"{}",token), &Token::LitInteger(x) => write!(f,"{}",x), &Token::LitStr(ref string) => write!(f,"{}",string), &Token::LitChar(c) => match c { '\'' => write!(f,"'\\\''"), '\\' => write!(f,"'\\\\'"), _ => write!(f,"'{}'",c), }, &Token::Str(ref string) => write!(f,"{}",string), &Token::BlockExpr(ref token) => write!(f,"{}",token), &Token::ExprMatch(ref expr,ref clauses) => write!(f,"match {} {{ {} }}",expr,clauses.iter().map(|c|c.to_string()).collect::>().join(" ")), &Token::ExprIf(ref expr, ref block, None) => write!(f,"if {} {}",expr,block), &Token::ExprIf(ref expr, ref block, Some(ref q_else_block)) => write!(f,"if {} {} else {}",expr,block,q_else_block), &Token::ExprIfLet(ref pattern, ref expr, ref block, None) => write!(f,"if let {}={} {}",pattern,expr,block), &Token::ExprIfLet(ref pattern, ref expr, ref block, Some(ref q_else_block)) => write!(f,"if let {}={} {} else {}",pattern,expr,block,q_else_block), &Token::ExprFor(ref pattern, ref expr, ref block) => write!(f,"for {} in {} {}",pattern,expr,block), &Token::ExprWhile(ref expr, ref block) => write!(f,"while {} {}",expr,block), &Token::True => write!(f,"true"), &Token::False => write!(f,"false"), &Token::Ref => write!(f,"ref"), &Token::For => write!(f,"for"), &Token::Match => write!(f,"match"), &Token::If => write!(f,"if"), &Token::Else => write!(f,"else"), &Token::MacroExpr(ref token,None,ref trees) => write!(f,"{}!{}",token,trees), &Token::DelimitedTokenTrees(ref trees) => write!(f,"{}",trees), &Token::BracketsDelimitedTokenTrees(ref trees) => write!(f,"[{}]",trees.iter().map(|t|t.to_string()).collect::>().join(" ")), &Token::ParensDelimitedTokenTrees(ref trees) => write!(f,"({})",trees.iter().map(|t|t.to_string()).collect::>().join(" ")), &Token::BracesDelimitedTokenTrees(ref trees) => write!(f,"{{{}}}",trees.iter().map(|t|t.to_string()).collect::>().join(" ")), &Token::LiteralIdent(ref string) => write!(f,"{}",string), &Token::Dot => write!(f,"."), &Token::Comma => write!(f,","), &Token::ModSep => write!(f,"::"), &Token::Vertical => write!(f,"|"), &Token::Ampersand => write!(f,"&"), &Token::Plus => write!(f,"+"), &Token::Minus => write!(f,"-"), &Token::Star => write!(f,"*"), &Token::Bang => write!(f,"!"), &Token::LT => write!(f,"<"), &Token::GT => write!(f,">"), &Token::NE => write!(f,"!="), &Token::EqualEqual => write!(f,"=="), &Token::AndAnd => write!(f,"&&"), &Token::OrOr => write!(f,"||"), &Token::PlusEqual => write!(f,"+="), &Token::FatArrow => write!(f,"=>"), &Token::DotDot => write!(f,".."), &Token::MatchClause(ref attributes,ref pattern, ref token) => write!(f,"{} => {},",pattern,token),//FIXME &Token::PatTup(ref patterns) => write!(f,"{}",patterns.iter().map(|p|p.to_string()).collect::>().join(" ")), &Token::LittleSelf => write!(f,"self"), _ => panic!("panic displaying {:?}",self), //_ => Err(fmt::Error), } } } re_terminal!(Static,"static"); re_terminal!(Mut,"mut"); re_terminal!(Const,"const"); re_terminal!(Crate,"crate"); re_terminal!(Extern,"extern"); re_terminal!(As,"as "); re_terminal!(Struct,"struct"); re_terminal!(Enum,"enum "); re_terminal!(Union,"union"); re_terminal!(Mod,"mod"); re_terminal!(Unsafe,"unsafe"); re_terminal!(FN,"fn "); re_terminal!(Pub,"pub"); re_terminal!(LittleSelf,"self"); re_terminal!(Type,"type "); re_terminal!(For,"for "); re_terminal!(Trait,"trait"); re_terminal!(DEFAULT,"default"); re_terminal!(Impl,"impl"); re_terminal!(Where,"where"); re_terminal!(Super,"super"); re_terminal!(BOX,"box"); re_terminal!(Ref,"ref"); re_terminal!(Typeof,"typeof"); re_terminal!(StaticLifetime,"'static"); re_terminal!(Continue,"continue"); re_terminal!(Return,"return"); re_terminal!(Break,"break"); re_terminal!(Yield,"yield"); re_terminal!(Move,"move"); re_terminal!(Match,"match"); re_terminal!(If,"if"); re_terminal!(Else,"else"); re_terminal!(LiteralLet,"let"); re_terminal!(While,"while"); re_terminal!(Loop,"loop"); re_terminal!(In,"in "); re_terminal!(True,"true"); re_terminal!(False,"false"); re_terminal!(Catch,"catch"); re_terminal!(Use,"use"); re_terminal!(Terminal,"terminal"); re_terminal!(Nonterminal,"nonterminal"); terminal ShebangLine { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,())> { None //if parser.line_number>0 //{ // return None; //} //match parser.re("^#![^\n]*\n", source) //{ // None => None, // Some(size,string) => Some(size,()), //} } } re_terminal!(LitInteger(usize),"[0-9]+"); //terminal LitInteger(usize) //{ // fn _match(parser: &mut Parser, source:&str) -> Option<(usize,usize)> // { // None // // 0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } // // 0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } // // 0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } // // [0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } // // [0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } // } //} terminal LitByte { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,())> { None } } terminal LitChar(char) { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,char)> { let mut characters=source.chars(); if (characters.next())==(Some('\'')) { let mut c=characters.next().unwrap(); let mut size=3; if c=='\\' { c=(characters.next().unwrap()); size=4; } if characters.next().unwrap()=='\'' { Some((size,c)) } else { None } } else { None } } } re_terminal!(LiteralLifetime(String),"'[a-zA-Z_]"); //terminal LiteralLifetime(String) //{ // fn _match(parser: &mut Parser, source:&str) -> Option<(usize,String)> // { // None // } //} terminal LitFloat { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,())> { None } } terminal LitStr(String) { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,String)> { let mut ret=None; let mut characters=source.chars(); if (characters.next())!=(Some('"')) { } else { let mut size=1; let mut r=String::from("\""); while true { match characters.next() { None => break, Some('"') => { ret=(Some((size+1,r+&"\""))); break; }, Some('\\') => { match characters.next() { None => break, //Some(c) => r+='\\'+c, Some(c) => { r.push('\\'); r.push(c); } }; size+=2; }, Some(c) => { //r+=&String::from(c); r.push(c); size+=1; }, }; } } ret } } terminal LitStrRaw { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,())> { None } } terminal LitByteStr { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,())> { None } } terminal LitByteStrRaw { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,())> { None } } terminal NoSpace { fn _match(parser: &mut Parser, source:&str) -> Option<(usize,())> { None } } re_terminal!(InnerDocComment,"\\\\![^\n]*\n"); re_terminal!(OuterDocComment(String),"\\\\\\[^\n]*\n"); re_terminal!(LiteralIdent(String),"[a-zA-Z\\x80-\\xff_][a-zA-Z0-9\\x80-\\xff_]*"); re_terminal!(Shebang,"#!"); re_terminal!(NumberSign,"#"); re_terminal!(FatArrow,"=>"); re_terminal!(EqualEqual,"=="); re_terminal!(NE,"!="); re_terminal!(Equal,"="); re_terminal!(LArrow,"<-"); re_terminal!(RArrow,"->"); //These cause many problems. Perhaps "<<" -> (LT,NOSPACE,LT) //re_terminal!(SHL,"\\<\\<"); //re_terminal!(SHR,"\\>\\>"); //re_terminal!(SHREQ,"\\>\\>="); re_terminal!(LE,"<="); re_terminal!(GE,">="); re_terminal!(MinusEqual,"-="); re_terminal!(AndEqual,"&="); re_terminal!(OrEqual,"\\|="); re_terminal!(PlusEqual,"\\+="); re_terminal!(StarEqual,"\\*="); re_terminal!(SlashEqual,"/="); re_terminal!(CaretEqual,"\\^="); re_terminal!(PercentEqual,"%="); re_terminal!(Underscore,"_"); re_terminal!(OrOr,"\\|\\|"); re_terminal!(Vertical,"\\|"); re_terminal!(Comma,","); re_terminal!(AndAnd,"&&"); re_terminal!(Ampersand,"&"); re_terminal!(DotDotDot,"\\.\\.\\."); re_terminal!(DotDot,"\\.\\."); re_terminal!(Dot,"\\."); re_terminal!(ModSep,"::"); re_terminal!(Colon,":"); re_terminal!(Caret,"\\^"); re_terminal!(Percent,"%"); re_terminal!(Semicolon,";"); re_terminal!(Bang,"!"); re_terminal!(At,"@"); re_terminal!(Star,"\\*"); re_terminal!(QuestionMark,"\\?"); re_terminal!(LBracket,"\\["); re_terminal!(RBracket,"\\]"); re_terminal!(LPar,"\\("); re_terminal!(RPar,"\\)"); re_terminal!(LBrace,"\\{"); re_terminal!(RBrace,"\\}"); re_terminal!(LT,"<"); re_terminal!(GT,">"); re_terminal!(Plus,"\\+"); re_terminal!(Minus,"-"); re_terminal!(_,"\\s+|\n|\\\\[^\n]*\n");//Otherwise skip spaces and normal comments re_terminal!(Slash,"/"); //////////////////////////////////////////////////////////////////////// // Part 1: Items and attributes //////////////////////////////////////////////////////////////////////// nonterminal WholeCrate(Vec>) { (MaybeShebang,InnerAttrs,MaybeModItems(ref items)) => items.clone(), (MaybeShebang,MaybeModItems(ref items)) => items.clone(), } nonterminal MaybeShebang { (ShebangLine) => (), () => (), } nonterminal MaybeInnerAttrs { (InnerAttrs) => (), () => (), } nonterminal InnerAttrs { (InnerAttr) => (), (InnerAttrs,InnerAttr) => (), } nonterminal InnerAttr { (Shebang,LBracket,MetaItem,RBracket) => (), (InnerDocComment) => (), } nonterminal MaybeOuterAttrs(Vec) { (OuterAttrs(ref attrs)) => attrs.clone(), () => vec![], } nonterminal OuterAttrs(Vec) { (OuterAttr(ref kind)) => vec![kind.clone()], (OuterAttrs(ref attrs),OuterAttr(ref attr)) => { let mut new=(attrs.clone()); new.push(attr.clone()); new }, } nonterminal OuterAttr(AttrKind) { (NumberSign,LBracket,MetaItem(ref attr),RBracket) => attr.clone(), (OuterDocComment(ref string)) => AttrKind::Documentation(string.clone()), } nonterminal MetaItem(AttrKind) { (Ident(ref string)) => AttrKind::Flag(string.clone()), (Ident(ref string),Equal,Lit(ref lit)) => AttrKind::Value(string.clone(),lit.clone()), (Ident(ref string),LPar,MetaSeq(ref seq),RPar) => AttrKind::Sequence(string.clone(),seq.clone()), (Ident(ref string),LPar,MetaSeq(ref seq),Comma,RPar) => AttrKind::Sequence(string.clone(),seq.clone()), } nonterminal MetaSeq(Vec) { () => vec![], (MetaItem(ref attr)) => vec![attr.clone()], (MetaSeq(ref seq),Comma,MetaItem(ref attr)) => { let mut new=(seq.clone()); new.push(attr.clone()); new }, } nonterminal MaybeModItems(Vec>) { (ModItems(ref items)) => items.clone(), () => vec![], } nonterminal ModItems(Vec>) { (ModItem(ref outer,ref item)) => vec![Rc::new(Token::ModItem(outer.clone(),item.clone()))], (ModItems(ref items),ModItem(ref outer,ref item)) => { let mut new=(items.clone()); new.push(Rc::new(Token::ModItem(outer.clone(),item.clone()))); new }, } nonterminal AttrsAndVis(Vec) { (MaybeOuterAttrs(ref attrs),Visibility) => attrs.clone(), } nonterminal ModItem(Vec,ItemKind) { (AttrsAndVis(ref attrs),Item(ref item)) => (attrs.clone(),item.clone()), } // items that can appear outside of a fn block nonterminal Item(ItemKind) { (StmtItem(ref item)) => item.clone(), (ItemMacro(ref item)) => item.clone(), } // items that can appear in "stmts" nonterminal StmtItem(ItemKind) { (ItemStatic) => ItemKind::Fixme, (ItemConst) => ItemKind::Fixme, (ItemType) => ItemKind::Fixme, (BlockItem(ref item)) => item.clone(), (ViewItem(ref view)) => ItemKind::View(view.clone()), } nonterminal ItemStatic { (Static,Ident,Colon,Ty,Equal,Expr,Semicolon) => (), (Static,Mut,Ident,Colon,Ty,Equal,Expr,Semicolon) => (), } nonterminal ItemConst { (Const,Ident,Colon,Ty,Equal,Semicolon) => (), } nonterminal ItemMacro(ItemKind) { (PathExpr(ref s),Bang,MaybeIdent,ParensDelimitedTokenTrees(ref trees),Semicolon) => ItemKind::Macro(Rc::new(Token::PathExpr(s.clone())),None,Rc::new(Token::ParensDelimitedTokenTrees(trees.clone()))), (PathExpr(ref s),Bang,MaybeIdent,BracesDelimitedTokenTrees(ref trees)) => ItemKind::Macro(Rc::new(Token::PathExpr(s.clone())),None,Rc::new(Token::BracesDelimitedTokenTrees(trees.clone()))), (PathExpr(ref s),Bang,MaybeIdent,BracketsDelimitedTokenTrees(ref trees),Semicolon) => ItemKind::Macro(Rc::new(Token::PathExpr(s.clone())),None,Rc::new(Token::BracketsDelimitedTokenTrees(trees.clone()))), } nonterminal ViewItem(ViewKind) { (UseItem(ref view)) => view.clone(), (ExternFnItem) => ViewKind::Fixme, (Extern,Crate,Ident(ref string),Semicolon) => ViewKind::ExternCrate(string.clone(),None), (Extern,Crate,Ident(ref string),As,Ident(ref string_as),Semicolon) => ViewKind::ExternCrate(string.clone(),Some(string_as.clone())), } nonterminal ExternFnItem { (Extern,MaybeAbi,ItemFn) => (), } nonterminal UseItem(ViewKind) { (Use,ViewPath(ref view),Semicolon) => view.clone(), } nonterminal ViewPath(ViewKind) { (PathNoTypesAllowed(ref path)) => ViewKind::Path(path.clone(),None), (PathNoTypesAllowed(ref path),ModSep,LBrace,RBrace) => ViewKind::Selection(Some(path.clone()),vec![]), (ModSep,LBrace,RBrace) => ViewKind::Selection(None,vec![]), (PathNoTypesAllowed(ref path),ModSep,LBrace,IdentsOrSelf(ref idents),RBrace) => ViewKind::Selection(Some(path.clone()),idents.clone()), (ModSep,LBrace,IdentsOrSelf(ref idents),RBrace) => ViewKind::Selection(None,idents.clone()), (PathNoTypesAllowed(ref path),ModSep,LBrace,IdentsOrSelf(ref idents),Comma,RBrace) => ViewKind::Selection(Some(path.clone()),idents.clone()), (ModSep,LBrace,IdentsOrSelf(ref idents),Comma,RBrace) => ViewKind::Selection(None,idents.clone()),//FIXME what is the point of :: ? (PathNoTypesAllowed(ref path),ModSep,Star) => ViewKind::All(Some(path.clone())), (ModSep,Star) => ViewKind::All(None),//FIXME what is this '::' ? (Star) => ViewKind::All(None), (LBrace,RBrace) => ViewKind::Selection(None,vec![]), (LBrace,IdentsOrSelf(ref idents),RBrace) => ViewKind::Selection(None,idents.clone()), (LBrace,IdentsOrSelf(ref idents),Comma,RBrace) => ViewKind::Selection(None,idents.clone()), (PathNoTypesAllowed(ref path),As,Ident(ref string)) => ViewKind::Path(path.clone(),Some(string.clone())), } nonterminal BlockItem(ItemKind) { (ItemFn(ref item)) => item.clone(), (ItemUnsafeFn) => ItemKind::Fixme, (ItemMod) => ItemKind::Fixme, (ItemForeignMod) => ItemKind::Fixme, (ItemStruct(ref item)) => item.clone(), (ItemEnum(ref item)) => item.clone(), (ItemUnion) => ItemKind::Fixme, (ItemTrait) => ItemKind::Fixme, (ItemImpl(ref item)) => item.clone(), (ItemTerminal(ref item)) => item.clone(),//NEW (ItemNonterminal(ref item)) => item.clone(),//NEW } nonterminal MaybeTyAscription(Option) { (Colon,TySum(ref qtype)) => Some(qtype.clone()), () => None, } nonterminal MaybeInitExpr(Option) { (Equal,Expr(ref expr)) => Some(expr.clone()), () => None, } //structs nonterminal ItemStruct(ItemKind) { (Struct,Ident(ref name),GenericParams(ref lifetimes, ref gp),MaybeWhereClause,StructDeclArgs(ref fields)) => ItemKind::Struct(name.clone(),lifetimes.clone(),gp.clone(),fields.clone()), (Struct,Ident,GenericParams,StructTupleArgs,MaybeWhereClause,Semicolon) => ItemKind::Fixme, (Struct,Ident,GenericParams,MaybeWhereClause,Semicolon) => ItemKind::Fixme, } nonterminal StructDeclArgs(Vec<(String,TyLf)>) { (LBrace,StructDeclFields(ref fields),RBrace) => fields.clone(), //(LBrace,StructDeclFields,RBrace,Comma) => (),//Wrong (LBrace,StructDeclFields(ref fields),Comma,RBrace) => fields.clone(), } nonterminal StructTupleArgs { (LPar,StructTupleFields,RPar) => (), (LPar,StructTupleFields,RPar,Comma) => (), } nonterminal StructDeclFields(Vec<(String,TyLf)>) { (StructDeclField(ref string, ref t)) => vec![(string.clone(),t.clone())], (StructDeclFields(ref list),Comma,StructDeclField(ref string, ref t)) => { let mut new=(list.clone()); new.push((string.clone(),t.clone())); new }, () => vec![], } nonterminal StructDeclField(String,TyLf) { (AttrsAndVis,Ident(ref string),Colon,TySum(ref t)) => (string.clone(),t.clone()), } nonterminal StructTupleFields { (StructTupleField) => (), (StructTupleFields,Comma,StructTupleField) => (), () => (), } nonterminal StructTupleField { (AttrsAndVis,TySum) => (), } // enums nonterminal ItemEnum(ItemKind) { (Enum,Ident(ref id),GenericParams(ref lifetimes, ref params),MaybeWhereClause,LBrace,EnumDefs(ref defs),RBrace) => ItemKind::Enum(id.clone(),lifetimes.clone(),params.clone(),defs.clone()), //(Enum,Ident,GenericParams,MaybeWhereClause,LBrace,EnumDefs,RBrace,Comma) => (),//Errata when copying (Enum,Ident(ref id),GenericParams(ref lifetimes, ref params),MaybeWhereClause,LBrace,EnumDefs(ref defs),Comma,RBrace) => ItemKind::Enum(id.clone(),lifetimes.clone(),params.clone(),defs.clone()), } nonterminal EnumDefs(Vec<(String,Vec)>) { (EnumDef(ref id, ref arguments)) => vec![(id.clone(),arguments.clone())], (EnumDefs(ref list),Comma,EnumDef(ref id, ref arguments)) => { let mut new=(list.clone()); new.push((id.clone(),arguments.clone())); new }, () => vec![], } nonterminal EnumDef(String,Vec) { (AttrsAndVis,Ident(ref string),EnumArgs(ref arguments)) => (string.clone(),arguments.clone()), } nonterminal EnumArgs(Vec) { (LBrace,StructDeclFields,RBrace) => vec![],//FIXME (LBrace,StructDeclFields,Comma,RBrace) => vec![],//FIXME (LPar,MaybeTySums(ref list),RPar) => list.clone(), (Equal,Expr) => vec![],//FIXME () => vec![], } // unions nonterminal ItemUnion { (Union,Ident,GenericParams,MaybeWhereClause,LBrace,StructDeclFields,RBrace) => (), (Union,Ident,GenericParams,MaybeWhereClause,LBrace,StructDeclFields,Comma,RBrace) => (), } nonterminal ItemMod { (Mod,Ident,Semicolon) => (), (Mod,Ident,LBrace,MaybeModItems,RBrace) => (), (Mod,Ident,LBrace,InnerAttrs,MaybeModItems,RBrace) => (), } nonterminal ItemForeignMod { (Extern,MaybeAbi,LBrace,MaybeForeignItems,RBrace) => (), (Extern,MaybeAbi,LBrace,InnerAttrs,MaybeForeignItems,RBrace) => (), } nonterminal MaybeAbi { (Str) => (), () => (), } nonterminal MaybeForeignItems { (ForeignItems) => (), () => (), } nonterminal ForeignItems { (ForeignItem) => (), (ForeignItems,ForeignItem) => (), } nonterminal ForeignItem { (AttrsAndVis,Static,ItemForeignStatic) => (), (AttrsAndVis,ItemForeignFn) => (), (AttrsAndVis,Unsafe,ItemForeignFn) => (), } nonterminal ItemForeignStatic { (MaybeMut,Ident,Colon,Ty,Semicolon) => (), } nonterminal ItemForeignFn { (FN,Ident,GenericParams,FnDeclAllowVariadic,MaybeWhereClause,Semicolon) => (), } nonterminal FnDeclAllowVariadic { (FnParamsAllowVariadic,RetTy) => (), } nonterminal FnParamsAllowVariadic { (LPar,RPar) => (), (LPar,Params,RPar) => (), (LPar,Params,Comma,RPar) => (), (LPar,Params,Comma,DotDotDot,RPar) => (), } nonterminal Visibility { (Pub) => (), () => (), } nonterminal IdentsOrSelf(Vec) { (IdentOrSelf(ref string)) => vec![string.clone()], (IdentsOrSelf(ref list),As,Ident) => list.clone(),//FIXME (IdentsOrSelf(ref list),Comma,IdentOrSelf(ref string)) => { //let mut new=list.clone();//FIXME let mut new=(list.clone()); new.push(string.clone()); new }, } nonterminal IdentOrSelf(String) { (Ident(ref string)) => string.clone(), (LittleSelf) => String::from("self"), } nonterminal ItemType { (Type,Ident,GenericParams,MaybeWhereClause,Equal,TySum,Semicolon) => (), } nonterminal ForSized { (For,QuestionMark,Ident) => (), (For,Ident,QuestionMark) => (), () => (), } nonterminal ItemTrait { (MaybeUnsafe,Trait,Ident,GenericParams,ForSized,MaybeTyParamBounds,MaybeWhereClause,LBrace,MaybeTraitItems,RBrace) => (), } nonterminal MaybeTraitItems { (TraitItems) => (), () => (), } nonterminal TraitItems { (TraitItem) => (), (TraitItems,TraitItem) => (), } nonterminal TraitItem { (TraitConst) => (), (TraitType) => (), (TraitMethod) => (), (MaybeOuterAttrs,ItemMacro) => (), } nonterminal TraitConst { (MaybeOuterAttrs,Const,Ident,MaybeTyAscription,MaybeConstDefault,Semicolon) => (), } nonterminal MaybeConstDefault { (Equal,Expr) => (), () => (), } nonterminal TraitType { (MaybeOuterAttrs,Type,TyParam,Semicolon) => (), } nonterminal MaybeUnsafe { (Unsafe) => (), () => (), } nonterminal MaybeDefaultMaybeUnsafe { (DEFAULT,Unsafe) => (), (Unsafe) => (), (Unsafe) => (), () => (), } nonterminal TraitMethod { (TypeMethod) => (), (Method) => (), } nonterminal TypeMethod { (MaybeOuterAttrs,MaybeUnsafe,FN,Ident,GenericParams,FnDeclWithSelfAllowAnonParams,MaybeWhereClause,Semicolon) => (), (MaybeOuterAttrs,Const,MaybeUnsafe,FN,Ident,GenericParams,FnDeclWithSelfAllowAnonParams,MaybeWhereClause,Semicolon) => (), (MaybeOuterAttrs,MaybeUnsafe,Extern,MaybeAbi,FN,Ident,GenericParams,FnDeclWithSelfAllowAnonParams,MaybeWhereClause,Semicolon) => (), } nonterminal Method { (MaybeOuterAttrs,MaybeUnsafe,FN,Ident,GenericParams,FnDeclWithSelfAllowAnonParams,MaybeWhereClause,InnerAttrsAndBlock) => (), (MaybeOuterAttrs,Const,MaybeUnsafe,FN,Ident,GenericParams,FnDeclWithSelfAllowAnonParams,MaybeWhereClause,InnerAttrsAndBlock) => (), (MaybeOuterAttrs,MaybeUnsafe,Extern,MaybeAbi,FN,Ident,GenericParams,FnDeclWithSelfAllowAnonParams,MaybeWhereClause,InnerAttrsAndBlock) => (), } nonterminal ImplMethod(ItemKind) { (AttrsAndVis,MaybeDefault,MaybeUnsafe,FN,Ident(ref name),GenericParams(ref lifetimes,ref gp),FnDeclWithSelf(has_self, has_ref, has_mut, ref ot_self, ref params, ref oret),MaybeWhereClause,InnerAttrsAndBlock(ref stmts,ref be)) => ItemKind::Method(name.clone(),lifetimes.clone(),gp.clone(),has_self,has_ref,has_mut,ot_self.clone(),params.clone(),oret.clone(),stmts.clone(),be.clone()), (AttrsAndVis,MaybeDefault,Const,MaybeUnsafe,FN,Ident,GenericParams,FnDeclWithSelf,MaybeWhereClause,InnerAttrsAndBlock) => ItemKind::Fixme, (AttrsAndVis,MaybeDefault,MaybeUnsafe,Extern,MaybeAbi,FN,Ident,GenericParams,FnDeclWithSelf,MaybeWhereClause,InnerAttrsAndBlock) => ItemKind::Fixme, } // --- BISON NOTES --- // There are two forms of impl: // // impl (<...>)? TY { ... } // impl (<...>)? TRAIT for TY { ... } // // Unfortunately since TY can begin with '<' itself -- as part of a // TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL: // should we reduce one of the early rules of TY (such as maybe_once) // or shall we continue shifting into the generic_params list for the // impl? // // The production parser disambiguates a different case here by // permitting / requiring the user to provide parens around types when // they are ambiguous with traits. We do the same here, regrettably, // by splitting ty into ty and ty_prim. nonterminal ItemImpl(ItemKind) { (MaybeDefaultMaybeUnsafe,Impl,GenericParams(ref lifetimes,ref gp),TyPrimSum(ref t),MaybeWhereClause,LBrace,MaybeInnerAttrs,MaybeImplItems(ref items),RBrace) => ItemKind::Impl(lifetimes.clone(),gp.clone(),None,t.clone(),items.clone()), (MaybeDefaultMaybeUnsafe,Impl,GenericParams,LPar,Ty,RPar,MaybeWhereClause,LBrace,MaybeInnerAttrs,MaybeImplItems,RBrace) => ItemKind::Fixme, (MaybeDefaultMaybeUnsafe,Impl,GenericParams(ref lifetimes, ref gp),TraitRef(ref path),For,TySum(ref t),MaybeWhereClause,LBrace,MaybeInnerAttrs,MaybeImplItems(ref items),RBrace) => ItemKind::Impl(lifetimes.clone(),gp.clone(),Some(path.clone()),t.clone(),items.clone()), (MaybeDefaultMaybeUnsafe,Impl,GenericParams,Bang,TraitRef,For,TySum,MaybeWhereClause,LBrace,MaybeInnerAttrs,MaybeImplItems,RBrace) => ItemKind::Fixme, (MaybeDefaultMaybeUnsafe,Impl,GenericParams,TraitRef,For,DotDot,LBrace,RBrace) => ItemKind::Fixme, (MaybeDefaultMaybeUnsafe,Impl,GenericParams,Bang,TraitRef,For,DotDot,LBrace,RBrace) => ItemKind::Fixme, } nonterminal MaybeImplItems(Vec) { (ImplItems(ref items)) => items.clone(), () => vec![], } nonterminal ImplItems(Vec) { (ImplItem(ref item)) => vec![item.clone()], (ImplItem(ref item),ImplItems(ref list)) => { let mut new=vec![item.clone()]; //new.extend(list); new.extend(list.iter().map( |x|(x.clone()) )); new }, } nonterminal ImplItem(ItemKind) { (ImplMethod(ref item)) => item.clone(), (AttrsAndVis,ItemMacro) => ItemKind::Fixme, (ImplConst) => ItemKind::Fixme, (ImplType) => ItemKind::Fixme, } nonterminal MaybeDefault { (DEFAULT) => (), () => (), } nonterminal ImplConst { (AttrsAndVis,MaybeDefault,ItemConst) => (), } nonterminal ImplType { (AttrsAndVis,MaybeDefault,Type,Ident,GenericParams,Equal,TySum,Semicolon) => (), } nonterminal ItemFn(ItemKind) { (FN,Ident(ref name),GenericParams(ref lives, ref gp),FnDecl(ref params,ref rt),MaybeWhereClause,InnerAttrsAndBlock(ref block_stmts, ref block_expr)) => (ItemKind::FN(name.clone(),lives.clone(),gp.clone(),params.clone(),rt.clone(),block_stmts.clone(),block_expr.clone())), (Const,FN,Ident(ref name),GenericParams(ref lives, ref gp),FnDecl(ref params,ref rt),MaybeWhereClause,InnerAttrsAndBlock(ref block_stmts, ref block_expr)) => (ItemKind::FN(name.clone(),lives.clone(),gp.clone(),params.clone(),rt.clone(),block_stmts.clone(),block_expr.clone())), } nonterminal ItemUnsafeFn { (Unsafe,FN,Ident,GenericParams,FnDecl,MaybeWhereClause,InnerAttrsAndBlock) => (), (Const,Unsafe,FN,Ident,GenericParams,FnDecl,MaybeWhereClause,InnerAttrsAndBlock) => (), (Unsafe,Extern,MaybeAbi,FN,Ident,GenericParams,FnDecl,MaybeWhereClause,InnerAttrsAndBlock) => (), } nonterminal FnDecl(Vec<(PatKind,TyLf)>,Option) { (FnParams(ref params),RetTy(ref ot)) => (params.clone(),ot.clone()), } nonterminal FnDeclWithSelf(bool,bool,bool,Option,Vec<(PatKind,TyLf)>,Option) { (FnParamsWithSelf(has_self, has_ref, has_mut, ref ot_self, ref params),RetTy(ref oret)) => (has_self,has_ref,has_mut,ot_self.clone(),params.clone(),oret.clone()), } nonterminal FnDeclWithSelfAllowAnonParams { (FnAnonParamsWithSelf,RetTy) => (), } nonterminal FnParams(Vec<(PatKind,TyLf)>) { (LPar,MaybeParams(ref params),RPar) => params.clone(), } nonterminal FnAnonParams { (LPar,AnonParam,AnonParamsAllowVariadicTail,RPar) => (), (LPar,RPar) => (), } nonterminal FnParamsWithSelf(bool,bool,bool,Option,Vec<(PatKind,TyLf)>)//has self, has &, has mut, self_type, other_params { (LPar,MaybeMut(ismut),LittleSelf,MaybeTyAscription(ref ot),MaybeCommaParams(ref params),RPar) => (true,false,ismut,ot.clone(),params.clone()), (LPar,Ampersand,MaybeMut(ismut),LittleSelf,MaybeTyAscription(ref ot),MaybeCommaParams(ref params),RPar) => (true,true,ismut,ot.clone(),params.clone()), (LPar,Ampersand,Lifetime,MaybeMut(ismut),LittleSelf,MaybeTyAscription(ref ot),MaybeCommaParams(ref params),RPar) => (true,true,ismut,ot.clone(),params.clone()),//FIXME: lifetime (LPar,MaybeParams(ref params),RPar) => (false,false,false,None,params.clone()), } nonterminal FnAnonParamsWithSelf { (LPar,MaybeMut,LittleSelf,MaybeTyAscription,MaybeCommaAnonParams,RPar) => (), (LPar,Ampersand,MaybeMut,LittleSelf,MaybeTyAscription,MaybeCommaAnonParams,RPar) => (), (LPar,Ampersand,Lifetime,MaybeMut,LittleSelf,MaybeTyAscription,MaybeCommaAnonParams,RPar) => (), (LPar,MaybeAnonParams,RPar) => (), } nonterminal MaybeParams(Vec<(PatKind,TyLf)>) { (Params(ref params)) => params.clone(), (Params(ref params),Comma) => params.clone(), () => vec![], } nonterminal Params(Vec<(PatKind,TyLf)>) { (Param(ref pattern, ref t)) => vec![(pattern.clone(),t.clone())], (Params(ref list),Comma,Param(ref pattern, ref t)) => { let mut new=(list.clone()); new.push((pattern.clone(),t.clone())); new }, } nonterminal Param(PatKind,TyLf) { (Pat(ref pattern),Colon,TySum(ref t)) => (pattern.clone(),t.clone()), } nonterminal InferrableParams(Vec<(PatKind,Option)>) { (InferrableParam(ref pattern, ref ot)) => (vec![(pattern.clone(),ot.clone())]), (InferrableParams(ref params),Comma,InferrableParam(ref pattern, ref ot)) => { let mut new=(params.clone()); new.push((pattern.clone(),ot.clone())); new }, } nonterminal InferrableParam(PatKind,Option) { (Pat(ref pat),MaybeTyAscription(ref ot)) => (pat.clone(),ot.clone()), } nonterminal MaybeCommaParams(Vec<(PatKind,TyLf)>) { (Comma) => vec![], (Comma,Params(ref params)) => params.clone(), (Comma,Params(ref params),Comma) => params.clone(), () => vec![], } nonterminal MaybeCommaAnonParams { (Comma) => (), (Comma,AnonParams) => (), (Comma,AnonParams,Comma) => (), () => (), } nonterminal MaybeAnonParams { (AnonParams) => (), (AnonParams, Comma) => (), () => (), } nonterminal AnonParams { (AnonParam) => (), (AnonParams,Comma,AnonParam) => (), } // anon means it's allowed to be anonymous (type-only), but it can // still have a name nonterminal AnonParam { (NamedArg,Colon,Ty) => (), (Ty) => (), } nonterminal AnonParamsAllowVariadicTail { (Comma,DotDotDot) => (), (Comma,AnonParam,AnonParamsAllowVariadicTail) => (), () => (), } nonterminal NamedArg { (Ident) => (), (Underscore) => (), (Ampersand,Ident) => (), (Ampersand,Underscore) => (), (AndAnd,Ident) => (), (AndAnd,Underscore) => (), (Mut,Ident) => (), } nonterminal RetTy(Option) { (RArrow,Bang) => Some(TyKind::Fixme), (RArrow,Ty(ref t)) => Some(t.clone()), () => None, } nonterminal GenericParams(Vec,Vec) { (LT,GT,MaybeSpace) => (vec![],vec![]), (LT,Lifetimes(ref lives),GT,MaybeSpace) => (lives.clone(),vec![]), (LT,Lifetimes(ref lives),Comma,GT,MaybeSpace) => (lives.clone(),vec![]), //(LT,Lifetimes,SHR) => (), //(LT,Lifetimes,Comma,SHR) => (), //Tricky with bison: push_back('>'); (LT,Lifetimes(ref lives),Comma,TyParams(ref params),GT,MaybeSpace) => (lives.clone(),params.clone()), (LT,Lifetimes(ref lives),Comma,TyParams(ref params),Comma,GT,MaybeSpace) => (lives.clone(),params.clone()), //(LT,Lifetimes,Comma,TyParams(ref params),SHR) => (), //(LT,Lifetimes,Comma,TyParams(ref params),COMMA,SHR) => (), (LT,TyParams(ref params),GT) => (vec![],params.clone()), (LT,TyParams(ref params),Comma,GT) => (vec![],params.clone()), //(LT,TyParams,SHR) => (), //(LT,TyParams,Comma,SHR) => (), () => (vec![],vec![]), } nonterminal MaybeWhereClause { () => (), (WhereClause) => (), } nonterminal WhereClause { (Where,WherePredicates) => (), (Where,WherePredicates,Comma) => (), } nonterminal WherePredicates { (WherePredicate) => (), (WherePredicates,Comma,WherePredicate) => (), } nonterminal WherePredicate { (MaybeForLifetimes,Lifetime,Colon,Bounds) => (), (MaybeForLifetimes,Ty,Colon,TyParamBounds) => (), } nonterminal MaybeForLifetimes { (For,LT,Lifetimes,GT) => (), () => (), //bison precedence of FORTYPE } nonterminal TyParams(Vec) { (TyParam(ref param)) => vec![param.clone()], (TyParams(ref list),Comma,TyParam(ref param)) => { let mut new=(list.clone()); new.push(param.clone()); new }, } // A path with no type parameters; e.g. `foo::bar::Baz` // // These show up in 'use' view-items, because these are processed // without respect to types. nonterminal PathNoTypesAllowed(PathNKind) { (Ident(ref string)) => PathNKind::Ident(string.clone()), (ModSep,Ident(ref string)) => PathNKind::AbsoluteIdent(string.clone()), (LittleSelf) => PathNKind::FromSelf, (ModSep,LittleSelf) => PathNKind::AbsoluteSelf, (Super) => PathNKind::Super, (ModSep,Super) => PathNKind::AbsoluteSuper, (PathNoTypesAllowed(ref path),ModSep,Ident(ref string)) => PathNKind::Step(Rc::new(path.clone()),string.clone()), } // A path with a lifetime and type parameters, with no double colons // before the type parameters; e.g. `foo::bar<'a>::Baz` // // These show up in "trait references", the components of // type-parameter bounds lists, as well as in the prefix of the // path_generic_args_and_bounds rule, which is the full form of a // named typed expression. // // They do not have (nor need) an extra '::' before '<' because // unlike in expr context, there are no "less-than" type exprs to // be ambiguous with. nonterminal PathGenericArgsWithoutColons(PathWKind) { (Ident(ref string)) => PathWKind::Ident(string.clone()), (Ident(ref string),GenericArgs(ref gens)) => PathWKind::IdentGeneric(string.clone(),gens.clone()), (Ident(ref string),LPar,MaybeTySums(ref list),RPar,RetTy) => PathWKind::Function(string.clone(),list.clone(),Rc::new(state.values[4].clone())), (PathGenericArgsWithoutColons(ref path),ModSep,Ident(ref string)) => PathWKind::StepIdent(Rc::new(path.clone()),string.clone()), (PathGenericArgsWithoutColons(ref path),ModSep,Ident(ref string),GenericArgs(ref gens)) => PathWKind::StepIdentGeneric(Rc::new(path.clone()),string.clone(),gens.clone()), (PathGenericArgsWithoutColons(ref path),ModSep,Ident(ref string),LPar,MaybeTySums(ref list),RPar,RetTy) => PathWKind::StepFunction(Rc::new(path.clone()),string.clone(),list.clone(),Rc::new(state.values[6].clone())), } nonterminal GenericArgs(Vec) { (LT,MaybeSpace,GenericValues(ref list),GT,MaybeSpace) => list.clone(), //(LT,GenericValues,SHR) => (), //push_back magic (LT,MaybeSpace,GenericValues(ref list),GE,MaybeSpace) => list.clone(), //(LT,GenericValues,SHREQ) => (), //(SHL,TyQualifiedPathAndGenericValues,GT) => (), //(SHL,TyQualifiedPathAndGenericValues,SHR) => (), //(SHL,TyQualifiedPathAndGenericValues,GE) => (), //(SHL,TyQualifiedPathAndGenericValues,SHREQ) => (), } nonterminal GenericValues(Vec) { (MaybeTySumsAndOrBindings(ref list)) => list.clone(), } nonterminal MaybeTySumsAndOrBindings(Vec) { (TySums(ref list)) => list.clone(), (TySums(ref list),Comma) => list.clone(), (TySums(ref list),Comma,Bindings) => list.clone(), (Bindings) => vec![], (Bindings,Comma) => vec![], () => vec![], } nonterminal MaybeBindings { (Comma,Bindings) => (), () => (), } //////////////////////////////////////////////////////////////////////// // Part 2: Patterns //////////////////////////////////////////////////////////////////////// nonterminal Pat(PatKind) { (Underscore) => PatKind::Underscore, (Ampersand,Pat(ref kind)) => PatKind::Ref(Rc::new(kind.clone())), (Ampersand,Mut,Pat(ref kind)) => PatKind::RefMut(Rc::new(kind.clone())), (AndAnd,Mut,Pat(ref kind)) => PatKind::Ref(Rc::new(PatKind::RefMut(Rc::new(kind.clone())))), (LPar,RPar) => PatKind::Void, (LPar,PatTup(ref patterns),RPar) => PatKind::Tuple(patterns.clone()), (LBracket,PatVec,RBracket) => PatKind::Fixme, (LitOrPath(ref path)) => PatKind::Path(path.clone()), (LitOrPath,DotDotDot,LitOrPath) => PatKind::Fixme, (PathExpr,LBrace,PatStruct,RBrace) => PatKind::Fixme, (PathExpr,LPar,RPar) => PatKind::EnumEmpty(Rc::new(state.values[0].clone())), (PathExpr,LPar,PatTup(ref patterns),RPar) => PatKind::Enum(Rc::new(state.values[0].clone()),patterns.clone()), (PathExpr,Bang,MaybeIdent,DelimitedTokenTrees) => PatKind::Fixme, (BindingMode(ref bind),Ident(ref string)) => PatKind::BindedIdent(bind.clone(),string.clone()), (Ident,At,Pat) => PatKind::Fixme, (BindingMode,Ident,At,Pat) => PatKind::Fixme, (BOX,Pat) => PatKind::Fixme, (LT,TySum,MaybeAsTraitRef,GT,ModSep,Ident) => PatKind::Fixme, //(SHL,TySum,MaybeAsTraitRef,GT,ModSep,Ident,MaybeAsTraitRef,GT,ModSep,Ident) => (), } nonterminal PatsOr(PatKind) { //(Pat) => Rc::new(state.values[0].clone()), (Pat(ref kind)) => kind.clone(), (PatsOr(ref kind),Vertical,Pat) => kind.clone(),//FIXME } nonterminal BindingMode(BindKind) { (Ref) => BindKind::Ref, (Ref,Mut) => BindKind::RefMut, (Mut) => BindKind::Mut, } nonterminal LitOrPath(PathKind) { (PathExpr(ref path)) => path.clone(), (Lit(ref token)) => PathKind::Literal(token.clone()), (Minus,Lit) => PathKind::Fixme, } nonterminal PatField { (Ident) => (), (BindingMode,Ident) => (), (BOX,Ident) => (), (BOX,BindingMode,Ident) => (), (Ident,Colon,Pat) => (), (BindingMode,Ident,Colon,Pat) => (), (LitInteger,Colon,Pat) => (), } nonterminal PatFields { (PatField) => (), (PatFields,Comma,PatField) => (), } nonterminal PatStruct { (PatFields) => (), (PatFields,Comma) => (), (PatFields,Comma,DotDot) => (), (DotDot) => (), () => (), } nonterminal PatTup(Vec) { (PatTupElts(ref elements)) => elements.clone(), (PatTupElts(ref elements),Comma) => elements.clone(), (PatTupElts(ref elements),DotDot) => vec![],//FIXME (PatTupElts(ref elements),Comma,DotDot) => vec![],//FIXME (PatTupElts(ref elements),DotDot,Comma,PatTupElts) => vec![],//FIXME (PatTupElts(ref elements),DotDot,Comma,PatTupElts,Comma) => vec![],//FIXME (PatTupElts(ref elements),Comma,DotDot,Comma,PatTupElts) => vec![],//FIXME (PatTupElts(ref elements),Comma,DotDot,Comma,PatTupElts,Comma) => vec![],//FIXME (DotDot,Comma,PatTupElts) => vec![],//FIXME (DotDot,Comma,PatTupElts,Comma) => vec![],//FIXME (DotDot) => vec![],//FIXME } nonterminal PatTupElts(Vec) { (Pat(ref pattern)) => vec![pattern.clone()], (PatTupElts(ref elements),Comma,Pat(ref pattern)) => { let mut new=(elements.clone()); new.push(pattern.clone()); new }, } nonterminal PatVec { (PatVecElts) => (), (PatVecElts,Comma) => (), (PatVecElts,DotDot) => (), (PatVecElts,Comma,DotDot) => (), (PatVecElts,DotDot,Comma,PatVecElts) => (), (PatVecElts,DotDot,Comma,PatVecElts,Comma) => (), (PatVecElts,Comma,DotDot,Comma,PatVecElts) => (), (PatVecElts,Comma,DotDot,Comma,PatVecElts,Comma) => (), (DotDot,Comma,PatVecElts) => (), (DotDot,Comma,PatVecElts,Comma) => (), (DotDot) => (), () => (), } nonterminal PatVecElts { (Pat) => (), (PatVecElts,Comma,Pat) => (), } //////////////////////////////////////////////////////////////////////// // Part 3: Types //////////////////////////////////////////////////////////////////////// nonterminal Ty(TyKind) { (TyPrim(ref kind)) => kind.clone(), (TyClosure) => TyKind::Fixme, (LT,TySum,MaybeAsTraitRef,GT,ModSep,Ident) => TyKind::Fixme, //(SHL,TySum,MaybeAsTraitRef,GT,ModSep,Ident,MaybeAsTraitRef,GT,ModSep,Ident) => (), (LPar,TySums(ref list),RPar) => TyKind::Tuple(list.clone()), (LPar,TySums(ref list),Comma,RPar) => TyKind::Tuple(list.clone()), (LPar,RPar) => TyKind::Void, } nonterminal TyPrim(TyKind) { (PathGenericArgsWithoutColons(ref string)) => TyKind::Path(string.clone()), (ModSep,PathGenericArgsWithoutColons) => TyKind::Fixme, (LittleSelf,ModSep,PathGenericArgsWithoutColons) => TyKind::Fixme, (PathGenericArgsWithoutColons,Bang,MaybeIdent,DelimitedTokenTrees) => TyKind::Fixme, (ModSep,PathGenericArgsWithoutColons,Bang,MaybeIdent,DelimitedTokenTrees) => TyKind::Fixme, (BOX,Ty) => TyKind::Fixme, (Star,MaybeMutOrConst,Ty) => TyKind::Fixme, (Ampersand,Ty(ref kind)) => TyKind::Ref(Rc::new(kind.clone())), (Ampersand,Mut,Ty(ref kind)) => TyKind::RefMut(Rc::new(kind.clone())), (AndAnd,Ty) => TyKind::Fixme, (AndAnd,Mut,Ty) => TyKind::Fixme, (Ampersand,Lifetime(ref lifetime),MaybeMut(ismut),Ty(ref t)) => TyKind::RefLifetime(lifetime.clone(),ismut,Rc::new(t.clone())), (LBracket,Ty,RBracket) => TyKind::Fixme, (LBracket,Ty,Comma,DotDot,Expr,RBracket) => TyKind::Fixme, (LBracket,Ty,Semicolon,Expr,RBracket) => TyKind::Fixme, (Typeof,LPar,Expr,RPar) => TyKind::Fixme, (Underscore) => TyKind::Underscore, (TyBareFn) => TyKind::Fixme, (ForInType) => TyKind::Fixme, } nonterminal TyBareFn { (FN,TyFnDecl) => (), (Unsafe,FN,TyFnDecl) => (), (Extern,FN,TyFnDecl) => (), (Unsafe,Extern,FN,TyFnDecl) => (), } nonterminal TyFnDecl { (GenericParams,FnAnonParams,RetTy) => (), } nonterminal TyClosure { (Unsafe,Vertical,AnonParams,Vertical,MaybeBounds,RetTy) => (), (Vertical,AnonParams,Vertical,MaybeBounds,RetTy) => (), (Unsafe,OrOr,MaybeBounds,RetTy) => (), (OrOr,MaybeBounds,RetTy) => (), } nonterminal ForInType { (For,LT,MaybeLifetimes,GT,ForInTypeSuffix) => (), } nonterminal ForInTypeSuffix { (TyBareFn) => (), (TraitRef) => (), (TyClosure) => (), } nonterminal MaybeMut(bool) { (Mut) => true, () => false, } nonterminal MaybeMutOrConst { (Mut) => (), (Const) => (), () => (), } nonterminal TyQualifiedPathAndGenericValues { (TyQualifiedPath,MaybeBindings) => (), (TyQualifiedPath,Comma,TySums,MaybeBindings) => (), } nonterminal TyQualifiedPath { (TySums,As,TraitRef,GT,ModSep,Ident) => (), (TySums,As,TraitRef,GT,ModSep,Ident,Plus,TyParamBounds) => (), } nonterminal MaybeTySums(Vec) { (TySums(ref qtypes)) => qtypes.clone(), (TySums(ref qtypes),Comma) => qtypes.clone(), () => vec![], } nonterminal TySums(Vec) { (TySum(ref t)) => vec![t.clone()], (TySums(ref qtypes),Comma,TySum(ref t)) => { let mut new=(qtypes.clone()); new.push(t.clone()); new }, } nonterminal TySum(TyLf) { (TySumElt(ref kind)) => kind.clone(), (TySum(ref kind),Plus,TySumElt) => kind.clone(),//FIXME } nonterminal TySumElt(TyLf) { (Ty(ref kind)) => TyLf::Type(kind.clone()), (Lifetime(ref string)) => TyLf::Lifetime(string.clone()), } nonterminal TyPrimSum(TyLf) { (TyPrimSumElt(ref t)) => t.clone(), (TyPrimSum(ref t),Plus,TyPrimSumElt) => t.clone(),//FIXME } nonterminal TyPrimSumElt(TyLf) { (TyPrim(ref t)) => TyLf::Type(t.clone()), (Lifetime(ref lifetime)) => TyLf::Lifetime(lifetime.clone()), } nonterminal MaybeTyParamBounds { (Colon,TyParamBounds) => (), () => (), } nonterminal TyParamBounds { (Boundseq) => (), () => (), } nonterminal Boundseq { (Polybound) => (), (Boundseq,Plus,Polybound) => (), } nonterminal Polybound { (For,LT,MaybeLifetimes,GT,Bound) => (), (Bound) => (), (QuestionMark,For,LT,MaybeLifetimes,GT,Bound) => (), (QuestionMark,Bound) => (), } nonterminal Bindings { (Binding) => (), (Bindings,Comma,Binding) => (), } nonterminal Binding { (Ident,Equal,Ty) => (), } nonterminal TyParam(String) { (Ident(ref s),MaybeTyParamBounds,MaybeTyDefault) => s.clone(),//FIXME (Ident(ref s),QuestionMark,Ident,MaybeTyParamBounds,MaybeTyDefault) => s.clone(),//FIXME } nonterminal MaybeBounds { (Colon,Bounds) => (), () => (), } nonterminal Bounds { (Bounds) => (), (Bounds,Plus,Bound) => (), } nonterminal Bound { (Lifetime) => (), (TraitRef) => (), } nonterminal MaybeLTBounds { (Colon,LTBounds) => (), () => (), } nonterminal LTBounds { (Lifetime) => (), (LTBounds,Plus,Lifetime) => (), } nonterminal MaybeTyDefault { (Equal,TySum) => (), () => (), } nonterminal MaybeLifetimes { (Lifetimes) => (), (Lifetimes,Comma) => (), () => (), } nonterminal Lifetimes(Vec) { (LifetimeAndBounds(ref string)) => vec![string.clone()], (Lifetimes(ref list),Comma,LifetimeAndBounds(ref lifetime)) => { let mut new=(list.clone()); new.push(lifetime.clone()); new }, } nonterminal LifetimeAndBounds(String) { (LiteralLifetime(ref string),MaybeLTBounds) => string.clone(), (StaticLifetime) => String::from("'static"), } nonterminal Lifetime(String) { (LiteralLifetime(ref string)) => string.clone(), (StaticLifetime) => String::from("'static"), } nonterminal TraitRef(PathWKind) { (PathGenericArgsWithoutColons(ref path)) => path.clone(), (ModSep,PathGenericArgsWithoutColons(ref path)) => path.clone(), } //////////////////////////////////////////////////////////////////////// // Part 4: Blocks, statements, and expressions //////////////////////////////////////////////////////////////////////// nonterminal InnerAttrsAndBlock(Vec,Option) { (LBrace,MaybeInnerAttrs,MaybeStmts(ref stmts, ref oe),RBrace) => (stmts.clone(),oe.clone()), } nonterminal Block(Vec,Option) { (LBrace,MaybeStmts(ref list,ref option),RBrace) => (list.clone(),option.clone()), } nonterminal MaybeStmts(Vec,Option) { (Stmts(ref list)) => (list.clone(),None), (Stmts(ref list),NonblockExpr(ref expr)) => (list.clone(),Some(expr.clone())), (NonblockExpr(ref expr)) => (vec![],Some(expr.clone())), () => (vec![],None), } // --- BISON NOTES --- // There are two sub-grammars within a "stmts: exprs" derivation // depending on whether each stmt-expr is a block-expr form; this is to // handle the "semicolon rule" for stmt sequencing that permits // writing // // if foo { bar } 10 // // as a sequence of two stmts (one if-expr stmt, one lit-10-expr // stmt). Unfortunately by permitting juxtaposition of exprs in // sequence like that, the non-block expr grammar has to have a // second limited sub-grammar that excludes the prefix exprs that // are ambiguous with binops. That is to say: // // {10} - 1 // // should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that // is to say, two statements rather than one, at least according to // the mainline rust parser. // // So we wind up with a 3-way split in exprs that occur in stmt lists: // block, nonblock-prefix, and nonblock-nonprefix. // // In non-stmts contexts, expr can relax this trichotomy. nonterminal Stmts(Vec) { (Stmt(ref stmt)) => vec![stmt.clone()], (Stmts(ref stmts),Stmt(ref stmt)) => { let mut new=(stmts.clone()); new.push(stmt.clone()); new }, } nonterminal Stmt(StmtKind) { (MaybeOuterAttrs,Let(ref stmt)) => stmt.clone(), (StmtItem(ref item)) => StmtKind::Item(vec![],item.clone()), (Pub,StmtItem(ref item)) => StmtKind::Item(vec![],item.clone()), (OuterAttrs(ref attrs),StmtItem(ref item)) => StmtKind::Item(attrs.clone(),item.clone()), (OuterAttrs(ref attrs),Pub,StmtItem(ref item)) => StmtKind::Item(attrs.clone(),item.clone()), (FullBlockExpr(ref block)) => StmtKind::Block(vec![],block.clone()), (MaybeOuterAttrs(ref attrs),Block) => StmtKind::Block(attrs.clone(),Rc::new(state.values[1].clone())), (NonblockExpr(ref expr),Semicolon) => StmtKind::Expr(vec![],expr.clone()), (OuterAttrs(ref attrs),NonblockExpr(ref expr),Semicolon) => StmtKind::Expr(attrs.clone(),expr.clone()), (Semicolon) => StmtKind::Empty, } nonterminal MaybeExprs(Vec) { (Exprs(ref list)) => list.clone(), (Exprs(ref list),Comma) => list.clone(), () => vec![], } nonterminal MaybeExpr(Option) { (Expr(ref expr)) => Some(expr.clone()), () => None, } nonterminal Exprs(Vec) { (Expr(ref expr)) => vec![expr.clone()], (Exprs(ref list),Comma,Expr(ref expr)) => { let mut new=(list.clone()); new.push(expr.clone()); new }, } nonterminal PathExpr(PathKind) { (PathGenericArgsWithColons(ref path)) => path.clone(), (ModSep,PathGenericArgsWithColons(ref path)) => PathKind::Absolute(Rc::new(path.clone())), (LittleSelf,ModSep,PathGenericArgsWithColons(ref path)) => PathKind::FromSelf(Rc::new(path.clone())), } // A path with a lifetime and type parameters with double colons before // the type parameters; e.g. `foo::bar::<'a>::Baz::` // // These show up in expr context, in order to disambiguate from "less-than" // expressions. nonterminal PathGenericArgsWithColons(PathKind) { (Ident(ref s)) => PathKind::Ident(s.clone()), (Super) => PathKind::Super, (PathGenericArgsWithColons(ref path),ModSep,Ident(ref s)) => PathKind::StepIdent(Rc::new(path.clone()),s.clone()), (PathGenericArgsWithColons(ref path),ModSep,Super) => PathKind::StepSuper(Rc::new(path.clone())), (PathGenericArgsWithColons(ref path),ModSep,GenericArgs(ref ga)) => PathKind::GenericArgs(Rc::new(path.clone()),ga.clone()), } // the braces-delimited macro is a block_expr so it doesn't appear here nonterminal MacroExpr(Rc,Option>,Rc) { (PathExpr(ref s),Bang,MaybeIdent,ParensDelimitedTokenTrees(ref trees)) => (Rc::new(Token::PathExpr(s.clone())),None,Rc::new(Token::ParensDelimitedTokenTrees(trees.clone()))), (PathExpr(ref s),Bang,MaybeIdent,BracketsDelimitedTokenTrees(ref trees)) => (Rc::new(Token::PathExpr(s.clone())),None,Rc::new(Token::BracketsDelimitedTokenTrees(trees.clone()))), } nonterminal NonblockExpr(ExprKind) { (Lit) => ExprKind::Single(Rc::new(state.values[0].clone())), (PathExpr) => ExprKind::Single(Rc::new(state.values[0].clone())), (LittleSelf) => ExprKind::Single(Rc::new(state.values[0].clone())), (MacroExpr) => ExprKind::Single(Rc::new(state.values[0].clone())), (PathExpr(ref path),LBrace,StructExprFields(ref fields),RBrace) => ExprKind::Struct(path.clone(),fields.clone()), (NonblockExpr,QuestionMark) => ExprKind::Fixme, #[priority(member)] (NonblockExpr(ref kind),Dot,PathGenericArgsWithColons(ref path)) => ExprKind::Member(Rc::new(kind.clone()),path.clone()), (NonblockExpr,Dot,LitInteger) => ExprKind::Fixme, (NonblockExpr(ref kind),LBracket,MaybeExpr(ref option),RBracket) => match option { &None => ExprKind::Index(Rc::new(kind.clone()),None), &Some(ref qindex) => ExprKind::Index(Rc::new(kind.clone()),Some(Rc::new(qindex.clone()))), }, (NonblockExpr(ref kind),LPar,MaybeExprs(ref arguments),RPar) => ExprKind::Call(Rc::new(kind.clone()),arguments.clone()), (LBracket,VecExpr,RBracket) => ExprKind::Fixme, (LPar,MaybeExprs(ref arguments),RPar) => ExprKind::Parentheses(arguments.clone()), (Continue) => ExprKind::Fixme, (Continue,Lifetime) => ExprKind::Fixme, (Return) => ExprKind::Return(None), (Return,Expr(ref expr)) => ExprKind::Return(Some(Rc::new(expr.clone()))), (Break) => ExprKind::Break(None), (Break,Lifetime(ref lifetime)) => ExprKind::Break(Some(lifetime.clone())), (Yield) => ExprKind::Fixme, (Yield,Expr) => ExprKind::Fixme, (NonblockExpr,LArrow,Expr) => ExprKind::Fixme, #[priority(qassignation)] (NonblockExpr(ref left),Equal,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(NonblockExpr,SHLEQ,Expr) => (), (NonblockExpr(ref left),LT,NoSpace,LT,Equal,Expr(ref right)) => ExprKind::Fixme, //(NonblockExpr,SHREQ,Expr) => (), (NonblockExpr(ref left),GT,NoSpace,GT,Equal,Expr(ref right)) => ExprKind::Fixme, (NonblockExpr(ref left),MinusEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),AndEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),OrEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),PlusEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),StarEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),SlashEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),CaretEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),PercentEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),OrOr,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),AndAnd,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),EqualEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),NE,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),LT,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),GT,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),LE,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),GE,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),Vertical,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),Caret,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),Ampersand,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(NonblockExpr,SHL,Expr) => (), (NonblockExpr(ref left),LT,NoSpace,LT,Expr(ref right)) => ExprKind::Fixme, //(NonblockExpr,SHR,Expr) => (), (NonblockExpr(ref left),GT,NoSpace,GT,Expr(ref right)) => ExprKind::Fixme, (NonblockExpr(ref left),Plus,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),Minus,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),Star,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),Slash,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),Percent,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (NonblockExpr(ref left),DotDot) => ExprKind::Range(Some(Rc::new(left.clone())),None), (NonblockExpr(ref left),DotDot,Expr(ref right)) => ExprKind::Range(Some(Rc::new(left.clone())),Some(Rc::new(right.clone()))), (DotDot,Expr(ref right)) => ExprKind::Range(None,Some(Rc::new(right.clone()))), (DotDot) => ExprKind::Range(None,None), (NonblockExpr,As,Ty) => ExprKind::Fixme, (NonblockExpr,Colon,Ty) => ExprKind::Fixme, (BOX,Expr) => ExprKind::Fixme, (ExprQualifiedPath) => ExprKind::Fixme, (NonblockPrefixExpr(ref expr)) => expr.clone(), } nonterminal Expr(ExprKind) { (Lit) => ExprKind::Single(Rc::new(state.values[0].clone())), (PathExpr) => ExprKind::Single(Rc::new(state.values[0].clone())), (LittleSelf) => ExprKind::Single(Rc::new(state.values[0].clone())), (MacroExpr) => ExprKind::Single(Rc::new(state.values[0].clone())), (PathExpr(ref path),LBrace,StructExprFields(ref fields),RBrace) => ExprKind::Struct(path.clone(),fields.clone()), (Expr,QuestionMark) => ExprKind::Fixme, #[priority(member)] (Expr(ref kind),Dot,PathGenericArgsWithColons(ref string)) => ExprKind::Member(Rc::new(kind.clone()),string.clone()), (Expr,Dot,LitInteger) => ExprKind::Fixme, (Expr(ref kind),LBracket,MaybeExpr(ref option),RBracket) => match option { &None => ExprKind::Index(Rc::new(kind.clone()),None), &Some(ref qindex) => ExprKind::Index(Rc::new(kind.clone()),Some(Rc::new(qindex.clone()))), }, (Expr(ref kind),LPar,MaybeExprs(ref arguments),RPar) => ExprKind::Call(Rc::new(kind.clone()),arguments.clone()), (LPar,MaybeExprs(ref arguments),RPar) => ExprKind::Parentheses(arguments.clone()), (LBracket,VecExpr,RBracket) => ExprKind::Fixme, (Continue) => ExprKind::Fixme, (Continue,Ident) => ExprKind::Fixme, (Return) => ExprKind::Return(None), (Return,Expr(ref expr)) => ExprKind::Return(Some(Rc::new(expr.clone()))), (Break) => ExprKind::Break(None), (Break,Ident(ref string)) => ExprKind::Break(Some(string.clone())), (Yield) => ExprKind::Fixme, (Yield,Expr) => ExprKind::Fixme, (Expr,LArrow,Expr) => ExprKind::Fixme, #[priority(qassignation)] (Expr(ref left),Equal,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(Expr,SHLEQ,Expr) => (), (Expr(ref left),LT,NoSpace,LT,Equal,Expr(ref right)) => ExprKind::Fixme, //(Expr,SHREQ,Expr) => (), (Expr(ref left),GT,NoSpace,GT,Equal,Expr(ref right)) => ExprKind::Fixme, (Expr(ref left),MinusEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),AndEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),OrEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),PlusEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),StarEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),SlashEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),CaretEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),PercentEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),OrOr,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),AndAnd,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),EqualEqual,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),NE,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),LT,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),GT,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),LE,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),GE,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Vertical,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Caret,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Ampersand,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(Expr,SHL,Expr) => (), (Expr(ref left),LT,NoSpace,LT,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(Expr,SHR,Expr) => (), (Expr(ref left),GT,NoSpace,GT,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Plus,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Minus,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Star,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Slash,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),Percent,Expr(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (Expr(ref left),DotDot) => ExprKind::Range(Some(Rc::new(left.clone())),None), (Expr(ref left),DotDot,Expr(ref right)) => ExprKind::Range(Some(Rc::new(left.clone())),Some(Rc::new(right.clone()))), (DotDot,Expr(ref right)) => ExprKind::Range(None,Some(Rc::new(right.clone()))), (DotDot) => ExprKind::Range(None,None), (Expr,As,Ty) => ExprKind::Fixme, (Expr,Colon,Ty) => ExprKind::Fixme, (BOX,Expr) => ExprKind::Fixme, (ExprQualifiedPath) => ExprKind::Fixme, (BlockExpr(ref block)) => ExprKind::Single(block.clone()), (Block) => ExprKind::Single(Rc::new(state.values[0].clone())), (NonblockPrefixExpr(ref expr)) => expr.clone(), } nonterminal ExprNostruct(ExprKind) { (Lit) => ExprKind::Single(Rc::new(state.values[0].clone())), (PathExpr) => ExprKind::Single(Rc::new(state.values[0].clone())), (LittleSelf) => ExprKind::Single(Rc::new(state.values[0].clone())), (MacroExpr) => ExprKind::Single(Rc::new(state.values[0].clone())), (ExprNostruct,QuestionMark) => ExprKind::Fixme, #[priority(member)] (ExprNostruct(ref kind),Dot,PathGenericArgsWithColons(ref path)) => ExprKind::Member(Rc::new(kind.clone()),path.clone()), (ExprNostruct,Dot,LitInteger) => ExprKind::Fixme, (ExprNostruct(ref kind),LBracket,MaybeExpr(ref option),RBracket) => match option { &None => ExprKind::Index(Rc::new(kind.clone()),None), &Some(ref qindex) => ExprKind::Index(Rc::new(kind.clone()),Some(Rc::new(qindex.clone()))), }, (ExprNostruct(ref kind),LPar,MaybeExprs(ref arguments),RPar) => ExprKind::Call(Rc::new(kind.clone()),arguments.clone()), (LBracket,VecExpr,RBracket) => ExprKind::Fixme, (LPar,MaybeExprs(ref arguments),RPar) => ExprKind::Parentheses(arguments.clone()), (Continue) => ExprKind::Fixme, (Continue,Ident) => ExprKind::Fixme, (Return) => ExprKind::Return(None), (Return,Expr(ref expr)) => ExprKind::Return(Some(Rc::new(expr.clone()))), (Break) => ExprKind::Break(None), (Break,Ident(ref string)) => ExprKind::Break(Some(string.clone())), (Yield) => ExprKind::Fixme, (Yield,Expr) => ExprKind::Fixme, (ExprNostruct(ref left),LArrow,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), #[priority(qassignation)] (ExprNostruct(ref left),Equal,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(ExprNostruct(ref left),SHLEQ,ExprNostruct(ref right)) => (), (ExprNostruct(ref left),LT,NoSpace,LT,Equal,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())),//FIXME //(ExprNostruct(ref left),SHREQ,ExprNostruct) => (), (ExprNostruct(ref left),GT,NoSpace,GT,Equal,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())),//FIXME (ExprNostruct(ref left),MinusEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),AndEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),OrEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),PlusEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),StarEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),SlashEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),CaretEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),PercentEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),OrOr,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),AndAnd,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),EqualEqual,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),NE,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),LT,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),GT,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),LE,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),GE,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Vertical,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Caret,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Ampersand,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(ExprNostruct,SHL,ExprNostruct) => (), (ExprNostruct(ref left),LT,NoSpace,LT,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), //(ExprNostruct,SHR,ExprNostruct) => (), (ExprNostruct(ref left),GT,NoSpace,GT,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Plus,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Minus,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Star,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Slash,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),Percent,ExprNostruct(ref right)) => ExprKind::Infix(Rc::new(left.clone()),Rc::new(state.values[1].clone()),Rc::new(right.clone())), (ExprNostruct(ref left),DotDot) => ExprKind::Range(Some(Rc::new(left.clone())),None), (ExprNostruct(ref left),DotDot,ExprNostruct(ref right)) => ExprKind::Range(Some(Rc::new(left.clone())),Some(Rc::new(right.clone()))), (DotDot,ExprNostruct(ref right)) => ExprKind::Range(None,Some(Rc::new(right.clone()))), (DotDot) => ExprKind::Range(None,None), (ExprNostruct,As,Ty) => ExprKind::Fixme, (ExprNostruct,Colon,Ty) => ExprKind::Fixme, (BOX,ExprNostruct) => ExprKind::Fixme, (ExprQualifiedPath) => ExprKind::Fixme, (BlockExpr) => ExprKind::Fixme, (Block) => ExprKind::Fixme, (NonblockPrefixExprNostruct(ref expr)) => expr.clone(), } nonterminal NonblockPrefixExprNostruct(ExprKind) { (Minus,ExprNostruct(ref expr)) => ExprKind::Prefix(Rc::new(state.values[0].clone()),Rc::new(expr.clone())), (Bang,ExprNostruct(ref expr)) => ExprKind::Prefix(Rc::new(state.values[0].clone()),Rc::new(expr.clone())), (Star,ExprNostruct(ref expr)) => ExprKind::Prefix(Rc::new(state.values[0].clone()),Rc::new(expr.clone())), (Ampersand,MaybeMut(ismut),ExprNostruct(ref expr)) => if ismut {ExprKind::RefMut(Rc::new(expr.clone()))} else {ExprKind::Ref(Rc::new(expr.clone()))}, (AndAnd,MaybeMut,ExprNostruct) => ExprKind::Fixme, (LambdaExprNostruct(ref expr)) => expr.clone(), (Move,LambdaExprNostruct(ref expr)) => expr.clone(),//FIXME } nonterminal NonblockPrefixExpr(ExprKind) { (Minus,Expr(ref expr)) => ExprKind::Prefix(Rc::new(state.values[0].clone()),Rc::new(expr.clone())), (Bang,Expr(ref expr)) => ExprKind::Prefix(Rc::new(state.values[0].clone()),Rc::new(expr.clone())), (Star,Expr(ref expr)) => ExprKind::Prefix(Rc::new(state.values[0].clone()),Rc::new(expr.clone())), (Ampersand,MaybeMut(ismut),Expr(ref expr)) => if ismut {ExprKind::RefMut(Rc::new(expr.clone()))} else {ExprKind::Ref(Rc::new(expr.clone()))}, (AndAnd,MaybeMut,Expr(ref expr)) => ExprKind::Fixme, (LambdaExpr(ref expr)) => expr.clone(), (Move,LambdaExpr(ref expr)) => expr.clone(),//FIXME } nonterminal ExprQualifiedPath { (LT,TySum,MaybeAsTraitRef,GT,ModSep,Ident,MaybeQPathParams) => (), //(SHL,TySum,MaybeAsTraitRef,GT,ModSep,Ident,MaybeAsTraitRef,GT,ModSep,Ident) => (), //(SHL,TySum,MaybeAsTraitRef,GT,ModSep,Ident,GenericArgs,MaybeAsTraitRef,GT,ModSep,Ident) => (), //(SHL,TySum,MaybeAsTraitRef,GT,ModSep,Ident,MaybeAsTraitRef,GT,ModSep,Ident,GenericArgs) => (), //(SHL,TySum,MaybeAsTraitRef,GT,ModSep,Ident,GenericArgs,MaybeAsTraitRef,GT,ModSep,Ident,GenericArgs) => (), } nonterminal MaybeQPathParams { (ModSep,GenericArgs) => (), () => (), } nonterminal MaybeAsTraitRef { (As,TraitRef) => (), () => (), } nonterminal LambdaExpr(ExprKind) { (OrOr,RetTy(ref ot),Expr(ref expr)) => ExprKind::Lambda(vec![],ot.clone(),Rc::new(expr.clone())), (Vertical,Vertical,RetTy(ref ot),Expr(ref expr)) => ExprKind::Lambda(vec![],ot.clone(),Rc::new(expr.clone())), (Vertical,InferrableParams(ref params),Vertical,RetTy(ref ot),Expr(ref expr)) => ExprKind::Lambda(params.clone(),ot.clone(),Rc::new(expr.clone())), (Vertical,InferrableParams(ref params),OrOr,LambdaExprNoFirstBar(ref expr)) => ExprKind::Lambda(params.clone(),None,Rc::new(expr.clone())), } nonterminal LambdaExprNoFirstBar(ExprKind) { (Vertical,RetTy(ref ot),Expr(ref expr)) => ExprKind::Lambda(vec![],ot.clone(),Rc::new(expr.clone())), (InferrableParams(ref params),Vertical,RetTy(ref ot),Expr(ref expr)) => ExprKind::Lambda(params.clone(),ot.clone(),Rc::new(expr.clone())), (InferrableParams(ref params),OrOr,LambdaExprNoFirstBar(ref expr)) => ExprKind::Lambda(params.clone(),None,Rc::new(expr.clone())), } nonterminal LambdaExprNostruct(ExprKind) { (OrOr,ExprNostruct(ref expr)) => ExprKind::Lambda(vec![],None,Rc::new(expr.clone())), (Vertical,Vertical,RetTy(ref ot),ExprNostruct(ref expr)) => ExprKind::Lambda(vec![],ot.clone(),Rc::new(expr.clone())), (Vertical,InferrableParams(ref params),Vertical,ExprNostruct(ref expr)) => ExprKind::Lambda(params.clone(),None,Rc::new(expr.clone())), //XXX No RetTy? (Vertical,InferrableParams(ref params),OrOr,LambdaExprNostructNoFirstBar(ref expr)) => ExprKind::Lambda(params.clone(),None,Rc::new(expr.clone())), } nonterminal LambdaExprNostructNoFirstBar(ExprKind) { (Vertical,RetTy(ref ot),ExprNostruct(ref expr)) => ExprKind::Lambda(vec![],ot.clone(),Rc::new(expr.clone())), (InferrableParams(ref params),Vertical,RetTy(ref ot),ExprNostruct(ref expr)) => ExprKind::Lambda(params.clone(),ot.clone(),Rc::new(expr.clone())), (InferrableParams(ref params),OrOr,LambdaExprNostructNoFirstBar(ref expr)) => ExprKind::Lambda(params.clone(),None,Rc::new(expr.clone())), } nonterminal VecExpr { (MaybeExprs) => (), (Exprs,Semicolon,Expr) => (), } nonterminal StructExprFields(Vec<(String,Option)>) { (FieldInits(ref list)) => list.clone(), (FieldInits(ref list),Comma) => list.clone(), (MaybeFieldInits(ref list),DefaultFieldInit) => list.clone(),//FIXME () => vec![], } nonterminal MaybeFieldInits(Vec<(String,Option)>) { (FieldInits(ref list)) => list.clone(), (FieldInits(ref list),Comma) => list.clone(), () => vec![], } nonterminal FieldInits(Vec<(String,Option)>) { (FieldInit(ref id, ref oe)) => vec![(id.clone(),oe.clone())], (FieldInits(ref list),Comma,FieldInit(ref id,ref oe)) => { let mut new=(list.clone()); new.push((id.clone(),oe.clone())); new }, } nonterminal FieldInit(String,Option) { (Ident(ref id)) => (id.clone(),None), (Ident(ref id),Colon,Expr(ref expr)) => (id.clone(),Some(expr.clone())), (LitInteger(ref number),Colon,Expr(ref expr)) => (number.to_string(),Some(expr.clone())), } nonterminal DefaultFieldInit { (DotDot,Expr) => (), } nonterminal BlockExpr(Rc) { (ExprMatch) => Rc::new(state.values[0].clone()), (ExprIf) => Rc::new(state.values[0].clone()), (ExprIfLet) => Rc::new(state.values[0].clone()), (ExprWhile) => Rc::new(state.values[0].clone()), (ExprWhileLet) => Rc::new(state.values[0].clone()), (ExprLoop) => Rc::new(state.values[0].clone()), (ExprFor) => Rc::new(state.values[0].clone()), (Unsafe,Block) => Rc::new(state.values[1].clone()),//FIXME (PathExpr,Bang,MaybeIdent,BracesDelimitedTokenTrees) => Rc::new(state.values[1].clone()),//FIXME } nonterminal FullBlockExpr(Rc) { (BlockExpr(ref block)) => block.clone(), (BlockExprDot) => Rc::new(state.values[0].clone()),//FIXME } nonterminal BlockExprDot { (BlockExpr,Dot,PathGenericArgsWithColons) => (), (BlockExprDot,Dot,PathGenericArgsWithColons) => (), (BlockExpr,Dot,PathGenericArgsWithColons,LBracket,MaybeExpr,RBracket) => (), (BlockExprDot,Dot,PathGenericArgsWithColons,LBracket,MaybeExpr,RBracket) => (), (BlockExpr,Dot,PathGenericArgsWithColons,LPar,MaybeExprs,RPar) => (), (BlockExprDot,Dot,PathGenericArgsWithColons,LPar,MaybeExprs,RPar) => (), (BlockExpr,Dot,LitInteger) => (), (BlockExprDot,Dot,LitInteger) => (), } nonterminal ExprMatch(ExprKind,Vec>) { (Match,ExprNostruct(ref expr),LBrace,RBrace) => (expr.clone(),vec![]), (Match,ExprNostruct(ref expr),LBrace,MatchClauses(ref list),RBrace) => (expr.clone(),list.clone()), (Match,ExprNostruct(ref expr),LBrace,MatchClauses(ref list),NonblockMatchClause(_,_,_),RBrace) => { let mut new=(list.clone()); new.push(Rc::new(state.values[4].clone())); (expr.clone(),new) }, (Match,ExprNostruct(ref expr),LBrace,NonblockMatchClause(_,_,_),RBrace) => (expr.clone(),vec![Rc::new(state.values[3].clone())]), } nonterminal MatchClauses(Vec>) { (MatchClause) => vec![Rc::new(state.values[0].clone())], (MatchClauses(ref clauses),MatchClause) => { let mut new=(clauses.clone()); new.push(Rc::new(state.values[1].clone())); new }, } nonterminal MatchClause(Vec,PatKind,Rc) { (NonblockMatchClause(ref attributes, ref pattern, ref expression),Comma) => (attributes.clone(),pattern.clone(),expression.clone()), (BlockMatchClause(ref attributes, ref pattern, ref expression)) => (attributes.clone(),pattern.clone(),expression.clone()), (BlockMatchClause(ref attributes, ref pattern, ref expression),Comma) => (attributes.clone(),pattern.clone(),expression.clone()), } nonterminal NonblockMatchClause(Vec,PatKind,Rc) { (MaybeOuterAttrs(ref attributes),PatsOr(ref pattern),MaybeGuard,FatArrow,NonblockExpr) => (attributes.clone(),pattern.clone(),Rc::new(state.values[4].clone())), (MaybeOuterAttrs(ref attributes),PatsOr(ref pattern),MaybeGuard,FatArrow,BlockExprDot) => (attributes.clone(),pattern.clone(),Rc::new(state.values[4].clone())), } nonterminal BlockMatchClause(Vec,PatKind,Rc) { (MaybeOuterAttrs(ref attributes),PatsOr(ref pattern),MaybeGuard,FatArrow,Block) => (attributes.clone(),pattern.clone(),Rc::new(state.values[4].clone())), (MaybeOuterAttrs(ref attributes),PatsOr(ref pattern),MaybeGuard,FatArrow,BlockExpr) => (attributes.clone(),pattern.clone(),Rc::new(state.values[4].clone())), } nonterminal MaybeGuard { (If,ExprNostruct) => (), () => (), } nonterminal ExprIf(ExprKind,Rc,Option>) { (If,ExprNostruct(ref expr),Block) => (expr.clone(),Rc::new(state.values[2].clone()),None), (If,ExprNostruct(ref expr),Block,Else,BlockOrIf(ref token)) => (expr.clone(),Rc::new(state.values[2].clone()),Some(token.clone())), } nonterminal ExprIfLet(PatKind,ExprKind,Rc,Option>) { (If,LiteralLet,Pat(ref pattern),Equal,ExprNostruct(ref expr),Block) => (pattern.clone(),expr.clone(),Rc::new(state.values[5].clone()),None), (If,LiteralLet,Pat(ref pattern),Equal,ExprNostruct(ref expr),Block,Else,BlockOrIf(ref token)) => (pattern.clone(),expr.clone(),Rc::new(state.values[5].clone()),Some(token.clone())), } nonterminal BlockOrIf(Rc) { (Block) => Rc::new(state.values[0].clone()), (ExprIf) => Rc::new(state.values[0].clone()), (ExprIfLet) => Rc::new(state.values[0].clone()), } nonterminal ExprWhile(ExprKind,Rc) { (MaybeLabel,While,ExprNostruct(ref expr),Block) => (expr.clone(),Rc::new(state.values[3].clone())), } nonterminal ExprWhileLet { (MaybeLabel,While,LiteralLet,Pat,Equal,ExprNostruct,Block) => (), } nonterminal ExprLoop { (MaybeLabel,Loop,Block) => (), } nonterminal ExprFor(PatKind,ExprKind,Rc) { (MaybeLabel,For,Pat(ref pattern),In,ExprNostruct(ref expr),Block) => (pattern.clone(),expr.clone(),Rc::new(state.values[5].clone())), } nonterminal MaybeLabel { (Lifetime,Colon) => (), () => (), } nonterminal Let(StmtKind) { (LiteralLet,Pat(ref pattern),MaybeTyAscription(ref option_type),MaybeInitExpr(ref option_expr),Semicolon) => StmtKind::Let(pattern.clone(),option_type.clone(),option_expr.clone()), } //////////////////////////////////////////////////////////////////////// // Part 5: Macros and misc. rules //////////////////////////////////////////////////////////////////////// nonterminal Lit(Rc) { (LitByte) => Rc::new(state.values[0].clone()), (LitChar) => Rc::new(state.values[0].clone()), (LitInteger) => Rc::new(state.values[0].clone()), (LitFloat) => Rc::new(state.values[0].clone()), (True) => Rc::new(state.values[0].clone()), (False) => Rc::new(state.values[0].clone()), (Str) => Rc::new(state.values[0].clone()), } nonterminal Str(String) { (LitStr(ref string)) => string.clone(), (LitStrRaw) => String::from("FIXME RAW"), (LitByteStr) => String::from("FIXME BSTR"), (LitByteStrRaw) => String::from("FIXME BRAW"), } nonterminal MaybeIdent { () => (), (Ident) => (), } nonterminal Ident(String) { (LiteralIdent(ref s)) => s.clone(), // Weak keywords that can be used as identifiers (Catch) => String::from("catch"), (DEFAULT) => String::from("default"), (Union) => String::from("union"), } nonterminal UnpairedToken(Rc) { //(SHL) => (), //(SHR) => (), (LE) => Rc::new(state.values[0].clone()), (EqualEqual) => Rc::new(state.values[0].clone()), (NE) => Rc::new(state.values[0].clone()), (GE) => Rc::new(state.values[0].clone()), (AndAnd) => Rc::new(state.values[0].clone()), (OrOr) => Rc::new(state.values[0].clone()), (LArrow) => Rc::new(state.values[0].clone()), //(SHLEQ) => (), //(SHREQ) => (), (MinusEqual) => Rc::new(state.values[0].clone()), (AndEqual) => Rc::new(state.values[0].clone()), (OrEqual) => Rc::new(state.values[0].clone()), (PlusEqual) => Rc::new(state.values[0].clone()), (StarEqual) => Rc::new(state.values[0].clone()), (SlashEqual) => Rc::new(state.values[0].clone()), (CaretEqual) => Rc::new(state.values[0].clone()), (PercentEqual) => Rc::new(state.values[0].clone()), (DotDot) => Rc::new(state.values[0].clone()), (DotDotDot) => Rc::new(state.values[0].clone()), (ModSep) => Rc::new(state.values[0].clone()), (RArrow) => Rc::new(state.values[0].clone()), (FatArrow) => Rc::new(state.values[0].clone()), (LitByte) => Rc::new(state.values[0].clone()), (LitChar) => Rc::new(state.values[0].clone()), (LitInteger) => Rc::new(state.values[0].clone()), (LitFloat) => Rc::new(state.values[0].clone()), (LitStr) => Rc::new(state.values[0].clone()), (LitStrRaw) => Rc::new(state.values[0].clone()), (LitByteStr) => Rc::new(state.values[0].clone()), (LitByteStrRaw) => Rc::new(state.values[0].clone()), (LiteralIdent) => Rc::new(state.values[0].clone()), (Underscore) => Rc::new(state.values[0].clone()), (LiteralLifetime) => Rc::new(state.values[0].clone()), (LittleSelf) => Rc::new(state.values[0].clone()), (Static) => Rc::new(state.values[0].clone()), //(Abstract) => (), //(AlignOf) => (), (As) => Rc::new(state.values[0].clone()), //(Become) => (), (Break) => Rc::new(state.values[0].clone()), (Catch) => Rc::new(state.values[0].clone()), (Crate) => Rc::new(state.values[0].clone()), (DEFAULT) => Rc::new(state.values[0].clone()), //(Do) => (), (Else) => Rc::new(state.values[0].clone()), (Enum) => Rc::new(state.values[0].clone()), (Extern) => Rc::new(state.values[0].clone()), (False) => Rc::new(state.values[0].clone()), //(Final) => (), (FN) => Rc::new(state.values[0].clone()), (For) => Rc::new(state.values[0].clone()), (If) => Rc::new(state.values[0].clone()), (Impl) => Rc::new(state.values[0].clone()), (In) => Rc::new(state.values[0].clone()), (LiteralLet) => Rc::new(state.values[0].clone()), (Loop) => Rc::new(state.values[0].clone()), //(Macro) => (), (Match) => Rc::new(state.values[0].clone()), (Mod) => Rc::new(state.values[0].clone()), (Move) => Rc::new(state.values[0].clone()), (Mut) => Rc::new(state.values[0].clone()), //(OffsetOf) => (), //(Override) => (), //(Priv) => (), (Pub) => Rc::new(state.values[0].clone()), //(Pure) => (), (Ref) => Rc::new(state.values[0].clone()), (Return) => Rc::new(state.values[0].clone()), (Struct) => Rc::new(state.values[0].clone()), //(Sizeof) => (), (Super) => Rc::new(state.values[0].clone()), (True) => Rc::new(state.values[0].clone()), (Trait) => Rc::new(state.values[0].clone()), (Type) => Rc::new(state.values[0].clone()), (Union) => Rc::new(state.values[0].clone()), (Unsafe) => Rc::new(state.values[0].clone()), //(Unsized) => (), (Use) => Rc::new(state.values[0].clone()), //(Virtual) => (), (While) => Rc::new(state.values[0].clone()), (Yield) => Rc::new(state.values[0].clone()), (Continue) => Rc::new(state.values[0].clone()), //(Proc) => (), (BOX) => Rc::new(state.values[0].clone()), (Const) => Rc::new(state.values[0].clone()), (Where) => Rc::new(state.values[0].clone()), (Typeof) => Rc::new(state.values[0].clone()), (InnerDocComment) => Rc::new(state.values[0].clone()), (OuterDocComment) => Rc::new(state.values[0].clone()), (Shebang) => Rc::new(state.values[0].clone()), (StaticLifetime) => Rc::new(state.values[0].clone()), (Semicolon) => Rc::new(state.values[0].clone()), (Comma) => Rc::new(state.values[0].clone()), (Dot) => Rc::new(state.values[0].clone()), (At) => Rc::new(state.values[0].clone()), (NumberSign) => Rc::new(state.values[0].clone()), //(Tilde) => (), (Colon) => Rc::new(state.values[0].clone()), //(Dolar) => (), (Equal) => Rc::new(state.values[0].clone()), (QuestionMark) => Rc::new(state.values[0].clone()), (Bang) => Rc::new(state.values[0].clone()), (LT) => Rc::new(state.values[0].clone()), (GT) => Rc::new(state.values[0].clone()), (Minus) => Rc::new(state.values[0].clone()), (Ampersand) => Rc::new(state.values[0].clone()), (Vertical) => Rc::new(state.values[0].clone()), (Plus) => Rc::new(state.values[0].clone()), (Star) => Rc::new(state.values[0].clone()), (Slash) => Rc::new(state.values[0].clone()), (Caret) => Rc::new(state.values[0].clone()), (Percent) => Rc::new(state.values[0].clone()), } nonterminal TokenTrees(Vec>) { () => vec![], (TokenTrees(ref trees),TokenTree(ref token)) => { let mut new=(trees.clone()); new.push(token.clone()); new }, } nonterminal TokenTree(Rc) { //(DelimitedTokenTrees(ref trees)) => Rc::new(Token_DelimitedTokenTrees(trees.clone())), (DelimitedTokenTrees(ref trees)) => trees.clone(), (UnpairedToken(ref token)) => token.clone(), } nonterminal DelimitedTokenTrees(Rc) { (ParensDelimitedTokenTrees(ref trees)) => Rc::new(Token::ParensDelimitedTokenTrees(trees.clone())), (BracesDelimitedTokenTrees(ref trees)) => Rc::new(Token::BracesDelimitedTokenTrees(trees.clone())), (BracketsDelimitedTokenTrees(ref trees)) => Rc::new(Token::BracketsDelimitedTokenTrees(trees.clone())), } nonterminal ParensDelimitedTokenTrees(Vec>) { (LPar,TokenTrees(ref trees),RPar) => trees.clone(), } nonterminal BracesDelimitedTokenTrees(Vec>) { (LBrace,TokenTrees(ref trees),RBrace) => trees.clone(), } nonterminal BracketsDelimitedTokenTrees(Vec>) { (LBracket,TokenTrees(ref trees),RBracket) => trees.clone(), } nonterminal MaybeSpace { (NoSpace) => (), () => (), } //New nonterminal ItemTerminal(ItemKind) { //(Struct,Ident,GenericParams,MaybeWhereClause,StructDeclArgs) => (), //(Struct,Ident,GenericParams,StructTupleArgs,MaybeWhereClause,Semicolon) => (), //(MaybeDefaultMaybeUnsafe,Impl,GenericParams,TyPrimSum,MaybeWhereClause,LBrace,MaybeInnerAttrs,MaybeImplItems,RBrace) => (), (Terminal,Ident(ref id),LBrace,MaybeTerminalItems(ref items),RBrace) => ItemKind::Terminal(id.clone(),None,items.clone()), (Terminal,Ident(ref id),LPar,MaybeTySums,RPar,LBrace,MaybeTerminalItems(ref items),RBrace) => ItemKind::Terminal(id.clone(),Some(Rc::new(state.values[3].clone())),items.clone()), } //New nonterminal MaybeTerminalItems(Vec) { (TerminalItems(ref items)) => items.clone(), () => vec![], } //New nonterminal TerminalItems(Vec) { (TerminalItem(ref item)) => vec![item.clone()], (TerminalItem(ref item),TerminalItems(ref items)) => { let mut new=(vec![item.clone()]); //new.extend(items.iter().map(|x|x.clone())); new.extend(items.iter().map( |x|(x.clone()) )); new }, } //New nonterminal TerminalItem(ItemKind) { (ItemFn(ref item)) => item.clone(), //(AttrsAndVis,ItemMacro) => (), //(ImplConst) => (), //(ImplType) => (), } //New nonterminal ItemNonterminal(ItemKind) { (Nonterminal,Ident(ref id),LBrace,MatchClauses(ref clauses),RBrace) => ItemKind::Nonterminal(id.clone(),None,clauses.clone()), (Nonterminal,Ident(ref id),LPar,MaybeTySums,RPar,LBrace,MatchClauses(ref clauses),RBrace) => ItemKind::Nonterminal(id.clone(),Some(Rc::new(state.values[3].clone())),clauses.clone()), } ordering!(member,qassignation); #[derive(Debug)] struct Rule { //left //right: Vec, patterns: Vec,//[Pat(Path(LitOrPath("NoSpace")))] , Pat(Enum(PathExpr("MaybeModItems"), PatTup([Pat(Path(LitOrPath("items")))]))) expression: Rc,//NonblockExpr priority: Option } #[derive(Debug)] struct TokenInfo { id: String, //type_arguments: Vec>, type_arguments: Vec, is_terminal: bool, re: Option, fn_match: Option, rules: Vec } struct Compiler<'a> { source: &'a Token, token_info: Vec, first_nonterminal: Option, token_name_to_index: HashMap,//already with the +1 ordering: HashMap<(String,String),Ordering>, ignore_res: Vec<(usize,String)> } impl<'a> Compiler<'a> { fn process_token(&mut self,token:&Token) { //println!(">>process_token {:?}",token); match token { &Token::WholeCrate(ref items) => { for item in items { self.process_token(item); } }, &Token::ModItem(ref attributes,ref item) => { //self.process_token(item); match item { &ItemKind::Fixme => println!("fixme item={:?}",item), &ItemKind::Macro(ref path, ref id, ref tree) => { match (path.as_ref(),tree.as_ref()) { (&Token::PathExpr(PathKind::Ident(ref s)),&Token::ParensDelimitedTokenTrees(ref data)) => { if s=="re_terminal" { //println!("re_terminal macro = {:?}",item); let mut comma_index=0; while (comma_index<(data.len())) && ((*data[comma_index])!=Token::Comma) { comma_index+=1; } if comma_index<(data.len()) { match (data[0].as_ref(),data[comma_index+1].as_ref()) { (&Token::LiteralIdent(ref id),&Token::LitStr(ref re)) => { let type_arguments=if let &Token::ParensDelimitedTokenTrees(ref data_types)=data[1].as_ref() { let mut new=vec![]; for dt in data_types { if let &Token::LiteralIdent(ref s)=dt.as_ref() { //println!("Got type {}",s); new.push(TyLf::Type(TyKind::Path(PathWKind::Ident(s.clone())))); } else { panic!("problem parsing types in macro {:?}",item); } } new } else { vec![] }; if id=="_" { self.ignore_res.push((self.token_info.len(),re[1..(re.len()-1)].to_string())); } else { self.token_info.push(TokenInfo{ id:id.clone(), //type_string:String::from("()"), type_arguments, is_terminal: true, re:Some(re[1..(re.len()-1)].to_string()), fn_match: None, rules: vec![], }); } }, _ => println!("incorrect data in re_terminal"), } } else { println!("incorrect data in re_terminal"); } } else if s=="ordering" { let mut order=vec![]; for elem in data { match elem.as_ref() { &Token::LiteralIdent(ref id) => order.push(id.clone()), &Token::Comma => (), _ => panic!("incorrect token in ordering! {:?}",elem), }; } for i in 0..(order.len()) { for j in 0..(order.len()) { self.ordering.insert((order[i].clone(),order[j].clone()),i.cmp(&j)); } } } }, _ => println!("ignoring macro {:?}",token), }; } //&ItemKind::FN(ref ) => (), &ItemKind::Terminal(ref id, ref ty, ref items) => { let type_arguments= match ty { &None => vec![], &Some(ref mts) => match mts.as_ref() { &Token::MaybeTySums(ref types) => types.clone(), _ => panic!(""), } }; let mut fn_match=None; for item in items { match item { &ItemKind::FN(ref name, ref lifetimes,ref _gp,ref _params,ref _oret,ref _bs,ref _be) => { if name=="_match" { fn_match=(Some(item.clone())); } else { panic!("received fn {} is terminal {}",name,id); } }, _ => panic!("We do not know what to do with item {:?} in terminal {}",item,id), }; } self.token_info.push(TokenInfo{ id:id.clone(), //type_string:String::from("()"), type_arguments, is_terminal: true, re: None, fn_match, rules: vec![], }); }, &ItemKind::Nonterminal(ref id, ref ty, ref clauses) => { if let None=self.first_nonterminal { self.first_nonterminal=(Some(self.token_info.len())); } let mut rules=vec![]; for clause in clauses { //println!("Found clause {:?}",clause); if let &Token::MatchClause(ref attributes,ref patterns,ref expression)=clause.as_ref() { let mut rule_patterns =vec![]; if let &PatKind::Tuple(ref patterns)=patterns { //rule_patterns.push(pat.clone()); rule_patterns=(patterns.clone()); } let mut priority=None; for attr in attributes { if let &AttrKind::Sequence(ref attr_name, ref seq)=attr { if attr_name=="priority" { if seq.len()!=1 { panic!("there must be exactly one priority flag ({:?})",attr); } if let AttrKind::Flag(ref p_flag)=seq[0] { priority=(Some(p_flag.clone())); } else { panic!("I do not understand this priority {:?}",attr); } } } } rules.push(Rule{ //right: vec![], patterns: rule_patterns, expression: expression.clone(), priority, }); } } let type_arguments= match ty { &None => vec![], &Some(ref mts) => match mts.as_ref() { &Token::MaybeTySums(ref types) => types.clone(), _ => panic!(""), } }; self.token_info.push(TokenInfo{ id:id.clone(), //type_string:String::from("()"), type_arguments, is_terminal: false, re: None, fn_match: None, rules, }); }, _ => { for attr in attributes { println!("{}",attr); } println!("{}",item); }, //&ItemKind::View(ref view) => println!("{}",view), //&ItemKind::Enum(ref id, ref params, ref defs) => //{ // print!("enum {}",id); // if params.len()>0 // { // print!("({})",params.join(",")); // } // println!("{{"); // for &(ref name,ref tys) in defs // { // print!("{}",name); // if tys.len()>0 // { // print!("({})",tys.iter().map(|t|t.to_string()).collect::>().join(",")) // } // println!(","); // } // println!("}}"); //}, } }, //&Token::ItemMacro(ref path, ref id, ref tree) => //{ // //println!("Got macro {:?} with data {:?}",path,tree); // match (path.as_ref(),tree.as_ref()) // { // (&Token::PathExpr(PathKind::Ident(ref s)),&Token::ParensDelimitedTokenTrees(ref data)) => // { // if s=="re_terminal" // { // let mut comma_index=0; // while comma_index // { // if id!="_" // { // self.token_info.push(TokenInfo{ // id:id.clone(), // //type_string:String::from("()"), // type_arguments: vec![], // is_terminal: true, // re:Some(re[1..re.len()-1].to_string()), // fn_match: None, // rules: vec![], // }); // } // }, // _ => println!("incorrect data in re_terminal"), // } // } // else // { // println!("incorrect data in re_terminal"); // } // } // else if s=="ordering" // { // let mut order=vec![]; // for elem in data // { // match elem.as_ref() // { // &Token::LiteralIdent(ref id) => order.push(id.clone()), // &Token::Comma => (), // _ => panic!("incorrect token in ordering! {:?}",elem), // }; // } // for i in 0..order.len() // { // for j in 0..order.len() // { // self.ordering.insert((order[i].clone(),order[j].clone()),i.cmp(&j)); // } // } // } // }, // _ => println!("ignoring macro {:?}",token), // }; //}, //&Token::ItemTerminal(ref id, ref ty, ref items) => //{ // let type_arguments= match ty // { // &None => vec![], // &Some(ref mts) => match mts.as_ref() // { // &Token::MaybeTySums(ref types) => types.clone(), // _ => panic!(""), // } // }; // self.token_info.push(TokenInfo{ // id:id.clone(), // //type_string:String::from("()"), // type_arguments, // is_terminal: true, // re: None, // fn_match: None,//FIXME // rules: vec![], // }); //}, //&Token::ItemNonterminal(ref id, ref ty, ref clauses) => //{ // if let None=self.first_nonterminal // { // self.first_nonterminal=Some(self.token_info.len()); // } // let mut rules=vec![]; // for clause in clauses // { // //println!("Found clause {:?}",clause); // if let &Token::MatchClause(ref attributes,ref patterns,ref expression)=clause.as_ref() // { // let mut rule_patterns : Vec>=vec![]; // if let &PatKind::Tuple(ref tuple)=patterns // { // if let &Token::PatTup(ref pats)=tuple.as_ref() // { // for pat in pats // { // rule_patterns.push(pat.clone()); // } // } // } // let mut priority=None; // for attr in attributes // { // if let &AttrKind::Sequence(ref attr_name, ref seq)=attr // { // if attr_name=="priority" // { // if seq.len()!=1 // { // panic!("there must be exactly one priority flag ({:?})",attr); // } // if let AttrKind::Flag(ref p_flag)=seq[0] // { // priority=Some(p_flag.clone()); // } // else // { // panic!("I do not understand this priority {:?}",attr); // } // } // } // } // rules.push(Rule{ // //right: vec![], // patterns: rule_patterns, // expression: expression.clone(), // priority, // }); // } // } // let type_arguments= match ty // { // &None => vec![], // &Some(ref mts) => match mts.as_ref() // { // &Token::MaybeTySums(ref types) => types.clone(), // _ => panic!(""), // } // }; // self.token_info.push(TokenInfo{ // id:id.clone(), // //type_string:String::from("()"), // type_arguments, // is_terminal: false, // re: None, // fn_match: None, // rules, // }); //}, //&Token::ViewItem(ref view) => println!("{}",view), //&Token::ItemEnum(ref id, ref params, ref defs) => //{ // print!("enum {}",id); // if params.len()>0 // { // print!("({})",params.join(",")); // } // println!("{{"); // for &(ref name,ref tys) in defs // { // print!("{}",name); // if tys.len()>0 // { // print!("({})",tys.iter().map(|t|t.to_string()).collect::>().join(",")) // } // println!(","); // } // println!("}}"); //}, _ => (), }; } fn compile(&mut self) { self.process_token(self.source); for (i,token) in self.token_info.iter().enumerate() { //println!("token {}={:?}",i+1,token); self.token_name_to_index.insert(token.id.clone(),i+1); } //println!("first non-terminal={:?}",self.first_nonterminal); //println!("--------------------------------------"); println!("#[derive(Clone,Debug,PartialEq)]"); println!("enum Token{{DummyStart,"); for token in self.token_info.iter() { if token.type_arguments.len()>0 { print!("{}({}),",token.id,token.type_arguments.iter().map(|t|format!("{}",t)).collect::>().join(",")); } else { print!("{},",token.id); } } println!("}}\nimpl Default for Token {{ fn default()->Self{{Token::DummyStart}} }}"); println!("struct ParsingTables {{ }}"); println!("impl ParsingTablesTrait for ParsingTables {{"); println!("fn initial()->usize {{ {} }}",self.first_nonterminal.unwrap()+1); println!("fn match_some(parser: &mut Parser) -> Option<(usize,Token)> {{ let source=&parser.source[parser.source_index..];"); let mut ignore_it=self.ignore_res.iter(); let (mut ignore_pos,mut ignore_sre) = if let Some(&(pos,ref sre))=ignore_it.next() { (Some(pos),Some(sre.clone())) } else { (None,None) }; for (i,token) in self.token_info.iter().enumerate() { if ignore_pos==(Some(i)) { if let Some(sre)=ignore_sre { println!("match {{ match parser.re(\"{}\",source) {{ None => None, Some((size,_string)) => Some((size,())) }} }}",sre); println!("{{ None => (), Some((size,_result)) => return Some((size,Token::DummyStart)), }};"); } if let Some(&(pos,ref sre))=ignore_it.next() { //(Some(pos),Some(sre.clone())) ignore_pos=(Some(pos)); ignore_sre=(Some(sre.clone())); } else { //(None,None) ignore_pos=None; ignore_sre=None; }; } if token.is_terminal { if let Some(ref sre)=token.re { //println!("PUT HERE THE MATCH WITH {} re={},",token.id,sre); if token.type_arguments.len()==0 { println!("match {{ match parser.re(\"{}\",source) {{ None => None, Some((size,_string)) => Some((size,())) }} }}",sre); println!("{{ None => (), Some((size,_result)) => return Some((size,Token::{})), }};",token.id); } else { println!("match {{ match parser.re(\"{}\",source) {{ None => None, Some((size,string)) => Some((size,string.parse::<{}>().unwrap() )) }} }}",sre,token.type_arguments.iter().map(|t|t.to_string()).collect::>().join(",")); println!("{{ None => (), Some((size,result)) => return Some((size,Token::{}(result))), }};",token.id); } } else if let Some(ref fun)=token.fn_match { //println!("PUT HERE THE MATCH WITH {},",token.id); println!("{{ {}",fun); if token.type_arguments.len()==0 { println!("match _match(parser,source) {{ None=>(), Some((size,_result)) => return Some((size,Token::{})), }} }};",token.id); } else { println!("match _match(parser,source) {{ None=>(), Some((size,result)) => return Some((size,Token::{}(result))), }} }};",token.id);//FIXME tuple } } else { panic!("terminal token {} has not matching function",token.id); } } } println!("None }}//match_some");//match_some println!("fn predict(parser:&mut Parser,index:usize,state_index:usize,token:usize) {{ match token {{"); let mut irule=1; for (i,token) in self.token_info.iter().enumerate() { if !token.is_terminal { println!("{} => {{",i+1); //println!("PRINT THE RULES OF TOKEN {}",token.id); for rule in token.rules.iter() { println!("parser.sets[index].predict(State{{rule: {} ,left: {} ,right:vec![ {} ],position:0,original_set:index,kind:EarleyKind::Predict(state_index),values:vec![Token::DummyStart; {} ],computed_value:Token::DummyStart,ambiguity_info:AmbiguityInfo::default(),}});",irule,i+1,rule.patterns.iter().map(|p|match p { &PatKind::Path(ref path) => match path { &PathKind::Ident(ref string) => self.token_name_to_index.get(string).expect(&format!("string {} not found in map",string)).to_string(), _ => panic!(""), }, &PatKind::Enum(ref name, _ ) => match name.as_ref() { &Token::PathExpr(PathKind::Ident(ref string)) => self.token_name_to_index.get(string).expect(&format!("string {} not found in map",string)).to_string(), _ => panic!(""), }, _ => panic!("received {:?}",p), }).collect::>().join(","),rule.patterns.len()); irule+=1; } println!("}}"); } } println!("_ => panic!(\"\"), }} }}//predict"); println!("fn compute_value(state:&mut State) {{ state.computed_value = match state.rule {{ 0 => state.values[0].clone(),"); //println!("GO THROUGH THE RULES"); let mut irule=1; for token in self.token_info.iter() { for rule in token.rules.iter() { let n=token.type_arguments.len(); if rule.patterns.len()==0 { if n==0 { println!("{} => Token::{},",irule,token.id); } else if n==1 { println!("{} => Token::{}({}),",irule,token.id,rule.expression); } else { let v=(0..n).map(|i| format!("x{}",i) ).collect::>().join(","); println!("{} => {{ let ({})={}; Token::{}({}) }},",irule,v,rule.expression,token.id,v); } } else { let pattern_string=rule.patterns.iter().map(|p|match p { &PatKind::Path(ref path) => match path { &PathKind::Ident(ref string) => { let index=self.token_name_to_index.get(string).expect(&format!("{} is not a token",string)); let n=self.token_info[*index-1].type_arguments.len(); if n==0 { format!("&Token::{}",string) } else { format!("&Token::{}({})",string,(0..n).map(|_|String::from("_")).collect::>().join(",")) } }, _ => panic!(""), }, &PatKind::Enum(ref name, ref tuple) => match name.as_ref() { &Token::PathExpr(ref string) => format!("&Token::{}({})",string,tuple.iter().map(|x| format!("{}",x) ).collect::>().join(",")), _ => panic!("name={:?} tuple={:?}",name,tuple), }, _ => panic!("received {:?}",p), }).collect::>().join(","); if rule.patterns.len()==1 { println!("{} => match &state.values[0] {{",irule); print!("{}",pattern_string); } else { println!("{} => match ({}) {{",irule,(0..rule.patterns.len()).map(|i| format!("&state.values[{}]",i) ).collect::>().join(",")); print!("({})",pattern_string); } if n==0 { //println!("({}) => Token::{},",pattern_string,token.id); println!(" => Token::{},",token.id); } else if n==1 { //println!("({}) => Token::{}({}),",pattern_string,token.id,rule.expression); println!(" => Token::{}({}),",token.id,rule.expression); } else { // We may need to do unpacking if >=2 // https://stackoverflow.com/questions/39878382/unpacking-tuples-into-arguments // https://github.com/rust-lang/rust/issues/17274 let v=(0..n).map(|i| format!("x{}",i) ).collect::>().join(","); println!(" => {{ let ({})={}; Token::{}({}) }},",v,rule.expression,token.id,v); } println!("_ => panic!(\"\"), }},"); } irule+=1; } } println!("_ => panic!(\"\"), }} }}//compute_value"); println!("fn table_terminal(token_index:usize)->bool {{ match token_index {{"); println!("{} => true,",self.token_info.iter().enumerate().filter_map(|(i,t)|if t.is_terminal {Some((i+1).to_string())} else {None}).collect::>().join("|")); println!("0|{} => false,",self.token_info.iter().enumerate().filter_map(|(i,t)|if !t.is_terminal {Some((i+1).to_string())} else {None}).collect::>().join("|")); println!("_ => panic!(\"table_terminal\"), }} }}//table_terminal"); println!("fn table_priority(a:usize, b:usize) -> Option {{ match (a,b) {{"); //println!("HERE THE PRIORITIES"); let mut irule=1; for ltoken in self.token_info.iter() { for lrule in ltoken.rules.iter() { if let Some(ref lorder)=lrule.priority { let mut jrule=1; for rtoken in self.token_info.iter() { for rrule in rtoken.rules.iter() { if let Some(ref rorder)=rrule.priority { //(6,6) => Some(Ordering::Equal), println!("({},{}) => Some(Ordering::{:?}),",irule,jrule,self.ordering.get(&(lorder.clone(),rorder.clone())).expect("what?")); } jrule+=1; } } } irule+=1; } } println!("_ => None, }} }}//table_priority"); println!("fn table_associativity(rule:usize) -> Option {{ match rule {{"); println!("_ => None, }} }}//table_associativity"); println!("fn to_usize(token:&Token) -> usize {{ match token {{ &Token::DummyStart => 0,"); for (i,token) in self.token_info.iter().enumerate() { if token.type_arguments.len()==0 { println!("&Token::{} => {},",token.id,i+1); } else { println!("&Token::{}({}) => {},",token.id,(0..token.type_arguments.len()).map(|_|String::from("_")).collect::>().join(","),i+1); } } println!("}} }}//to_usize"); println!("}}//impl");//impl } } fn main() { let args: Vec = env::args().collect(); //println!("{:?}", args); if args.len()!=2 { println!("Use:\n\t{} filename",args[0]); return; } let mut f = File::open(&args[1]).expect("file cannot be opened"); let mut contents = String::new(); f.read_to_string(&mut contents).expect("something went wrong reading the file"); //println!("With text:\n{}", contents); match Parser::::parse(&contents,None) { Err(x) => println!("error parsing: {:?}",x), Ok(x) => { //println!("parsed correctly: {:?}",x); let mut compiler=Compiler{ source: &x, token_info: vec![], first_nonterminal: None, token_name_to_index: HashMap::new(), ordering: HashMap::new(), ignore_res: vec![], }; compiler.compile(); }, }; }