# https://github.com/mwherman2000/did-uri-spec/tree/master/abnf/did-uri-spec-2019-04-03.abnf

# !syntax("abnf")
did                       = did-method method-specific-idstring;
did-method                = did-root method ":";
did-root                  = "did" ":";

method                    = 1*methodchar;
methodchar                = %x61-7A / DIGIT;
method-specific-idstring  = idstring *( ":" idstring );
idstring                  = 1*idchar;
idchar                    = ALPHA / DIGIT / "." / "-";

did-uri                   = did-optional-transform
                          / did-method-transform
                          / did-root-transform;
                          
did-optional-transform    = did [ transform ] [ path-abempty ] [ "?" query ] [ "#" fragment ];
did-method-transform      = did-method transform;
did-root-transform         = did-root transform;

transform                 = TRANSFORM transformer *( "&" transformer );
transformer               = "$" transformer-option [ transformer-namedvalue ];
transformer-namedvalue    = "=" DQUOTE transformer-value DQUOTE;
transformer-option        = transformer-options;
transformer-value         = *transformer-char;
transformer-char          = ALPHA / DIGIT / "." / "-";

TRANSFORM                 =  %x21;                # !

generic-option            = ALPHA 1*transformer-char;

transformer-options       = generic-option;

#------------------------------------------------------------------------------
# A. URI syntax [RFC3986]
#------------------------------------------------------------------------------

URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ];
hier-part     = "//" authority path-abempty
              / path-absolute
              / path-rootless;
#              / path-empty;
#URI-reference = URI / relative-ref;
#absolute-URI  = scheme ":" hier-part [ "?" query ];
#relative-ref  = relative-part [ "?" query ] [ "#" fragment ];
#relative-part = "//" authority path-abempty
#              / path-absolute
#              / path-noscheme
#              / path-empty;
scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." );
authority     = [ userinfo "@" ] host [ ":" port ];
userinfo      = *( unreserved / pct-encoded / sub-delims / ":" );
host          = IP-literal / IPv4address / reg-name;
port          = *DIGIT;
IP-literal    = "[" ( IPv6address / IPvFuture  ) "]";
IPvFuture     = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" );
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 ] "::";
h16           = 1*4HEXDIG;
ls32          = ( h16 ":" h16 ) / IPv4address;
IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet;
dec-octet     = "1" 2DIGIT            # 100-199
              / "2" %x30-34 DIGIT     # 200-249
              / "25" %x30-35          # 250-255
              / %x31-39 DIGIT         # 10-99
              / DIGIT;                # 0-9
reg-name      = *( unreserved / pct-encoded / sub-delims );
#path          = path-abempty    # begins with "/" or is empty
#              / path-absolute   # begins with "/" but not "//"
#              / path-noscheme   # begins with a non-colon segment
#              / path-rootless   # begins with a segment
#              / path-empty;     # zero characters
path-abempty  = *( "/" segment );
path-absolute = "/" [ segment-nz *( "/" segment ) ];
#path-noscheme = segment-nz-nc *( "/" segment );
path-rootless = segment-nz *( "/" segment );
#path-empty    = "";
segment       = *pchar;
segment-nz    = 1*pchar;
#segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) # non-zero-length segment without any colon ":";
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@";
query         = *( pchar / "/" / "?" );
fragment      = *( pchar / "/" / "?" );
pct-encoded   = "%" HEXDIG HEXDIG;
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~";
#reserved      = gen-delims / sub-delims;
#gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@";
#sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=";
sub-delims     =       "$" / "&" / "'" /                                     "=" / other-delims;
other-delims   = "!" /                   "(" / ")" / "*" / "+" / "," / ";";

pchar-no-SQUOTE       = unreserved / pct-encoded-no-SQUOTE / other-delims / "$" / "&" / "=" / ":" / "@";
pct-encoded-no-SQUOTE = "%" ( "0" / "1" /   "3" / "4" / "5" / "6" / "8" / "9" / A-to-F ) HEXDIG
                      / "%" "2" ( "0" / "1" / "2" / "3" / "4" / "5" / "6" /   "8" / "9" / A-to-F );

qchar-no-AMP              = unreserved / pct-encoded / other-delims / ":" / "@" / "/" / "?" / "$" / "'" / "=";
qchar-no-AMP-EQ           = unreserved / pct-encoded / other-delims / ":" / "@" / "/" / "?" / "$" / "'";
qchar-no-AMP-EQ-AT-DOLLAR = unreserved / pct-encoded / other-delims / ":" /       "/" / "?" /       "'";

##qchar-unescaped       = unreserved / pct-encoded-unescaped / other-delims / ":" / "@" / "/" / "?" / "$" / "'" / "=";
##pct-encoded-unescaped = "%" ( "0" / "1" /   "3" / "4" /   "6" / "7" / "8" / "9" / A-to-F ) HEXDIG 
##                      / "%" "2" ( "0" / "1" /   "3" / "4" / "5" / "6" / "7" / "8" / "9" / A-to-F ) 
##                      / "%" "5" ( DIGIT / "A" / "B" /   "D" / "E" / "F" );

##qchar-no-AMP-DQUOTE   = qchar-unescaped 
##                      / escape ( escape / quotation-mark );
                 
                 
#------------------------------------------------------------------------------
# B. IRI syntax [RFC3987]
#------------------------------------------------------------------------------
# Note: these are over-generous stubs, for the actual patterns refer to RFC3987
#------------------------------------------------------------------------------

##IRI-in-header = 1*( VCHAR / obs-text );
##IRI-in-query  = 1*qchar-no-AMP;

                      
#------------------------------------------------------------------------------
# C. ABNF core definitions [RFC5234]
#------------------------------------------------------------------------------

ALPHA  = %x41-5A / %x61-7A;
DIGIT  = %x30-39;
HEXDIG = DIGIT / A-to-F;
A-to-F = "A" / "B" / "C" / "D" / "E" / "F";
DQUOTE = %x22;
SP     = %x20;
HTAB   = %x09;
#WSP    = SP / HTAB;
#LWSP = *(WSP / CRLF WSP);
VCHAR = %x21-7E;
#CHAR = %x01-7F;
#LOCTET = %x00-FF;
#CR     = %x0D;
#LF     = %x0A;
#CRLF   = CR LF;
#BIT = "0" / "1";
