; Note: This CDDL does not make sense *semantically*. ; These are various examples from the CDDL spec that ; should cover most syntax cases, however. pii = ( age: int, name: tstr, employer: tstr, ) person = { pii } person = {( age: int, name: tstr, employer: tstr, )} person = { identity, employer: tstr, } dog = { identity, leash-length: float, } identity = ( age: int, name: tstr, ) address = { delivery } delivery = ( street: tstr, ? number: uint, city // po-box: uint, city // per-pickup: true ) city = ( name: tstr, zip-code: uint ) attire /= "swimwear" delivery //= ( lat: float, long: float, drone-type: tstr ) device-address = bytefloat max-byte = 0b01001001 max-oct = 0o014 max-int = -123 max-float = 23.5 int-range = 0..10 ; only integers match float-range = 0.0..10.0 ; only floats match byte = 0..max-byte ; inclusive range first-non-byte = 256 byte1 = 0...first-non-byte ; byte1 is equivalent to byte BAD-range1 = 0..10.0 ; NOT DEFINED BAD-range2 = 0.0..10 ; NOT DEFINED numeric-range = int-range / float-range terminal-color = &basecolors basecolors = ( black: 0, red: 1, green: 2, yellow: 3, blue: 4, magenta: 5, cyan: 6, white: 7, ) extended-color = &( basecolors, orange: 8, pink: 9, purple: 10, brown: 11, ) foo = # my_breakfast = #6.55799(breakfast) ; cbor-any is too general! breakfast = cereal / porridge cereal = #6.998(tstr) porridge = #6.999([liquid, solid]) liquid = milk / water milk = 0 water = 1 solid = tstr ; This is a comment person = { g } g = ( "name": tstr, age: int, ; "age" is a bareword ) apartment = { kitchen: size, * bedroom: size, } size = float ; in m2 unlimited-people = [* person] one-or-two-people = [1*2 person] at-least-two-people = [2* person] person = ( name: tstr, age: uint, ) Geography = [ city : tstr, gpsCoordinates : GpsCoordinates, ] GpsCoordinates = { longitude : uint, ; multiplied by 10^7 latitude : uint, ; multiplied by 10^7 } located-samples = { sample-point: int, samples: [+ float], } proper-ints = 1 / 0 ;invalid-int = 01 flt = 1.23 flt = -1.23 flt = 1.23e+10 flt = 1.23e-10 flt = 1.23e10 val = 123 located-samples = { sample-point: int, samples: [+ float], * equipment-type => equipment-tolerances, } equipment-type = [name: tstr, manufacturer: tstr] equipment-tolerances = [+ [float, float]] PersonalData = { ? displayName: tstr, NameComponents, ? age: uint, * tstr => any } NameComponents = ( ? firstName: tstr, ? familyName: tstr, ) square-roots = {* x => y} x = int y = float extensible-map-example = { ? "optional-key" ^ => int, * tstr => any } extensible-map-example = { ? "optional-key": int, * tstr => any } extensible-map-example = { ? optional-key: int, * tstr => any } biguint = #6.2(bstr) buuid = #6.37(bstr) my_uri = #6.32(tstr) / tstr basic-header = [ field1: int, field2: text, ] advanced-header = [ ~basic-header, field3: bytes, field4: ~time, ] hexfloat = 0xcafe.badp-9sdf hexfloat = 0xcafe.badp-9 full-address = [[+ label], ip4, ip6] ip4 = bstr .size 4 ip6 = bstr .size 16 label = bstr .size (1..63) member-keys = { bare-word: true, "string": false, 4711: number, 0xdecafe: false, } audio_sample = uint .size 3 ; 24-bit, equivalent to 0...16777216 tcpflagbytes = bstr .bits flags flags = &( fin: 8, syn: 9, rst: 10, psh: 11, ack: 12, urg: 13, ece: 14, cwr: 15, ns: 0, ) / (4..7) ; data offset bits rwxbits = uint .bits rwx rwx = &(r: 2, w: 1, x: 0) nai = tstr .regexp "[A-Za-z0-9]+@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)+" message = $message .within message-structure message-structure = [message_type, *message_option] message_type = 0..255 message_option = any $message /= [3, dough: text, topping: [* text]] $message /= [4, noodles: text, sauce: text, parmesan: bool] speed = number .ge 0 ; unit: m/s timer = { time: uint, ? displayed-step: (number .gt 0) .default 1 } tcp-header = {seq: uint, ack: uint, * $$tcp-option} ; later, in a different file $$tcp-option //= ( sack: [+(left: uint, right: uint)] ) ; and, maybe in another file $$tcp-option //= ( sack-permitted: true ) PersonalData = { ? displayName: tstr, NameComponents, ? age: uint, * $$personaldata-extensions } NameComponents = ( ? firstName: tstr, ? familyName: tstr, ) ; The above already works as is. ; But then, we can add later: $$personaldata-extensions //= ( favorite-salsa: tstr, ) ; and again, somewhere else: $$personaldata-extensions //= ( shoesize: uint, ) messages = message<"reboot", "now"> / message<"sleep", 1..100> message = {type: t, value: v} t = [group1] group1 = (a / b // c / d) a = 1 b = 2 c = 3 d = 4 t = {group2} group2 = (? ab: a / b // cd: c / d) a = 1 b = 2 c = 3 d = 4 t = [group3] group3 = (+ a / b / c) a = 1 b = 2 c = 3 t = [group4] group4 = (+ a // b / c) a = 1 b = 2 c = 3 t = [group4a] group4a = ((+ a) // (b / c)) a = 1 b = 2 c = 3 byte-strings = 'hello world' / h'68656c6c6f20776f726c64' / b64'Zm-9v_YmE=' ;byte-strings-w-errors = h'68656gc6c6f2077oops6f726c64' / b64'Zm+9vY/mE=' oneline-bstr = '' multiline-bstr = ' ' multiline-hex = h' 83 ; \'83\' means Array of length 3 01 ; 1 82 ; Array of length 2 02 ; 2 03 ; 3 82 ; Array of length 2 04 ; 4 05 ; 5 ' ;multiline-hex-err = h' ; 83 \'83\' means Array of length 3 (oops, missed the \';\') ; 01 ; 1 ;' ; THE STANDARD "POSTLUDE" any = # uint = #0 nint = #1 int = uint / nint bstr = #2 bytes = bstr tstr = #3 text = tstr tdate = #6.0(tstr) time = #6.1(number) number = int / float biguint = #6.0x02(bstr) biguint = #6.2(bstr) bignint = #6.3(bstr) bigint = biguint / bignint integer = int / bigint unsigned = uint / biguint decfrac = #6.4([e10: int, m: integer]) bigfloat = #6.5([e2: int, m: integer]) eb64url = #6.21(any) eb64legacy = #6.22(any) eb16 = #6.23(any) encoded-cbor = #6.24(bstr) uri = #6.32(tstr) b64url = #6.33(tstr) b64legacy = #6.34(tstr) regexp = #6.35(tstr) mime-message = #6.36(tstr) cbor-any = #6.55799(any) float16 = #7.25 float32 = #7.26 float64 = #7.27 float16-32 = float16 / float32 float32-64 = float32 / float64 float = float16-32 / float64 false = #7.20 true = #7.21 bool = false / true nil = #7.22 null = nil undefined = #7.23 ; INVALID CDDL ;invalid_identifier- = -another_invalid ;untermindated-string = "sometimes I cannot finish my… ;next-thought = { valid: true }