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<String>)
{
() => 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) => '=',
}