1 using System.Net.Http;
  2 using UriTokens;
  3 
  4 parser Uri
  5 {
  6     uselexer UriLexer;
  7     main;
  8     
  9     uri_reference : UriReference
 10         ::= absolute_uri:au{ return au; } | relative_ref:rr{ return rr; }
 11         ;
 12     
 13     absolute_uri(var UriReference uriReference) : UriReference
 14         ::= (scheme:schm{ uriReference.SetScheme(schm); } 
 15             COLON
 16             hier_part(&uriReference):hp
 17             (QUEST query:qry{ uriReference.SetQuery(qry); })?
 18             (HASH fragment:frg{ uriReference.SetFragment(frg); })?
 19         )
 20         { 
 21             return uriReference; 
 22         }
 23         ;
 24         
 25     scheme(var string s) : string
 26         ::= ((scheme_char:sc{ s.Append(sc); })+){ return s; }
 27         ;
 28         
 29     scheme_char : char
 30         ::= ALPHA{ return lexer.GetChar(pos); } | DIGIT{ return lexer.GetChar(pos); } | DASH{ return '-'; } | PLUS{ return '+'; } | DOT{ return '.'; }
 31         ;
 32         
 33     hier_part(UriReference* uriReference)
 34         ::= SLASH SLASH authority:a{ uriReference->SetAuthority(a); } path_abempty:pae{ uriReference->SetPath(pae); }
 35         |   path_absolute:pa{ uriReference->SetPath(pa); }
 36         |   path_rootless:pr{ uriReference->SetPath(pr); }
 37         |   path_empty:pe{ uriReference->SetPath(pe); }
 38         ;
 39         
 40     relative_ref(var UriReference uriReference) : UriReference
 41         ::= (relative_part(&uriReference):rp
 42             (QUEST query:qry{ uriReference.SetQuery(qry); })? 
 43             (HASH fragment:frg{ uriReference.SetFragment(frg); })?)
 44         {
 45             return uriReference;
 46         }
 47         ;
 48         
 49     relative_part(UriReference* uriReference)
 50         ::= SLASH SLASH authority:a{ uriReference->SetAuthority(a); } path_abempty:pae{ uriReference->SetPath(pae); }
 51         |   path_absolute:pa{ uriReference->SetPath(pa); }
 52         |   path_noscheme:pn{ uriReference->SetPath(pn); }
 53         |   path_empty:pe{ uriReference->SetPath(pe); }
 54         ;
 55         
 56     authority(var Authority a) : Authority
 57         ::= ((userinfo:ui AT{ a.SetUserInfo(ui); })? host:h{ a.SetHost(h); } (COLON port:p{ a.SetPort(p); })?){ return a; }
 58         ;
 59         
 60     userinfo(var string s) : string
 61         ::= ((unreserved:u{ s.Append(u); } | pct_encoded:e{ s.Append(e); } | sub_delims:d{ s.Append(d); } | COLON{ s.Append(':'); })*){ return s; }
 62         ;
 63         
 64     host : string
 65         ::= ip_literal:iplit{ return iplit; } | ipv4_address:ipv4{ return ipv4; } | reg_name:rn{ return rn; }
 66         ;
 67         
 68     ip_literal(var string s) : string
 69         ::= (LBRACKET{ s.Append('['); } (ipv6_address:ipv6{ s.Append(ipv6); } | ipv_future:ipvf{ s.Append(ipvf); }) RBRACKET{ s.Append(']'); }){ return s; }
 70         ;
 71         
 72     ipv4_address(var string s) : string
 73         ::= ((DIGIT{ s.Append(lexer.GetChar(pos)); })+ DOT{ s.Append('.'); } 
 74             (DIGIT{ s.Append(lexer.GetChar(pos)); })+ DOT{ s.Append('.'); } 
 75             (DIGIT{ s.Append(lexer.GetChar(pos)); })+ DOT{ s.Append('.'); } 
 76             (DIGIT{ s.Append(lexer.GetChar(pos)); })+){ return s; }
 77         ;
 78 
 79     ipv6_address(var string s) : string
 80         ::= ((ipv6_char:c{ s.Append(c); })+){ return s; }
 81         ;
 82         
 83     ipv6_char : char
 84         ::= DIGIT{ return lexer.GetChar(pos); } | HEX{ return lexer.GetChar(pos); } | COLON{ return ':'; }| DOT{ return '.'; } | SLASH{ return '/'; }
 85         ;
 86 
 87     ipv_future(var string s) : string
 88         ::= (ALPHA{ pass = lexer.GetChar(pos) == 'v'; } (DIGIT{ s.Append(lexer.GetChar(pos)); } | HEX{ s.Append(lexer.GetChar(pos)); })+ DOT{ s.Append('.'); }
 89             (unreserved:u{ s.Append(u); } | sub_delims:d{ s.Append(d); } | COLON{ s.Append(':'); })+){ return s; }
 90         ;
 91        
 92     port(var string s) : int
 93         ::= ((DIGIT{ s.Append(lexer.GetChar(pos)); })*){ return ParseInt(s); }
 94         ;
 95         
 96     reg_name(var string s) : string
 97         ::= ((unreserved:u{ s.Append(u); } | pct_encoded:e{ s.Append(e); } | sub_delims:d{ s.Append(d); })*){ return s; }
 98         ;
 99         
100     path_abempty(var string s) : string
101         ::= ((SLASH segment:seg{ s.Append('/').Append(seg); })*){ return s; }
102         ;
103         
104     path_absolute(var string s) : string
105         ::= SLASH{ s.Append('/'); } (segment_nz:snz{ s.Append(snz); } (SLASH segment:seg{ s.Append('/').Append(seg); })*){ return s; }
106         ;
107         
108     path_noscheme(var string s) : string
109         ::= (segment_nz_nc:snz{ s.Append(snz); } (SLASH segment:seg{ s.Append('/').Append(seg); })*){ return s; }
110         ;
111         
112     path_rootless(var string s) : string
113         ::= (segment_nz:snz{ s.Append(snz); } (SLASH segment:seg{ s.Append('/').Append(seg); })*){ return s; }
114         ;
115         
116     path_empty : string
117         ::= empty{ return string(); }
118         ;
119         
120     segment(var string s)  : string
121         ::= ((pchar:pc{ s.Append(pc); })*){ return s; }
122         ;
123     
124     segment_nz(var string s) : string
125         ::= ((pchar:pc{ s.Append(pc); })+){ return s; }
126         ;
127         
128     segment_nz_nc(var string s) : string
129         ::= ((unreserved:u{ s.Append(u); } | pct_encoded:e{ s.Append(e); } | sub_delims:d{ s.Append(d); } | AT{ s.Append('@'); })+){ return s; }
130         ;
131         
132     query(var string s) : string
133         ::= ((pchar:pc{ s.Append(pc); } | SLASH{ s.Append('/'); } | QUEST{ s.Append('?'); })*){ return s; }
134         ;
135         
136     fragment(var string s) : string
137         ::= ((pchar:pc{ s.Append(pc); } | SLASH{ s.Append('/'); } | QUEST{ s.Append('?'); })*){ return s; }
138         ;
139         
140     pchar : char
141         ::= unreserved:u{ return u; } | pct_encoded:e{ return e; } | sub_delims:d{ return d; } | COLON{ return ':'; } | AT{ return '@'; }
142         ;
143         
144     unreserved : char
145         ::= ALPHA{ return lexer.GetChar(pos); } | HEX{ return lexer.GetChar(pos); } | DIGIT{ return lexer.GetChar(pos); } | DOT{ return '.'; } | DASH{ return '-'; } | UNDERSCORE{ return '_'; } | TILDE{ return '~'; }
146         ;
147         
148     reserved : char
149         ::= gen_delims:gd{ return gd; } | sub_delims:sd{ return sd; }
150         ;
151         
152     gen_delims : char
153         ::= COLON{ return ':'; } | SLASH{ return '/'; } | QUEST{ return '?'; } | HASH{ return '#'; } | LBRACKET{ return '['; } | RBRACKET{ return ']'; } | AT{ return '@'; }
154         ;
155         
156     sub_delims : char
157         ::= EXCLAMATION{ return '!'; } | DOLLAR{ return '$'; } | AMP{ return '&'; } | SQ{ return '\''; } | LPAREN{ return '('; } | RPAREN{ return ')'; } | ASTERISK{ return '*'; } | PLUS{ return '+'; } | COMMA{ return ','; } | 
158             SEMICOLON{ return ';'; } | EQ{ return '='; }
159         ;
160         
161     pct_encoded(var string s) : char
162         ::= (PERCENT hex:x1{ s.Append(x1); } hex:x2{ s.Append(x2); }){ return cast<char>(ParseHexByte(s)); }
163         ;
164         
165     hex : char
166         ::= DIGIT{ return lexer.GetChar(pos); } | HEX{ return lexer.GetChar(pos); }
167         ;
168 }