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 }