Status: Authoritative Specification Version: 2.0.0 Last Updated: 2026-07-15 Related Documents: 03 Grammar · 05 AST Design · 06 Lexer Design · 14 Error Codes
Statements and declarations are parsed using recursive descent because of their clear, keyword-led structure. Expressions are parsed using a Pratt parser to handle operator precedence and associativity.
pub struct Parser<'a> {
tokens: &'a [Token],
pos: usize,
errors: Vec<Diagnostic>,
node_id_counter: u32,
}Methods inside a model can be declared with either build or the deprecated fun keyword:
parse_model_decl():
expect(Model)
name = expect(Identifier)
expect(LeftBrace)
fields = []
methods = []
while not check(RightBrace) and not is_at_end():
skip_newlines()
if check(Make):
fields.push(parse_field_decl())
else if check(Build) or check(Fun):
methods.push(parse_method_decl())
else:
error("Expected field or method declaration")
synchronize()
expect(RightBrace)
return ModelDecl { name, fields, methods }
parse_method_decl():
keyword_token = advance() // consume Build or Fun
keyword = if keyword_token.kind == Build: MethodKeyword::Build else MethodKeyword::Fun
name = expect(Identifier)
expect(LeftParen)
params = parse_parameter_list()
expect(RightParen)
body = parse_block()
return MethodDecl { keyword, name, params, body }
| Operator | LBP | RBP | Associativity |
|---|---|---|---|
or |
10 | 11 | Left |
and |
20 | 21 | Left |
==, !=, is |
30 | 31 | Left |
<, >, <= |
40 | 41 | Left |
.., ..= |
50 | 50 | Non-associative |
+, - |
60 | 61 | Left |
*, /, //, % |
70 | 71 | Left |
** |
81 | 80 | Right |
Unary -, not |
— | 90 | Right |
(), [], . |
100 | — | Postfix |
Panic-mode synchronization skips tokens until a statement boundary or synchronization point (like ;, }, make, build, when) is met, allowing the parser to detect multiple errors.
- Parsing
funMethods: The parser treats thefuntoken exactly like thebuildtoken insidemodeldeclarations. Both map to aMethodDeclAST node. - Strict Extensions: Files with non-
.txsextensions are rejected prior to parsing by the CLI dispatch.
- When
funis parsed:- The AST stores
MethodKeyword::Fun. - The parser registers a compilation note.
- The semantic check phase maps this flag to diagnostic
W0015(warning).
- The AST stores
- The parser itself does not halt on
fun; it executes recovery logic normally.
- Identical Node structure: Using
MethodDeclfor both keywords avoids duplicate parsing branches, simplifying code and minimizing maintenance overhead. - Synchronized Error limits: Aborting after 20 errors prevents cascading loop crashes on severely truncated
.txssource files.
- v2.2: The parser will be expanded to support optional type signatures:
fn parse_parameter(&mut self) -> Result<Parameter, Diagnostic> { let name = self.expect(TokenKind::Identifier)?; let mut param_type = None; if self.match_token(TokenKind::Colon) { param_type = Some(self.parse_type_annotation()?); } // ... }