@@ -265,10 +265,65 @@ KDL does not specify any restrictions on what implementations might do with
265
265
these annotations. They are free to ignore them, or use them to make decisions
266
266
about how to interpret a value.
267
267
268
- Additionally, the following type annotations MAY be recognized by KDL parsers
269
- and, if used, SHOULD interpret these types as follows :
268
+ # ## Suffix Type Annotation
269
+
270
+ When a ({{value}}) is a ({{number}}), it's possible to attach the type
271
+ annotation as a "suffix", instead of prepending it between `(` and `)`. This
272
+ makes it possible to, for example, write `10px`, `10.5%`, `512GiB`, etc., which
273
+ are equivalent to `(px)10`, `(%)5`, and `(GiB)512`, respectively.
274
+
275
+ An implementation that finds BOTH a parenthesized and a suffix
276
+ ({{type-annotation}}) on the same ({{number}}) MUST yield a syntax error.
277
+
278
+ Suffixes MUST BE plain ({{identifier-string}})s. No other ({{string}}) is
279
+ acceptable.
280
+
281
+ There are two kinds of ({{suffix-type-annotation}}) available :
282
+ ({{bare-suffix-type-annotation}})s and ({{explicit-suffix-type-annotation}}).
283
+
284
+ # ### Bare Suffix Type Annotation
285
+
286
+ When a ({{value}}) is a decimal ({{number}}) WITHOUT exponential syntax (`1e+5`
287
+ etc) (and ONLY a decimal), it's possible to attach the type annotation as a
288
+ suffix directly to the number, without any additional syntax.
289
+
290
+ They also come with some additional rules (like only being available for
291
+ decimals), in order to prevent potential ambiguity or footguns with the syntax.
292
+ This is generally acceptable, as type annotations in particular tend to be
293
+ application-defined and limited in scope, rather than arbitrary user data. In
294
+ designing this feature, it was determined that the value for various real-world
295
+ DSLs outweighed the complexity of the following rules.
296
+
297
+ As such, to remove ambiguity, the suffix ({{identifier-string}}) MUST NOT start
298
+ with any of the following patterns, all of which MUST yield syntax errors :
270
299
271
- # ## Reserved Type Annotations for Numbers Without Decimals:
300
+ * `.`, `,`, or `_`
301
+ * `[a-zA-Z][0-9_]` (to disambiguate all non-decimals, with breathing room)
302
+ * `[eE][+-]?[0-9]` (to disambiguate exponentials)
303
+ * `[xX][a-fA-F]` (to disambiguate hexadecimals)
304
+
305
+ All other ({{identifier-strings}}) can be safely appended to decimal numbers, so
306
+ long as the decimal does not include an exponential component.
307
+
308
+ If the desired suffix would violate any of the above rules, either regular
309
+ parenthetical ({{type-annotation}})s, or ({{explicit-suffix-type-annotation}})s
310
+ may be used.
311
+
312
+ # ### Explicit Suffix Type Annotation
313
+
314
+ Any ({{number}}) may have a `#` attached to it, followed by any valid
315
+ ({{identifier-string}}). This is an explicit ({{suffix-type-annotation}}) syntax
316
+ without any of the relatively complex requirements of
317
+ ({{bare-suffix-type-annotation}}), which can be a useful escape hatch. For
318
+ example : ` 10.0#u8` is invalid syntax without the `#` prefix.
319
+
320
+ Note again that, unlike Bare Suffixes, Explicit Suffixes may be used with ALL
321
+ ({{number}}) formats (hexadecimal, decimal, octal, and binary).
322
+
323
+ # ## Reserved Type Annotations for Numbers Without Decimals
324
+
325
+ Additionally, the following type annotations MAY be recognized by KDL parsers
326
+ and, if used, SHOULD interpret these types as follows.
272
327
273
328
Signed integers of various sizes (the number is the bit size) :
274
329
@@ -335,6 +390,7 @@ IEEE 754-2008 decimal floating point numbers
335
390
336
391
~~~kdl
337
392
node (u8)123
393
+ node 123#i64
338
394
node prop=(regex).*
339
395
(published)date "1970-01-01"
340
396
(contributor)person name="Foo McBar"
@@ -1013,12 +1069,26 @@ multi-line-raw-string-body :=
1013
1069
// Numbers
1014
1070
number := keyword-number | hex | octal | binary | decimal
1015
1071
1016
- decimal := sign? integer ('.' integer)? exponent?
1072
+ decimal := sign? integer ('.' integer)? (
1073
+ // NOTE : This grammar does not explicitly guard against having both
1074
+ // parenthesized and type suffixes.
1075
+ bare-type-suffix |
1076
+ explicit-type-suffix |
1077
+ (exponent explicit-type-suffix?)
1078
+ )?
1017
1079
exponent := ('e' | 'E') sign? integer
1018
1080
integer := digit (digit | '_')*
1019
1081
digit := [0-9]
1020
1082
sign := '+' | '-'
1021
1083
1084
+ bare-type-suffix := bare-type-suffix-initial identifier-char*
1085
+ bare-type-suffix-initial := identifier-char
1086
+ - ' .' - ',' - '_'
1087
+ - ([a-zA-Z] [0-9_])
1088
+ - (('e' | 'E') sign? digit)
1089
+ - (('x' | 'X') [a-fA-F])
1090
+ explicit-type-suffix := '#' identifier-string
1091
+
1022
1092
hex := sign? '0x' hex-digit (hex-digit | '_')*
1023
1093
octal := sign? '0o' [0-7] [0-7_]*
1024
1094
binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')*
0 commit comments