
cddl = S 1*rule
rule = typename [genericparm] S assign S type S
       / groupname [genericparm] S assign S grpent S

typename = id
groupname = id

assign = "=" / "/=" / "//="

genericparm = "<" S id S *("," S id S ) ">"
genericarg = "<" S type1 S *("," S type1 S ) ">"

type = type1 S *("/" S type1 S)

type1 = type2 [S (rangeop / ctlop) S type2]

lll

type2 = value
         / typename [genericarg]
         / "(" type ")"
         / "~" S groupname [genericarg]
         / "#" "6" ["." uint] "(" S type S ")" ; note no space!
         / "#" DIGIT ["." uint]                ; major/ai
         / "#"                                 ; any
         / "{" S group S "}"
         / "[" S group S "]"
         / "&" S "(" S group S ")"
         / "&" S groupname [genericarg]

rangeop = "..." / ".."

ctlop = "." id

group = grpchoice S *("//" S grpchoice S)

grpchoice = *grpent

grpent = [occur S] [memberkey S] type optcom
       / [occur S] groupname [genericarg] optcom ; preempted by above
       / [occur S] "(" S group S ")" optcom

memberkey = type1 S "=>"
          / bareword S ":"
          / value S ":"

bareword = id

optcom = S ["," S]

occur = [uint] "*" [uint]
      / "+"
      / "?"

uint = ["0x" / "0b"] "0"
     / DIGIT1 *DIGIT
     / "0x" 1*HEXDIG
     / "0b" 1*BINDIG

value = number
      / text
      / bytes

int = ["-"] uint

; This is a float if it has fraction or exponent; int otherwise
number = int ["." fraction] ["e" exponent ]
fraction = 1*DIGIT
exponent = int

text = %x22 *SCHAR %x22
SCHAR = %x20-21 / %x23-5B / %x5D-10FFFD / SESC
SESC = "\" %x20-10FFFD

bytes = [bsqual] %x27 *BCHAR %x27
BCHAR = %x20-26 / %x28-5B / %x5D-10FFFD / SESC / CRLF
bsqual = %x68 ; "h"
       / %x62.36.34 ; "b64"

id = EALPHA *(*("-" / ".") (EALPHA / DIGIT))
ALPHA = %x41-5A / %x61-7A
EALPHA = %x41-5A / %x61-7A / "@" / "_" / "$"
DIGIT = %x30-39
DIGIT1 = %x31-39
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
BINDIG = %x30-31

S = *WS
WS = SP / NL
SP = %x20
NL = COMMENT / CRLF
COMMENT = ";" *PCHAR CRLF
PCHAR = %x20-10FFFD
CRLF = %x0A / %x0D.0A
