@@ -265,10 +265,65 @@ KDL does not specify any restrictions on what implementations might do with
265265these annotations. They are free to ignore them, or use them to make decisions
266266about how to interpret a value.
267267
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 :
270299
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.
272327
273328Signed integers of various sizes (the number is the bit size) :
274329
@@ -335,6 +390,7 @@ IEEE 754-2008 decimal floating point numbers
335390
336391~~~kdl
337392node (u8)123
393+ node 123#i64
338394node prop=(regex).*
339395(published)date "1970-01-01"
340396(contributor)person name="Foo McBar"
@@ -1013,12 +1069,26 @@ multi-line-raw-string-body :=
10131069// Numbers
10141070number := keyword-number | hex | octal | binary | decimal
10151071
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+ )?
10171079exponent := ('e' | 'E') sign? integer
10181080integer := digit (digit | '_')*
10191081digit := [0-9]
10201082sign := '+' | '-'
10211083
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+
10221092hex := sign? '0x' hex-digit (hex-digit | '_')*
10231093octal := sign? '0o' [0-7] [0-7_]*
10241094binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')*
0 commit comments