extern crate gramatica; use std::cmp::Ordering; use std::io::BufRead; use gramatica::{Associativity,EarleyKind,State,Parser,ParsingTablesTrait,AmbiguityInfo}; // see http://www.rfc-editor.org/rfc/rfc3986.txt // also https://stackoverflow.com/questions/6243051/how-to-pass-an-array-within-a-query-string #[derive(Clone,Debug,PartialEq)] enum HierKind { Authority(), Absolute(), Rootless(), Empty, } re_terminal!(Digit(char),"[0-9]"); re_terminal!(AtoF(char),"[a-fA-F]"); re_terminal!(GtoZnoV(char),"[g-uw-zG-UW-Z]"); re_terminal!(V,"[vV]"); //re_terminal!(Scheme(String),"[a-zA-Z]([a-zA-Z0-9.-])*");// ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) //re_terminal!(UserInfo(String),"([a-zA-Z0-9:])*");//FIXME *( unreserved / pct-encoded / sub-delims / ":" ) //re_terminal!(RegName(String),"([a-zA-Z0-9])*");//FIXME *( unreserved / pct-encoded / sub-delims ) //re_terminal!(Port(String),"[0-9]*");//*DIGIT //re_terminal!(IPvFuture(String),"v[0-9A-F]\\.[a-zA-Z0-9:]");//FIXME "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) //re_terminal!(IPv6Address(String),"::");//FIXME buff ////re_terminal!(IPv4Address(String),"\\.\\.\\."); //re_terminal!(DecOctet(String),"[0-9]|[1-9][0-9]|1[0-9][0-9]|25[0-5]"); re_terminal!(Dot,"\\."); re_terminal!(At,"@"); re_terminal!(Colon,":"); re_terminal!(Slash,"/"); re_terminal!(LBracket,"\\["); re_terminal!(RBracket,"\\]"); re_terminal!(Percent,"%"); re_terminal!(Minus,"-"); re_terminal!(Underscore,"_"); re_terminal!(QuestionMark,"\\?"); re_terminal!(NumberSign,"#"); re_terminal!(Bang,"!"); re_terminal!(Dolar,"\\$"); re_terminal!(Ampersand,"&"); re_terminal!(SingleQuote,"'"); re_terminal!(LPar,"\\("); re_terminal!(RPar,"\\)"); re_terminal!(Star,"\\*"); re_terminal!(Plus,"\\+"); re_terminal!(Comma,","); re_terminal!(Semicolon,";"); re_terminal!(Equal,"="); nonterminal Uri(String,String,Option<>,Option<>) { (Scheme(ref scheme),Colon,HierPart(ref part),MaybeQuery(ref query),MaybeFragment(ref fragment)) => (scheme.clone(),part.clone(),query.clone(),fragment.clone()), } nonterminal HierPart(HierKind) { (Slash,Slash,Authority,PathABEmpty) => (), (PathAbsolute) => (), (PathRootless) => (), (PathEmpty) => (), } nonterminal Authority { (MaybeUserInfo,Host,MaybePort) => (), } nonterminal MaybeUserInfo { () => (), (UserInfo,At) => (), } nonterminal MaybePort { () => (), (Colon,Port) => (), } nonterminal Host { (IPLiteral) => (), (IPv4Address) => (), (RegName) => (), } nonterminal Port { () => (), (Digit,Port) => (), } nonterminal IPLiteral { (LBracket,IPv6Address,RBracket) => (), (LBracket,IPvFuture,RBracket) => (), } nonterminal IPvFuture { //"v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) (V,HexDigit,Dot,Unreserved) => (), (V,HexDigit,Dot,SubDelims) => (), (V,HexDigit,Dot,Colon) => (), } nonterminal IPv6Address { (Colon,Colon) => (), //FIXME ???????????? } nonterminal IPv4Address { (DecOctet,Dot,DecOctet,Dot,DecOctet,Dot,DecOctet) => (), } nonterminal DecOctet { (Digit) => (), (Digit1to9,Digit) => (), (Digit1,Digit,Digit) => (), (Digit2,Digit0to4,Digit) => (), (Digit2,Digit5,Digit0to5) => (), } nonterminal PathABEmpty { () => (), (PathABEmpty,Dash,Segment) => (), } nonterminal PathAbsolute { (Dash) => (), (Dash,SegmentNZ,Segments) => (), } nonterminal PathRootless { (SegmentNZ,Segments) => (), } nonterminal Segments(Vec) { () => vec![], (Segments(ref list),Slash,Segment(ref s)) => { let mut new=list.clone(); new.push(s); new }, } nonterminal Segment(String)//*pchar { () => String::new(), (Segment(ref a),Pchar(ref b)) => a+b, } nonterminal SegmentNZ(String) { (Pchar(ref s)) => s.clone(), (SegmentNZ(ref a),Pchar(ref b)) => a+b, } nonterminal PChar(String) { (Unreserved(c)) => c.to_string(), (PctEncoded(ref s)) => s.clone(), (SubDelims(c)) => c.to_string(), (Colon) => String::from(":"), (At) => String::from("@"), } nonterminal Query(String) { () => String::new(), (Query(ref a),QueryChar(ref b)) => a+b, } nonterminal QueryChar(String) { (PChar(ref s)) => s.clone(), (Slash) => String::from("/"), (QuestionMark) => String::from("?"), } nonterminal PctEncoded(String) { (Percent,HexDigit(a),HexDigit(b)) => format!("%{}{}",a,b), } nonterminal HexDigit(char) { (Digit(c)) => c, (AtoF(c)) => c, } nonterminal Unreserved(char) { (Alpha(c)) => c, (Digit(c)) => c, (Minus) => '-', (Dot) => '.', (Underscore) => '_', } nonterminal Alpha(char) { (AtoF(c)) => c, (GtoZnoV(c)) => c, (V) => 'v', } nonterminal Reserved(char) { (GenDelims(c)) => c, (SubDelims(c)) => c, } nonterminal GenDelims(char) { (Colon) => ':', (Slash) => '/', (QuestionMark) => '?', (NumberSign) => '#', (LBracket) => '[', (RBracket) => ']', (At) => '@', } nonterminal SubDelims(char) { (Bang) => '!', (Dolar) => '$', (Ampersand) => '&', (SingleQuote) => '\'', (LPar) => '(', (RPar) => ')', (Star) => '*', (Plus) => '+', (Comma) => ',', (Semicolon) => ';', (Equal) => '=', }