Lexical structure
This page describes how Spine source text is broken into tokens: whitespace, comments, identifiers, literals, and punctuation.
Line terminators and whitespace
Whitespace (spaces, tabs, unicode spaces, vertical tab, form feed) and line terminators (\n, \r) separate tokens. They have no meaning beyond separating tokens.
Comments
- Line comment: from
//to the end of the line (the line break is not part of the comment). - Block comment:
/*…*/. Block comments do not nest.
Identifiers
- Start with a Unicode alphabetic character or
_. - Continue with Unicode letters, digits, or
_. - Version suffix: optional
@immediately followed by one or more ASCII digits, attached to the same identifier token (e.g.Foo@1,prop@42).
If an identifier spells a keyword exactly (case-sensitive), it is treated as that keyword (true, false, namespace, Struct, …).
Numeric literals
- Decimal integers: ASCII digits.
- Decimal floats: optional fractional part, optional exponent (
e/Ewith optional sign). An optional single suffix letter may follow:dDfFbBsSiIlL. - Hexadecimal:
0xor0Xplus hex digits (underscores may appear; invalid digit sequences are reported when the file is checked). - Octal:
0oor0O… - Binary:
0bor0B…
A . after a number starts a fractional part only when the following characters fit a numeric literal; otherwise . is member access (e.g. 1.23 vs e.0.foo).
String literals
- Double-quoted
"…"and single-quoted'…'. - Backslash starts an escape sequence. Unterminated strings are invalid.
Regular expression literals
When / can start a regex literal, the text is read as /pattern/optionalFlags. If that interpretation does not apply, / is the division operator. This distinction matters for expressions such as a / b versus /foo/g.
Boolean literals
true and false.
Punctuation and operators
Brackets [](){}, ;, ,, =, ?, :, ., single-character + - * % < > & ^ | ! ~, and multi-character << >> <= >= == != => && || ->. See Operators.
@ for annotations
A standalone @ begins a field annotation such as @AdminOnly. In name@123, the @123 part is a version on the name, not a separate annotation token.
Invalid characters
Characters that cannot start a valid token produce a diagnostic when you run dataspine check.