// basd on RFC3986 and RFC6874 // char types: digit:alias:failpass = [0-9]; hex:alias:failpass = [0-9a-fA-F]; alpha:alias:failpass = [a-zA-Z]; delimiter:alias:failpass = ":" | "/" | "?" | "#" | "[" | "]" | "@"; subdelimiter:alias:failpass = "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | ";" | "="; unreserved:alias:failpass = alpha | digit | "-" | "." | "_" | "~"; reserved:alias:failpass = delimiter | subdelimiter; percent-encoded:alias:failpass = "%" hex{2}; path-char:alias:failpass = unreserved | percent-encoded | subdelimiter | ":" | "@"; // scheme: scheme = alpha (alpha | digit | [+-.])*; // userinfo: userinfo = (unreserved | percent-encoded | subdelimiter | ":")*; // IPv4: dec-byte:alias:failpass = digit | [1-9] digit | "1" digit{2} | "2" [0-4] digit | "25" [0-5]; ipv4:failpass = dec-byte ("." dec-byte){3}; // IPv6: h16:alias:failpass = hex{1,4}; ls32:alias:failpass = h16 ":" h16 | ipv4; ipv6:failpass = (h16 ":"){6} ls32 | "::" (h16 ":"){5} ls32 | h16? "::" (h16 ":"){4} ls32 | ((h16 ":")? h16)? "::" (h16 ":"){3} ls32 | ((h16 ":"){,2} h16)? "::" (h16 ":"){2} ls32 | ((h16 ":"){,3} h16)? "::" h16 ":" ls32 | ((h16 ":"){,4} h16)? "::" ls32 | ((h16 ":"){,5} h16)? "::" h16 | ((h16 ":"){,6} h16)? "::"; zone-id:alias:failpass = (unreserved | percent-encoded)+; ipv6-zone:failpass = ipv6 "%25" zone-id; // RFC6874 // host: registry-name-rfc:failpass = (unreserved | percent-encoded | subdelimiter)*; // all RFC chars allowed dns-label:alias:failpass = (alpha | digit) ("-"* (alpha | digit)+)*; domain-name:failpass = dns-label ("." dns-label)* "."?; // DNS compatible hostname-rfc = ipv4 | "[" (ipv6 | ipv6-zone) "]" | registry-name-rfc; hostname = ipv4 | "[" (ipv6 | ipv6-zone) "]" | domain-name; port = digit*; host-rfc:alias:failpass = hostname-rfc (":" port)?; host:alias:failpass = hostname (":" port)?; // path: segment:alias:failpass = path-char*; segment-non-zero:alias:failpass = path-char+; segment-non-zero-no-colon:alias:failpass = (unreserved | percent-encoded | subdelimiter | "@")+; path-absolute-or-empty = ("/" segment)*; path-absolute = "/" (segment-non-zero ("/" segment)*)?; path-rootless = segment-non-zero ("/" segment)*; path-noscheme = segment-non-zero-no-colon ("/" segment)*; path-empty = ""; query = (path-char | "/" | "?")*; fragment = (path-char | "/" | "?")*; // composed together: authority-rfc:alias:failpass = (userinfo "@")? host-rfc; authority:alias:failpass = (userinfo "@")? host; hierarchy-part-rfc:alias:failpass = "//" authority-rfc path-absolute-or-empty | path-absolute | path-rootless | path-empty; hierarchy-part:alias:failpass = "//" authority path-absolute-or-empty | path-absolute | path-rootless | path-empty; relative-part-rfc:alias:failpass = "//" authority-rfc path-absolute-or-empty | path-absolute | path-noscheme | path-empty; relative-part:alias:failpass = "//" authority path-absolute-or-empty | path-absolute | path-noscheme | path-empty; absolute-url-rfc = scheme ":" hierarchy-part-rfc ("?" query)? ("#" fragment)?; absolute-url = scheme ":" hierarchy-part ("?" query)? ("#" fragment)?; relative-url-rfc = relative-part-rfc ("?" query)? ("#" fragment)?; relative-url = relative-part ("?" query)? ("#" fragment)?; // supporting four possible types URLs: url:root = absolute-url | absolute-url-rfc | relative-url | relative-url-rfc;