Lexical Structure
This chapter defines the lexical grammar of Lattice: the rules by which a sequence of characters is broken into tokens. The lexer processes source code left-to-right, producing a stream of tokens that the parser consumes.
Source Encoding
Lattice source files are encoded in UTF-8. String literals may contain arbitrary UTF-8 sequences. Identifiers are restricted to ASCII letters, digits, and underscores.
Whitespace and Line Breaks
Whitespace characters (space, tab, carriage return, newline) serve as token separators
and are otherwise insignificant. Lattice does not use significant whitespace for block structure;
blocks are delimited by braces { }.
Comments
Lattice supports two forms of comments:
- Line comments begin with
//and extend to the end of the line. - Block comments begin with
/*and end with*/. Block comments nest: each/*must have a matching*/.
// This is a line comment /* This is a block comment */ /* Block comments /* can be */ nested */
Keywords
The following 38 identifiers are reserved as keywords and cannot be used as variable or function names:
| Category | Keywords |
|---|---|
| Bindings | flux fix let |
| Phase | freeze thaw forge clone anneal crystallize sublimate |
| Declarations | fn struct enum trait impl test |
| Control flow | if else for in while loop match |
| Jump | return break continue |
| Concurrency | scope spawn |
| Error handling | try catch defer |
| Modules | import from as |
| Literals | true false nil |
| Built-in | print |
Contextual Identifiers
The following identifiers are not reserved but have special meaning in certain syntactic positions. They may be used as variable names elsewhere:
| Identifier | Context |
|---|---|
select | Channel multiplexing expression |
default | Default arm in select |
timeout | Timeout arm in select |
where | Contract clause in freeze() |
except | Exception list in freeze() |
require | Function precondition |
ensure | Function postcondition |
fluid | Phase qualifier in match patterns |
crystal | Phase qualifier in match patterns |
Identifiers
identifier ::= (letter | "_") { letter | digit | "_" } letter ::= "a".."z" | "A".."Z" digit ::= "0".."9"
Identifiers begin with a letter or underscore, followed by any combination of letters, digits, and underscores. Identifiers are case-sensitive.
Literals
Integer Literals
int_literal ::= digit { digit }
Integer literals are sequences of decimal digits. They represent 64-bit signed integers
(int64_t). Negative integer literals are formed by applying the unary negation
operator to a positive literal.
Float Literals
float_literal ::= digit { digit } "." digit { digit }
Float literals contain a decimal point with digits on both sides. They represent 64-bit IEEE 754 double-precision floating point values.
String Literals
Lattice supports three forms of string literals:
Double-Quoted Strings
double_string ::= '"' { string_char | escape | interpolation } '"'
Double-quoted strings support escape sequences and string interpolation with ${...}.
Single-Quoted Strings
single_string ::= "'" { string_char | escape } "'"
Single-quoted strings support escape sequences but not interpolation.
Triple-Quoted Strings
triple_string ::= '"""' { any_char | interpolation } '"""'
Triple-quoted strings span multiple lines, support interpolation, and auto-dedent based on the minimum indentation of non-empty lines.
Escape Sequences
| Escape | Character |
|---|---|
\n | Newline (LF) |
\t | Tab |
\r | Carriage return |
\0 | Null byte |
\\ | Backslash |
\" | Double quote |
\' | Single quote |
\$ | Dollar sign (escape interpolation) |
\xHH | Hex byte value |
String Interpolation
interpolation ::= "${" expression "}"
Within double-quoted and triple-quoted strings, ${...} embeds an expression
whose value is converted to a string at runtime. The expression may be any valid Lattice
expression, including method calls and nested interpolations.
let name = "world" print("hello ${name}") // hello world print("2 + 2 = ${2 + 2}") // 2 + 2 = 4 print("upper: ${name.to_upper()}") // upper: WORLD
Boolean Literals
The keywords true and false are boolean literals.
Nil Literal
The keyword nil represents the absence of a value.
Operators and Punctuation
Lattice defines the following operator and punctuation tokens:
| Category | Tokens |
|---|---|
| Arithmetic | + - * / % |
| Comparison | == != < > <= >= |
| Logical | && || ! |
| Bitwise | & | ^ ~ << >> |
| Assignment | = += -= *= /= %= &= |= ^= <<= >>= |
| Range | .. |
| Spread | ... |
| Arrow | -> => |
| Optional | ?. ?[ ?? ? |
| Dot | . |
| Delimiters | ( ) { } [ ] |
| Punctuation | , : :: ; |
| Phase prefix | ~ (fluid) * (crystal) |
Mode Directive
mode_directive ::= "#mode" ("casual" | "strict")
A mode directive, if present, must appear at the beginning of the source file (before any statements or items). It controls the strictness of phase checking.
Lattice