2. Lexical Structure
2.1 Input Format
Culsma source text:
MUSTbe parsed as UTF-8.MAYuseLForCRLFline endings.MUSTbe tokenized left-to-right under these lexical rules.
Parsing errors in source format or token stream MUST surface as syntax errors.
2.2 Keywords
Keyword set:
protocolincludeletrepeatifelsebreakcontinueandortruefalse
Parser-surface control keywords additionally include:
withenvconstraint
Surface notes:
includeis reserved for source-level file loading and for the protocol-include statement surface.- Qualified protocol reference uses
Module.Protocol()without introducing a new keyword. - Legacy
onsyntax is not part of the parser surface.
Rules:
- Keywords
MUST NOTbe used asIDENTIFIER. trueandfalseare lexed asBOOLEAN, not identifier names.- Step-call names such as
sep,frac,img,ecp, andphyare not keywords; they are identifiers validated in semantic stages.
2.3 Identifiers
An IDENTIFIER token matches:
[A-Za-z][A-Za-z0-9_]*Constraints:
- The first character
MUSTbe an ASCII letter. - Remaining characters
MAYinclude ASCII letters, digits, and underscore. - A token that matches a keyword in Chapter 2.2
MUSTbe tokenized as keyword/boolean, not asIDENTIFIER.
2.4 Comments
Culsma supports:
- Line comments:
// ...to end-of-line - Block comments:
/* ... */
Rules:
- Comments are ignored by parsing and have no runtime semantics.
- Comment text inside string literals is not treated as comment syntax.
- Block comments are not nestable and terminate at the first matching
*/.
2.5 Whitespace
Whitespace characters include (at minimum):
- Space (
U+0020) - Horizontal tab (
U+0009) - Line feed (
U+000A) - Carriage return (
U+000D)
Rules:
- Whitespace matching the grammar ignore rule
%ignore /\\s+/is ignored outside string literals, except as token separator. - Implementations
MUSTtreat equivalent whitespace forms identically for lexical behavior.
2.6 Tokens
2.6.1 String Literal
A STRING literal:
MUSTuse double quotes (").MAYinclude backslash escapes.MUST NOTcross line boundaries unless represented by escapes.
Executable lexical behavior:
- The lexer accepts any
\\.escape sequence. - The transformer only interprets
\\\"and\\\\; other escapes are preserved as raw text.
2.6.2 Boolean Literal
Boolean literals are:
truefalse
Both are case-sensitive.
2.6.3 Quantity Literal
A QUANTITY literal is a decimal/integer numeric token with an optional unit suffix.
Examples:
1012.55mL95C
Accepted canonical unit suffixes:
ng_per_uL,ug_per_mLms,s,min,h,dayrpm,rcf,xg,HzuL,mL,LmM,uM,nM,Mmg,ug,kg,gnm,um%mW,W,mV,VC,KX
Unit compatibility checks are semantic/typecheck responsibilities.
Compatibility note:
secis accepted as a legacy alias fors.hris accepted as a legacy alias forh.ulis accepted as a legacy alias foruL.mlis accepted as a legacy alias formL.pctis accepted as a legacy alias for%.- Legacy aliases remain valid source text but are not canonical spellings.
Rules:
- A leading
-is not part of theQUANTITYtoken; it is parsed as unary negation in expressions. - Unit suffixes
MUSTnot be immediately followed by[A-Za-z0-9_](prevents partial matches).- Example:
200Cooltokenizes asQUANTITY(200)thenIDENTIFIER(Cool), notQUANTITY(200C).
- Example:
2.6.4 Operators and Delimiters
Recognized operator and delimiter tokens include:
- Comparison:
==,!=,<,<=,>,>= - Arithmetic:
+,-,*,/ - Assignment:
= - Mutation operator:
<< - Grouping and punctuation:
(,),{,},[,],,,; - Qualified protocol separator:
.
Parser token notes:
- Plate region selectors such as
plate96[A1:B2, D1]are tokenized by the executable grammar as a dedicated selector token after the base identifier. - Source-level behavior treats that shape as parser surface, even though the selector internals are later decoded into AST regions by the transformer.
2.6.5 Tokenization Priority
When multiple token patterns could match at a position:
- The lexer
MUSTprefer the longest valid token. trueandfalseMUSTbe tokenized asBOOLEAN.- Multi-character operators
MUSTbe tokenized before their single-character prefixes. - Keyword literals (such as
"protocol") take precedence over the genericIDENTIFIERtoken.
2.6.6 Ignored Tokens
The following are ignored by the grammar (outside string literals):
- Whitespace:
%ignore /\\s+/ - Line comments:
%ignore /\\/\\/[^\n]*/ - Block comments:
%ignore /\\/\\*[\\s\\S]*?\\*\\//s
2.7 Conformance Boundary
Parser implementations and parser tests must conform to these lexical rules; they do not define separate lexical behavior.
If conflicts are found, maintainers MUST reconcile the reference and executable behavior before treating either side as settled.
