; Copyright Glen Knowles 2017 - 2018.
; Distributed under the Boost Software License, Version 1.0.
;
; uri.abnf - dim uri
;
; Rules to parse uri, based on the ABNF in the spec at:
;   https://tools.ietf.org/html/rfc3986

%root = URI
%api.prefix = Uri
%api.namespace = Dim::Detail

; Characters
gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
qry-delims  = "!" / "$" / "'" / "(" / ")" / "*" / "," / ";"
sub-delims  = qry-delims / "&" / "=" / "+"
unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~" { Char }

gen-delims-copy = gen-delims { Char, As copy }


pct-encoded = "%" pct-high pct-low
pct-high    = HEXDIG { Char }
pct-low     = HEXDIG { Char }

; URI Grammar
URI = scheme "://" authority path-abempty [ "?" query ] [ "#" fragment ]

http-path = "*" / origin-form
origin-form = absolute-path [ "?" query ]

; Scheme
scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) { Start+, End+ }

; Authority
authority   = [ userinfo "@" ] host [ ":" port ]
userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
host        = IP-literal / IPv4address / reg-name { End+ }
port        = *5DIGIT { Char+ }

IP-literal  = "[" ( IPv6address ["%25" ZoneId] / IPvFuture  ) "]"
IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
ZoneId      = 1*( unreserved / pct-encoded )

IPv6address =                            6( h16 ":" ) ls32
            /                       "::" 5( h16 ":" ) ls32
            / [               h16 ] "::" 4( h16 ":" ) ls32
            / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
            / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
            / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
            / [ *4( h16 ":" ) h16 ] "::"              ls32
            / [ *5( h16 ":" ) h16 ] "::"              h16
            / [ *6( h16 ":" ) h16 ] "::"

ls32        = ( h16 ":" h16 ) / IPv4address
            ; least-significant 32 bits of address

h16         = 1*4HEXDIG
            ; 16 bits of address represented in hexadecimal

IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
dec-octet   = DIGIT                 ; 0-9
            / %x31-39 DIGIT         ; 10-99
            / "1" 2DIGIT            ; 100-199
            / "2" %x30-34 DIGIT     ; 200-249
            / "25" %x30-35          ; 250-255

reg-name    = *( unreserved / pct-encoded / sub-delims )

; Path
absolute-path = 1*( "/" segment )
path-abempty  = *( "/" segment )
segment       = *pchar { Start+, End+ }
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"

; Query
query       = [ qry-pair ] *("&" qry-pair)
qry-pair    = qry-name [ "=" qry-value ]
qry-name    = 1*qchar { Start+, End+ }
qry-value   = *(qchar / "=") { Start+, End+ }
qchar       = unreserved / pct-encoded / qry-delims / qry-plus
            / ":" / "@" / "/" / "?"
qry-plus    = "+" { Char }

; Fragment
fragment    = *( pchar / "/" / "?" ) { Start, End }
