lib/std/lang/parser.rad 77.8 KiB raw
1
//! Recursive descent parser for the Radiance programming language.
2
@test export mod tests;
3
4
use std::mem;
5
use std::io;
6
use std::fmt;
7
use std::lang::alloc;
8
use std::lang::types;
9
use std::lang::ast;
10
use std::lang::strings;
11
use std::lang::scanner;
12
13
/// Maximum `u32` value.
14
export constant U32_MAX: u32 = 0xFFFFFFFF;
15
/// Minimum `i64` value.
16
export constant I64_MIN: i64 = -0x8000000000000000;
17
/// Largest magnitude representable by a negative `i64`.
18
export constant I64_MIN_MAGNITUDE: u64 = 0x8000000000000000;
19
/// Maximum representable `i64` magnitude.
20
export constant I64_MAX_MAGNITUDE: u64 = 0x7FFFFFFFFFFFFFFF;
21
/// Maximum representable `u64` value.
22
export constant U64_MAX: u64 = 0xFFFFFFFFFFFFFFFF;
23
/// Maximum number of fields in a record.
24
export constant MAX_RECORD_FIELDS: u32 = 32;
25
26
/// Maximum number of parser errors before aborting.
27
constant MAX_ERRORS: u32 = 8;
28
29
/// Parser error type.
30
export union ParseError: Copy {
31
    /// Encountered a token that was not expected in the current context.
32
    UnexpectedToken,
33
}
34
35
/// Represents a parsed name-type-value triple.
36
///
37
/// Used for record field declarations, variable declarations,
38
/// and record field initializations.
39
record NameTypeValue: Copy {
40
    /// The identifier name.
41
    name: *ast::Node,
42
    /// The optional type annotation.
43
    type: ?*ast::Node,
44
    /// The optional initialization value.
45
    value: ?*ast::Node,
46
    /// The optional alignment specifier.
47
    alignment: ?*ast::Node,
48
}
49
50
/// Behavioural differences when parsing record field lists.
51
union RecordFieldMode: Copy {
52
    /// Labeled fields, allows for default values.
53
    Labeled,
54
    /// Unlabeled fields.
55
    Unlabeled,
56
}
57
58
/// Parser context differentiates between regular expressions and
59
/// conditional contexts where `{` begins a block.
60
union Context: Copy {
61
    /// Normal expression context where `{` may start a record literal
62
    /// and `if` may start a conditional expression.
63
    Normal,
64
    /// Pattern context where `{` may start a record literal
65
    /// but `if` is reserved for guards.
66
    Pattern,
67
    /// Conditional context where `{` always begins a block
68
    /// and `if` is reserved for guards.
69
    Condition,
70
}
71
72
/// A single parser error with location information.
73
export record Error: Copy {
74
    /// Human-readable error message.
75
    message: *[u8],
76
    /// The token where the error occurred.
77
    token: scanner::Token,
78
}
79
80
/// List of parser errors encountered during parsing.
81
record ErrorList: Copy {
82
    /// Fixed-size array of error records.
83
    list: [Error; MAX_ERRORS],
84
    /// Number of errors currently in the list.
85
    count: u32,
86
}
87
88
/// Snapshot of parser state for speculative parsing.
89
record SavedState: Copy {
90
    parser: Parser,
91
    arena: u32,
92
    nextId: u32,
93
}
94
95
/// Operator metadata for precedence climbing.
96
record OpInfo: Copy {
97
    op: ast::BinaryOp,
98
    prec: i32,
99
}
100
101
/// Get operator info for a token kind using match-based dispatch.
102
/// Returns nil if the token is not a binary operator.
103
fn getOpInfo(kind: scanner::TokenKind) -> ?OpInfo {
104
    match kind {
105
        case scanner::TokenKind::Star =>
106
            return { op: ast::BinaryOp::Mul, prec: 7 },
107
        case scanner::TokenKind::Slash =>
108
            return { op: ast::BinaryOp::Div, prec: 7 },
109
        case scanner::TokenKind::Percent =>
110
            return { op: ast::BinaryOp::Mod, prec: 7 },
111
        case scanner::TokenKind::Plus =>
112
            return { op: ast::BinaryOp::Add, prec: 6 },
113
        case scanner::TokenKind::Minus =>
114
            return { op: ast::BinaryOp::Sub, prec: 6 },
115
        case scanner::TokenKind::LtLt =>
116
            return { op: ast::BinaryOp::Shl, prec: 5 },
117
        case scanner::TokenKind::GtGt =>
118
            return { op: ast::BinaryOp::Shr, prec: 5 },
119
        case scanner::TokenKind::Amp =>
120
            return { op: ast::BinaryOp::BitAnd, prec: 4 },
121
        case scanner::TokenKind::Caret =>
122
            return { op: ast::BinaryOp::BitXor, prec: 3 },
123
        case scanner::TokenKind::Pipe =>
124
            return { op: ast::BinaryOp::BitOr, prec: 2 },
125
        case scanner::TokenKind::EqualEqual =>
126
            return { op: ast::BinaryOp::Eq, prec: 1 },
127
        case scanner::TokenKind::LtGt =>
128
            return { op: ast::BinaryOp::Ne, prec: 1 },
129
        case scanner::TokenKind::Lt =>
130
            return { op: ast::BinaryOp::Lt, prec: 1 },
131
        case scanner::TokenKind::Gt =>
132
            return { op: ast::BinaryOp::Gt, prec: 1 },
133
        case scanner::TokenKind::LtEqual =>
134
            return { op: ast::BinaryOp::Lte, prec: 1 },
135
        case scanner::TokenKind::GtEqual =>
136
            return { op: ast::BinaryOp::Gte, prec: 1 },
137
        case scanner::TokenKind::And =>
138
            return { op: ast::BinaryOp::And, prec: 0 },
139
        case scanner::TokenKind::Or =>
140
            return { op: ast::BinaryOp::Or, prec: 0 },
141
        else =>
142
            return nil,
143
    }
144
}
145
146
/// Parser state.
147
export record Parser: Copy {
148
    /// The scanner that provides tokens.
149
    scanner: scanner::Scanner,
150
    /// The current token being examined.
151
    current: scanner::Token,
152
    /// The most recently consumed token.
153
    previous: scanner::Token,
154
    /// Collection of errors encountered during parsing.
155
    errors: ErrorList,
156
    /// Arena for all node allocations.
157
    arena: *mut ast::NodeArena,
158
    /// Allocator backed by the node arena.
159
    allocator: alloc::Allocator,
160
    /// Current parsing context (normal or conditional).
161
    context: Context,
162
}
163
164
/// Create a new parser initialized with the given source kind, source and node arena.
165
export fn mkParser(sourceLoc: scanner::SourceLoc, source: *[u8], arena: *mut ast::NodeArena, pool: *mut strings::Pool) -> Parser {
166
    return Parser {
167
        scanner: scanner::scanner(sourceLoc, source, pool),
168
        current: scanner::invalid(0, ""),
169
        previous: scanner::invalid(0, ""),
170
        errors: ErrorList { list: undefined, count: 0 },
171
        arena,
172
        allocator: alloc::arenaAllocator(&mut arena.arena),
173
        context: Context::Normal,
174
    };
175
}
176
177
/// Emit a `true` or `false` literal node.
178
fn nodeBool(p: *mut Parser, value: bool) -> *ast::Node {
179
    return node(p, ast::NodeValue::Bool(value));
180
}
181
182
/// Parse an integer literal while mapping shared errors into parser diagnostics.
183
fn parseIntLiteral(p: *mut Parser, text: *[u8]) -> fmt::IntLiteral
184
    throws (ParseError)
185
{
186
    let literal = try fmt::parseInt(text) catch err {
187
        match err {
188
            case fmt::ParseError::Invalid =>
189
                throw failParsing(p, "invalid integer literal"),
190
            case fmt::ParseError::InvalidDigit =>
191
                throw failParsing(p, "invalid digit in integer literal"),
192
            case fmt::ParseError::Overflow =>
193
                throw failParsing(p, "integer literal overflow"),
194
        }
195
    };
196
    return literal;
197
}
198
199
/// Emit an integer type node.
200
fn nodeTypeInt(p: *mut Parser, width: u8, sign: ast::Signedness) -> *ast::Node {
201
    return node(p, ast::NodeValue::TypeSig(
202
        ast::TypeSig::Integer { width, sign }
203
    ));
204
}
205
206
/// Emit a number literal node with the provided literal metadata.
207
fn nodeNumber(p: *mut Parser, literal: fmt::IntLiteral) -> *ast::Node {
208
    return node(p, ast::NodeValue::Number(literal));
209
}
210
211
/// Emit a `super` node.
212
fn nodeSuper(p: *mut Parser) -> *ast::Node {
213
    return node(p, ast::NodeValue::Super);
214
}
215
216
/// Emit a single attribute node.
217
fn nodeAttribute(p: *mut Parser, attr: ast::Attribute) -> *ast::Node {
218
    return node(p, ast::NodeValue::Attribute(attr));
219
}
220
221
/// Emit a unary operator node.
222
fn nodeUnary(p: *mut Parser, op: ast::UnaryOp, value: *ast::Node) -> *ast::Node {
223
    return node(p, ast::NodeValue::UnOp({ op, value }));
224
}
225
226
/// Parse one expression without inheriting a surrounding condition or pattern context.
227
fn parseNormalExpr(p: *mut Parser) -> *ast::Node throws (ParseError) {
228
    let saved = p.context;
229
    set p.context = Context::Normal;
230
    let expr = try parseExpr(p);
231
    set p.context = saved;
232
    return expr;
233
}
234
235
/// Parse a parenthesized expression without applying postfix operators.
236
fn parseParenthesized(p: *mut Parser) -> *ast::Node
237
    throws (ParseError)
238
{
239
    try expect(p, scanner::TokenKind::LParen, "expected `(`");
240
241
    let expr = try parseNormalExpr(p);
242
243
    try expect(p, scanner::TokenKind::RParen, "expected `)`");
244
245
    return expr;
246
}
247
248
/// Parse an array literal: `[a, b, c]` or `[item; count]`.
249
fn parseArrayLiteral(p: *mut Parser) -> *ast::Node
250
    throws (ParseError)
251
{
252
    try expect(p, scanner::TokenKind::LBracket, "expected `[`");
253
    if consume(p, scanner::TokenKind::RBracket) { // Empty array: `[]`.
254
        let empty: *mut [*ast::Node] = &mut [];
255
        return node(p, ast::NodeValue::ArrayLit(empty));
256
    }
257
    let firstExpr = try parseNormalExpr(p);
258
259
    if consume(p, scanner::TokenKind::Semicolon) {
260
        // Array repeat literal: `[item; count]`.
261
        let count = try parseNormalExpr(p);
262
        try expect(p, scanner::TokenKind::RBracket, "expected `]` after array repeat count");
263
264
        return node(p, ast::NodeValue::ArrayRepeatLit(
265
            ast::ArrayRepeatLit { item: firstExpr, count }
266
        ));
267
    }
268
    // Regular array literal: `[a, b, ...]`.
269
    let mut items = ast::nodeSlice(p.arena, 64).append(firstExpr, p.allocator);
270
271
    while consume(p, scanner::TokenKind::Comma) and not check(p, scanner::TokenKind::RBracket) {
272
        let elem = try parseNormalExpr(p);
273
        items.append(elem, p.allocator);
274
    }
275
    try expect(p, scanner::TokenKind::RBracket, "expected `]` after array elements");
276
277
    return node(p, ast::NodeValue::ArrayLit(items));
278
}
279
280
/// Parse a function call expression.
281
fn parseCall(p: *mut Parser, callee: *ast::Node) -> *ast::Node
282
    throws (ParseError)
283
{
284
    let args = try parseList(
285
        p,
286
        scanner::TokenKind::LParen,
287
        scanner::TokenKind::RParen,
288
        parseNormalExpr
289
    );
290
    return node(p, ast::NodeValue::Call(
291
        ast::Call { callee, args }
292
    ));
293
}
294
295
/// Parse zero or more trailing `as` casts applied to `expr`.
296
fn parseAsCast(p: *mut Parser, expr: *ast::Node) -> *ast::Node
297
    throws (ParseError)
298
{
299
    let mut result = expr;
300
301
    while consume(p, scanner::TokenKind::As) {
302
        let target = try parseType(p);
303
304
        set result = node(p, ast::NodeValue::As(
305
            ast::As { value: result, type: target }
306
        ));
307
    }
308
    return result;
309
}
310
311
/// Parse an optional conditional expression suffix.
312
///
313
///   `<thenExpr> if <condition> else <elseExpr>`
314
///
315
/// If no `if` keyword follows, returns the input expression unchanged.
316
fn parseCondExpr(p: *mut Parser, thenExpr: *ast::Node) -> *ast::Node
317
    throws (ParseError)
318
{
319
    // Only parse conditional expressions in normal context.
320
    // In conditional context, `if` is used for guards.
321
    if p.context <> Context::Normal {
322
        return thenExpr;
323
    }
324
    if not consume(p, scanner::TokenKind::If) {
325
        return thenExpr;
326
    }
327
    let condition = try parseCond(p);
328
    try expect(p, scanner::TokenKind::Else, "expected `else` in conditional expression");
329
    let elseExpr = try parseExpr(p);
330
331
    return node(p, ast::NodeValue::CondExpr(
332
        ast::CondExpr { condition, thenExpr, elseExpr }
333
    ));
334
}
335
336
/// Parse array subscript or slice expression after `[`.
337
fn parseSubscriptOrSlice(p: *mut Parser, container: *ast::Node) -> *ast::Node
338
    throws (ParseError)
339
{
340
    try expect(p, scanner::TokenKind::LBracket, "expected `[`");
341
342
    let mut index: *ast::Node = undefined;
343
344
    if consume(p, scanner::TokenKind::DotDot) {
345
        // Either `..` or `..end`.
346
        let mut endExpr: ?*ast::Node = nil;
347
        if not check(p, scanner::TokenKind::RBracket) {
348
            set endExpr = try parseNormalExpr(p);
349
        }
350
        set index = node(p, ast::NodeValue::Range(
351
            ast::Range { start: nil, end: endExpr }
352
        ));
353
    } else {
354
        // Either `n`, `n..` or `n..end`.
355
        let startExpr = try parseNormalExpr(p);
356
357
        if consume(p, scanner::TokenKind::DotDot) {
358
            // Either `n..` or `n..end`.
359
            let mut endExpr: ?*ast::Node = nil;
360
            if not check(p, scanner::TokenKind::RBracket) {
361
                set endExpr = try parseNormalExpr(p);
362
            }
363
            set index = node(p, ast::NodeValue::Range(
364
                ast::Range { start: startExpr, end: endExpr }
365
            ));
366
        } else {
367
            // Just `n` - regular indexing.
368
            set index = startExpr;
369
        }
370
    }
371
    try expect(p, scanner::TokenKind::RBracket, "expected `]` after array index");
372
373
    return node(p, ast::NodeValue::Subscript { container, index });
374
}
375
376
/// Parse postfix operators (eg. field access, function call etc.)
377
fn parsePostfix(p: *mut Parser, expr: *ast::Node) -> *ast::Node
378
    throws (ParseError)
379
{
380
    let mut result = expr;
381
382
    loop {
383
        match p.current.kind {
384
            case scanner::TokenKind::Dot => {
385
                advance(p);
386
387
                let field = try parseIdent(p, "expected field name after `.`");
388
                set result = node(p, ast::NodeValue::FieldAccess(
389
                    ast::Access { parent: result, child: field }
390
                ));
391
            }
392
            case scanner::TokenKind::ColonColon => {
393
                advance(p);
394
395
                let ident = try parseIdent(p, "expected identifier after `::`");
396
                set result = node(p, ast::NodeValue::ScopeAccess(
397
                    ast::Access { parent: result, child: ident }
398
                ));
399
            }
400
            case scanner::TokenKind::LBracket => {
401
                set result = try parseSubscriptOrSlice(p, result);
402
            }
403
            case scanner::TokenKind::LParen => {
404
                set result = try parseCall(p, result);
405
            }
406
            case scanner::TokenKind::LBrace if p.context <> Context::Condition => {
407
                set result = try parseRecordLit(p, result);
408
            }
409
            else => {
410
                break;
411
            }
412
        }
413
    }
414
    return result;
415
}
416
417
/// Parse a conditional expression.
418
export fn parseCond(p: *mut Parser) -> *ast::Node throws (ParseError) {
419
    let saved = p.context;
420
    set p.context = Context::Condition;
421
    let expr = try parseExpr(p);
422
    set p.context = saved;
423
424
    return expr;
425
}
426
427
/// Parse unary expression followed by optional `as` cast.
428
/// `as` has higher precedence than binary ops but lower than unary.
429
fn parseUnary(p: *mut Parser) -> *ast::Node throws (ParseError) {
430
    let unary = try parseUnaryExpr(p);
431
    return try parseAsCast(p, unary);
432
}
433
434
/// Parse prefix unary expressions and defer to primary expressions otherwise.
435
fn parseUnaryExpr(p: *mut Parser) -> *ast::Node
436
    throws (ParseError)
437
{
438
    match p.current.kind {
439
        case scanner::TokenKind::Not => {
440
            advance(p);
441
            let value = try parseUnaryExpr(p);
442
            return nodeUnary(p, ast::UnaryOp::Not, value);
443
        }
444
        case scanner::TokenKind::Minus => {
445
            advance(p);
446
            let value = try parseUnaryExpr(p);
447
            return nodeUnary(p, ast::UnaryOp::Neg, value);
448
        }
449
        case scanner::TokenKind::Tilde => {
450
            advance(p);
451
            let value = try parseUnaryExpr(p);
452
            return nodeUnary(p, ast::UnaryOp::BitNot, value);
453
        }
454
        case scanner::TokenKind::Star => {
455
            advance(p);
456
            let value = try parseUnaryExpr(p);
457
            return node(p, ast::NodeValue::Deref(value));
458
        }
459
        case scanner::TokenKind::Amp => {
460
            advance(p);
461
            let mutable = consume(p, scanner::TokenKind::Mut);
462
            let target = try parseUnaryExpr(p);
463
            return node(p, ast::NodeValue::AddressOf({ target: target, mutable: mutable }));
464
        }
465
        else => {
466
            return try parsePrimary(p);
467
        }
468
    }
469
}
470
471
/// Find the operator info for a token if it has precedence greater than the
472
/// given minimum.
473
fn findNextOp(kind: scanner::TokenKind, minPrec: i32) -> ?OpInfo {
474
    if let opInfo = getOpInfo(kind) {
475
        if opInfo.prec > minPrec {
476
            return opInfo;
477
        }
478
    }
479
    return nil;
480
}
481
482
/// Determine whether the current token can terminate a range expression.
483
fn isRangeTerminator(kind: scanner::TokenKind) -> bool {
484
    match kind {
485
        case scanner::TokenKind::Comma,
486
             scanner::TokenKind::Semicolon,
487
             scanner::TokenKind::RParen,
488
             scanner::TokenKind::RBrace,
489
             scanner::TokenKind::RBracket,
490
             scanner::TokenKind::Else,
491
             scanner::TokenKind::In,
492
             scanner::TokenKind::LBrace,
493
             scanner::TokenKind::Eof =>
494
            return true,
495
        else =>
496
            return false,
497
    }
498
}
499
500
/// Build a range expression node with an optional start and end expression.
501
fn parseRangeExpr(p: *mut Parser, start: ?*ast::Node) -> *ast::Node
502
    throws (ParseError)
503
{
504
    let mut endExpr: ?*ast::Node = nil;
505
506
    if not isRangeTerminator(p.current.kind) {
507
        let right = try parseUnary(p);
508
        set endExpr = try parseBinary(p, right, -1);
509
    }
510
    return node(p, ast::NodeValue::Range(
511
        ast::Range { start, end: endExpr }
512
    ));
513
}
514
515
/// Parse binary expressions using precedence climbing.
516
fn parseBinary(p: *mut Parser, left: *ast::Node, minPrec: i32) -> *ast::Node
517
    throws (ParseError)
518
{
519
    let mut result = left;
520
521
    loop {
522
        if p.current.kind == scanner::TokenKind::DotDot {
523
            advance(p);
524
            set result = try parseRangeExpr(p, result);
525
        } else {
526
            let opInfo = findNextOp(p.current.kind, minPrec) else break;
527
            advance(p);
528
529
            let mut right = try parseUnary(p);
530
531
            while let _ = findNextOp(p.current.kind, opInfo.prec)  {
532
                set right = try parseBinary(p, right, opInfo.prec);
533
            }
534
            set result = node(p, ast::NodeValue::BinOp(ast::BinOp {
535
                op: opInfo.op, left: result, right,
536
            }));
537
        }
538
    }
539
    return result;
540
}
541
542
/// Check whether an expression may appear on the left side of an assignment.
543
fn isAssignableTarget(node: *ast::Node) -> bool {
544
    match node.value {
545
        case ast::NodeValue::Ident(_) =>
546
            return true,
547
        case ast::NodeValue::FieldAccess(_) =>
548
            return true,
549
        case ast::NodeValue::ScopeAccess(_) =>
550
            return true,
551
        case ast::NodeValue::Subscript { .. } =>
552
            return true,
553
        case ast::NodeValue::Deref(_) =>
554
            return true,
555
        else =>
556
            return false,
557
    }
558
}
559
/// Check if a statement requires a semicolon after it.
560
///
561
/// Statements that end with blocks don't require semicolons.
562
/// All other statements do.
563
fn expectsSemicolon(stmt: *ast::Node) -> bool {
564
    match stmt.value {
565
        case ast::NodeValue::If(_),
566
             ast::NodeValue::IfLet(_),
567
             ast::NodeValue::While(_),
568
             ast::NodeValue::WhileLet(_),
569
             ast::NodeValue::For(_),
570
             ast::NodeValue::Loop { .. },
571
             ast::NodeValue::Match(_),
572
             ast::NodeValue::Block(_),
573
             ast::NodeValue::FnDecl(_),
574
             ast::NodeValue::RecordDecl(_),
575
             ast::NodeValue::UnionDecl(_),
576
             ast::NodeValue::TraitDecl { .. },
577
             ast::NodeValue::InstanceDecl { .. },
578
             ast::NodeValue::MethodDecl { .. } => return false,
579
        else => return true,
580
    }
581
}
582
583
/// Parse a primary leaf expression without postfix operators.
584
fn parseLeaf(p: *mut Parser) -> *ast::Node
585
    throws (ParseError)
586
{
587
    match p.current.kind {
588
        case scanner::TokenKind::True => {
589
            advance(p);
590
            return nodeBool(p, true);
591
        }
592
        case scanner::TokenKind::False => {
593
            advance(p);
594
            return nodeBool(p, false);
595
        }
596
        case scanner::TokenKind::Ident => {
597
            advance(p);
598
            return node(p, ast::NodeValue::Ident(p.previous.source));
599
        }
600
        case scanner::TokenKind::Super => {
601
            advance(p);
602
            return nodeSuper(p);
603
        }
604
        case scanner::TokenKind::Number => {
605
            advance(p);
606
            let literal = try parseIntLiteral(p, p.previous.source);
607
            return nodeNumber(p, literal);
608
        }
609
        case scanner::TokenKind::LParen => {
610
            return try parseParenthesized(p);
611
        }
612
        case scanner::TokenKind::Try => {
613
            return try parseTryExpr(p);
614
        }
615
        case scanner::TokenKind::Nil => {
616
            advance(p);
617
            return node(p, ast::NodeValue::Nil);
618
        }
619
        case scanner::TokenKind::Undefined => {
620
            advance(p);
621
            return node(p, ast::NodeValue::Undef);
622
        }
623
        case scanner::TokenKind::Char => {
624
            advance(p);
625
            let ch = try fmt::parseChar(p.previous.source) catch {
626
                throw failParsing(p, "invalid char literal");
627
            };
628
            return node(p, ast::NodeValue::Char(ch));
629
        }
630
        case scanner::TokenKind::String => {
631
            advance(p);
632
            let src = p.previous.source;
633
            let raw = &src[1..src.len - 1]; // Strip quotes.
634
635
            // Process escape sequences into arena buffer.
636
            let buf = alloc::remainingBuf(&mut p.arena.arena);
637
            let len = fmt::unescapeString(raw, buf);
638
            alloc::commit(&mut p.arena.arena, len);
639
640
            return node(p, ast::NodeValue::String(&buf[..len]));
641
        }
642
        case scanner::TokenKind::Underscore => {
643
            advance(p);
644
            return node(p, ast::NodeValue::Placeholder);
645
        }
646
        case scanner::TokenKind::LBracket => {
647
            return try parseArrayLiteral(p);
648
        }
649
        case scanner::TokenKind::AtIdent => {
650
            return try parseBuiltin(p);
651
        }
652
        case scanner::TokenKind::DotDot => {
653
            advance(p);
654
            return try parseRangeExpr(p, nil);
655
        }
656
        case scanner::TokenKind::LBrace => {
657
            // Anonymous record literal: { x: 1, y: 2 }.
658
            // Only allowed in normal context, not in conditions.
659
            if p.context <> Context::Normal {
660
                throw failParsing(p, "unexpected `{` in this context");
661
            }
662
            return try parseRecordLit(p, nil);
663
        }
664
        else => {
665
            throw failParsing(p, "expected expression");
666
        }
667
    }
668
}
669
670
/// Parse a primary expression (leaf nodes followed by postfix operators).
671
fn parsePrimary(p: *mut Parser) -> *ast::Node
672
    throws (ParseError)
673
{
674
    let leaf = try parseLeaf(p);
675
    return try parsePostfix(p, leaf);
676
}
677
678
/// Parse a builtin function call like `@sizeOf(T)` or `@alignOf(T)`.
679
fn parseBuiltin(p: *mut Parser) -> *ast::Node
680
    throws (ParseError)
681
{
682
    // Skip the '@' to get the name.
683
    let ident = p.current.source;
684
    advance(p);
685
686
    let mut kind: ast::Builtin = undefined;
687
    // TODO: Use `match`.
688
    if ident == "@sizeOf" {
689
        set kind = ast::Builtin::SizeOf;
690
    } else if ident == "@alignOf" {
691
        set kind = ast::Builtin::AlignOf;
692
    } else if ident == "@sliceOf" {
693
        set kind = ast::Builtin::SliceOf;
694
    } else {
695
        throw failParsing(p, "unknown builtin");
696
    }
697
    try expect(p, scanner::TokenKind::LParen, "expected `(` after builtin name");
698
699
    // Parse arguments into a list. Use capacity 4 to handle any valid argument count
700
    // plus some extra for error recovery.
701
    let mut args = ast::nodeSlice(p.arena, 4);
702
703
    if kind == ast::Builtin::SliceOf {
704
        // Parse comma-separated expressions until closing paren.
705
        // Argument count validation is done in semantic analysis.
706
        while not check(p, scanner::TokenKind::RParen) {
707
            args.append(try parseExpr(p), p.allocator);
708
            if not consume(p, scanner::TokenKind::Comma) {
709
                break;
710
            }
711
        }
712
    } else {
713
        args.append(try parseType(p), p.allocator);
714
    }
715
    try expect(p, scanner::TokenKind::RParen, "expected `)` after builtin argument");
716
717
    return node(p, ast::NodeValue::BuiltinCall { kind, args });
718
}
719
720
/// Parse a single expression.
721
///
722
/// Parses unary and binary operators using precedence climbing.
723
/// Conditional expressions (`x if cond else y`) have lowest precedence.
724
export fn parseExpr(p: *mut Parser) -> *ast::Node
725
    throws (ParseError)
726
{
727
    let left = try parseUnary(p);
728
    let expr = try parseBinary(p, left, -1);
729
    return try parseCondExpr(p, expr);
730
}
731
732
/// Try to consume a compound assignment operator and return its binary op.
733
fn tryCompoundAssignOp(p: *mut Parser) -> ?ast::BinaryOp {
734
    match p.current.kind {
735
        case scanner::TokenKind::PlusEqual =>    { advance(p); return ast::BinaryOp::Add; }
736
        case scanner::TokenKind::MinusEqual =>   { advance(p); return ast::BinaryOp::Sub; }
737
        case scanner::TokenKind::StarEqual =>    { advance(p); return ast::BinaryOp::Mul; }
738
        case scanner::TokenKind::SlashEqual =>   { advance(p); return ast::BinaryOp::Div; }
739
        case scanner::TokenKind::PercentEqual => { advance(p); return ast::BinaryOp::Mod; }
740
        case scanner::TokenKind::AmpEqual =>     { advance(p); return ast::BinaryOp::BitAnd; }
741
        case scanner::TokenKind::PipeEqual =>    { advance(p); return ast::BinaryOp::BitOr; }
742
        case scanner::TokenKind::CaretEqual =>   { advance(p); return ast::BinaryOp::BitXor; }
743
        case scanner::TokenKind::LtLtEqual =>    { advance(p); return ast::BinaryOp::Shl; }
744
        case scanner::TokenKind::GtGtEqual =>    { advance(p); return ast::BinaryOp::Shr; }
745
        else => return nil,
746
    }
747
}
748
749
/// Parse an expression statement.
750
export fn parseExprStmt(p: *mut Parser) -> *ast::Node
751
    throws (ParseError)
752
{
753
    let expr = try parseExpr(p);
754
    return node(p, ast::NodeValue::ExprStmt(expr));
755
}
756
757
/// Parse a `set` statement assignment.
758
fn parseSetStmt(p: *mut Parser) -> *ast::Node
759
    throws (ParseError)
760
{
761
    let target = try parseUnary(p);
762
    if not ast::isPlaceExpr(target) {
763
        throw failParsing(p, "invalid assignment target");
764
    }
765
    if consume(p, scanner::TokenKind::Equal) {
766
        let value = try parseExpr(p);
767
        return node(p, ast::NodeValue::Assign(
768
            ast::Assign { left: target, right: value }
769
        ));
770
    }
771
    // Compound assignment: desugar `set x <op>= y` into `set x = x <op> y`.
772
    // The target node is shared with the binary operand.
773
    if let op = tryCompoundAssignOp(p) {
774
        let rhs = try parseExpr(p);
775
        let binop = node(p, ast::NodeValue::BinOp(
776
            ast::BinOp { op, left: target, right: rhs }
777
        ));
778
        return node(p, ast::NodeValue::Assign(
779
            ast::Assign { left: target, right: binop }
780
        ));
781
    }
782
    throw failParsing(p, "expected assignment after `set`");
783
}
784
785
/// Parse leading attributes and declaration modifiers.
786
fn parseAttributes(p: *mut Parser) -> ?ast::Attributes {
787
    let mut attrs = ast::nodeSlice(p.arena, 4);
788
789
    if let attr = tryParseAnnotation(p) {
790
        attrs.append(attr, p.allocator);
791
    }
792
    if consume(p, scanner::TokenKind::Export) {
793
        attrs.append(nodeAttribute(p, ast::Attribute::Export), p.allocator);
794
    }
795
    if consume(p, scanner::TokenKind::Unsafe) {
796
        attrs.append(nodeAttribute(p, ast::Attribute::Unsafe), p.allocator);
797
    }
798
    if attrs.len > 0 {
799
        return ast::Attributes { list: attrs };
800
    }
801
    return nil;
802
}
803
804
/// Try to parse an annotation like `@default`.
805
///
806
/// Returns `nil` if not a known annotation (e.g. `@sizeOf` or `@alignOf` which are builtins).
807
/// Only consumes tokens if a valid annotation is found.
808
fn tryParseAnnotation(p: *mut Parser) -> ?*ast::Node {
809
    if not check(p, scanner::TokenKind::AtIdent) {
810
        return nil;
811
    }
812
    // Token is @identifier, skip the '@' to get the name.
813
    let ident = &p.current.source[..];
814
    if ident == "@default" {
815
        advance(p); // Consume `@default`.
816
        return nodeAttribute(p, ast::Attribute::Default);
817
    }
818
    if ident == "@test" {
819
        advance(p); // Consume `@test`.
820
        return nodeAttribute(p, ast::Attribute::Test);
821
    }
822
    if ident == "@intrinsic" {
823
        advance(p); // Consume `@intrinsic`.
824
        return nodeAttribute(p, ast::Attribute::Intrinsic);
825
    }
826
    return nil;
827
}
828
829
/// Parse a single statement.
830
///
831
/// Dispatches to the appropriate statement parser based on the current token.
832
export fn parseStmt(p: *mut Parser) -> *ast::Node
833
    throws (ParseError)
834
{
835
    // TODO: Why is `parseStmt` checking for attributes?
836
    // We should have a `parseDecl` which is top-level, and `parseStmt` which
837
    // is inside functions.
838
    let attrs = parseAttributes(p);
839
    if let list = attrs {
840
        if ast::attributesContains(&list, ast::Attribute::Unsafe)
841
            and p.current.kind <> scanner::TokenKind::Fn
842
            and p.current.kind <> scanner::TokenKind::Mod
843
        {
844
            throw failParsing(p, "`unsafe` is only allowed on functions and modules");
845
        }
846
        let allowed: bool =
847
            p.current.kind == scanner::TokenKind::Fn or
848
            p.current.kind == scanner::TokenKind::Union or
849
            p.current.kind == scanner::TokenKind::Record or
850
            p.current.kind == scanner::TokenKind::Mod or
851
            p.current.kind == scanner::TokenKind::Static or
852
            p.current.kind == scanner::TokenKind::Constant or
853
            p.current.kind == scanner::TokenKind::Use or
854
            p.current.kind == scanner::TokenKind::Trait;
855
856
        if not allowed {
857
            throw failParsing(p, "attributes are not allowed in this context");
858
        }
859
    }
860
861
    match p.current.kind {
862
        case scanner::TokenKind::If => {
863
            return try parseIf(p);
864
        }
865
        case scanner::TokenKind::LBrace => {
866
            return try parseBlock(p);
867
        }
868
        case scanner::TokenKind::While => {
869
            return try parseWhile(p);
870
        }
871
        case scanner::TokenKind::Loop => {
872
            return try parseLoop(p);
873
        }
874
        case scanner::TokenKind::For => {
875
            return try parseFor(p);
876
        }
877
        case scanner::TokenKind::Return => {
878
            return try parseReturn(p);
879
        }
880
        case scanner::TokenKind::Throw => {
881
            return try parseThrow(p);
882
        }
883
        case scanner::TokenKind::Panic => {
884
            return try parsePanic(p);
885
        }
886
        case scanner::TokenKind::Assert => {
887
            return try parseAssert(p);
888
        }
889
        case scanner::TokenKind::Break => {
890
            advance(p);
891
            return node(p, ast::NodeValue::Break);
892
        }
893
        case scanner::TokenKind::Continue => {
894
            advance(p);
895
            return node(p, ast::NodeValue::Continue);
896
        }
897
        case scanner::TokenKind::Match => {
898
            return try parseMatch(p);
899
        }
900
        case scanner::TokenKind::Let => {
901
            advance(p);
902
            if consume(p, scanner::TokenKind::Case) {
903
                return try parseLetCase(p);
904
            }
905
            if consume(p, scanner::TokenKind::Mut) {
906
                return try parseLet(p, true);
907
            }
908
            return try parseLet(p, false);
909
        }
910
        case scanner::TokenKind::Set => {
911
            advance(p);
912
            return try parseSetStmt(p);
913
        }
914
        case scanner::TokenKind::Constant => {
915
            return try parseConst(p, attrs);
916
        }
917
        case scanner::TokenKind::Static => {
918
            return try parseStatic(p, attrs);
919
        }
920
        case scanner::TokenKind::Fn => {
921
            return try parseFnDecl(p, attrs);
922
        }
923
        case scanner::TokenKind::Union => {
924
            return try parseUnionDecl(p, attrs);
925
        }
926
        case scanner::TokenKind::Record => {
927
            return try parseRecordDecl(p, attrs);
928
        }
929
        case scanner::TokenKind::Use => {
930
            return try parseUse(p, attrs);
931
        }
932
        case scanner::TokenKind::Mod => {
933
            return try parseMod(p, attrs);
934
        }
935
        case scanner::TokenKind::Trait => {
936
            return try parseTraitDecl(p, attrs);
937
        }
938
        case scanner::TokenKind::Instance => {
939
            return try parseInstanceDecl(p);
940
        }
941
        else => {
942
            return try parseExprStmt(p);
943
        }
944
    }
945
}
946
947
/// Parse statements until the specified ending token is encountered.
948
///
949
/// Adds each parsed statement to the given block's statement list.
950
export fn parseStmtsUntil(p: *mut Parser, end: scanner::TokenKind, blk: *mut ast::Block)
951
    throws (ParseError)
952
{
953
    while not check(p, end) {
954
        let stmt = try parseStmt(p);
955
        blk.statements.append(stmt, p.allocator);
956
957
        if check(p, end) or check(p, scanner::TokenKind::Eof) {
958
            break;
959
        }
960
        if not consume(p, scanner::TokenKind::Semicolon) {
961
            // Only require semicolon if the statement needs one.
962
            if expectsSemicolon(stmt) {
963
                throw failParsing(p, "expected `;` after statement");
964
            }
965
        }
966
    }
967
}
968
969
/// Parse a block of statements enclosed in curly braces.
970
export fn parseBlock(p: *mut Parser) -> *ast::Node
971
    throws (ParseError)
972
{
973
    let start = p.current;
974
    let mut blk = mkBlock(p, 64);
975
976
    if not consume(p, scanner::TokenKind::LBrace) {
977
        throw failParsing(p, "expected `{`");
978
    }
979
    try parseStmtsUntil(p, scanner::TokenKind::RBrace, &mut blk);
980
    try expect(p, scanner::TokenKind::RBrace, "expected `}`");
981
982
    return node(p, ast::NodeValue::Block(blk));
983
}
984
985
/// Create an empty block with no statements.
986
fn mkBlock(p: *mut Parser, cap: u32) -> ast::Block {
987
    return ast::Block { statements: ast::nodeSlice(p.arena, cap) };
988
}
989
990
/// Create a block containing a single statement node.
991
fn mkBlockWith(p: *mut Parser, node: *ast::Node) -> ast::Block {
992
    let stmts = ast::nodeSlice(p.arena, 1).append(node, p.allocator);
993
    return ast::Block { statements: stmts };
994
}
995
996
/// Parse the branch that follows `else` in let-else style constructs.
997
///
998
/// Allows either a block, a single statement like `return`,
999
/// or a standalone expression which is returned directly.
1000
fn parseLetElseBranch(p: *mut Parser) -> *ast::Node
1001
    throws (ParseError)
1002
{
1003
    if check(p, scanner::TokenKind::LBrace) {
1004
        return try parseBlock(p);
1005
    }
1006
    let branch = try parseStmt(p);
1007
1008
    if let case ast::NodeValue::ExprStmt(expr) = branch.value {
1009
        return expr;
1010
    }
1011
    return branch;
1012
}
1013
1014
/// Allocate a new node from the parser's arena.
1015
fn node(p: *mut Parser, value: ast::NodeValue) -> *mut ast::Node {
1016
    let span = ast::Span {
1017
        offset: p.previous.offset,
1018
        length: p.previous.source.len,
1019
    };
1020
    let n = ast::allocNode(p.arena, span, value);
1021
    finishSpan(p, n);
1022
1023
    return n;
1024
}
1025
1026
/// Update the span of `node` using the most recently consumed token.
1027
fn finishSpan(p: *mut Parser, node: *mut ast::Node) {
1028
    let start: u32 = node.span.offset;
1029
    let mut end: u32 = p.previous.offset + p.previous.source.len;
1030
1031
    if end >= start {
1032
        set node.span.length = end - start;
1033
    } else {
1034
        set node.span.length = 0;
1035
    }
1036
}
1037
1038
/// Save parser state for speculative parsing.
1039
fn saveState(p: *Parser) -> SavedState {
1040
    return SavedState {
1041
        parser: *p,
1042
        arena: alloc::save(&p.arena.arena),
1043
        nextId: p.arena.nextId,
1044
    };
1045
}
1046
1047
/// Restore parser state from a snapshot, fully undoing any
1048
/// side effects of a failed speculative parse.
1049
fn restoreState(p: *mut Parser, s: *SavedState) {
1050
    set *p = s.parser;
1051
    alloc::restore(&mut p.arena.arena, s.arena);
1052
    set p.arena.nextId = s.nextId;
1053
}
1054
1055
/// Report a parser error.
1056
fn reportError(p: *mut Parser, token: scanner::Token, message: *[u8]) {
1057
    assert message.len > 0;
1058
1059
    // Ignore errors once the error list is full.
1060
    if p.errors.count < p.errors.list.len {
1061
        set p.errors.list[p.errors.count] = Error { message, token };
1062
        set p.errors.count += 1;
1063
    }
1064
}
1065
1066
/// Fail the parsing process with the given error.
1067
fn failParsing(p: *mut Parser, err: *[u8]) -> ParseError {
1068
    reportError(p, p.current, err);
1069
    return ParseError::UnexpectedToken;
1070
}
1071
1072
/// Print all errors that have been collected during parsing.
1073
export fn printErrors(p: *Parser) {
1074
    for i in 0..p.errors.count {
1075
        let e = p.errors.list[i];
1076
        if let loc = scanner::getLocation(
1077
            p.scanner.sourceLoc, p.scanner.source, e.token.offset
1078
        ) {
1079
            if let case scanner::SourceLoc::File(path) = loc.source {
1080
                io::print(path);
1081
                io::print(":");
1082
            }
1083
            io::printU32(loc.line as u32);
1084
            io::print(":");
1085
            io::printU32(loc.col as u32);
1086
            io::print(": error: ");
1087
        } else {
1088
            io::print("error: ");
1089
        }
1090
        io::print(e.message);
1091
        if e.token.kind == scanner::TokenKind::Invalid {
1092
            io::print(": ");
1093
            io::print(e.token.source);
1094
        } else {
1095
            io::print(", got `");
1096
            io::print(e.token.source);
1097
            io::print("`");
1098
        }
1099
        io::print("\n");
1100
    }
1101
}
1102
1103
/// Check whether the current token matches the expected kind.
1104
export fn check(p: *Parser, kind: scanner::TokenKind) -> bool {
1105
    return p.current.kind == kind;
1106
}
1107
1108
/// Advance the parser by one token.
1109
export fn advance(p: *mut Parser) {
1110
    set p.previous = p.current;
1111
    set p.current = scanner::next(&mut p.scanner);
1112
}
1113
1114
/// Parse an `if let` pattern matching statement.
1115
///
1116
/// Syntax: `if let binding = scrutinee { ... }`
1117
/// Syntax: `if let mut binding = scrutinee { ... }`
1118
fn parseIfLet(p: *mut Parser) -> *ast::Node throws (ParseError) {
1119
    try expect(p, scanner::TokenKind::Let, "expected `let`");
1120
1121
    // Parse pattern: either `case <pattern>`, `mut <ident>`, or simple `<ident>`.
1122
    let mut pattern: *ast::Node = undefined;
1123
    let mut kind = ast::PatternKind::Binding;
1124
    let mut mutable = false;
1125
1126
    if consume(p, scanner::TokenKind::Case) {
1127
        set pattern = try parseMatchPattern(p);
1128
        set kind = ast::PatternKind::Case;
1129
    } else {
1130
        set mutable = consume(p, scanner::TokenKind::Mut);
1131
        set pattern = try parseIdentOrPlaceholder(p, "expected `case`, `mut`, or identifier after `let`");
1132
    }
1133
    try expect(p, scanner::TokenKind::Equal, "expected `=` after pattern");
1134
1135
    let scrutinee = try parseCond(p);
1136
    let mut guard: ?*ast::Node = nil;
1137
1138
    if consume(p, scanner::TokenKind::Semicolon) {
1139
        set guard = try parseCond(p);
1140
    }
1141
    let thenBranch = try parseBlock(p);
1142
    let mut elseBranch: ?*ast::Node = nil;
1143
1144
    if consume(p, scanner::TokenKind::Else) {
1145
        if check(p, scanner::TokenKind::If) {
1146
            set elseBranch = node(p, ast::NodeValue::Block(
1147
                mkBlockWith(p, try parseIf(p))
1148
            ));
1149
        } else {
1150
            set elseBranch = try parseBlock(p);
1151
        }
1152
    }
1153
1154
    return node(p, ast::NodeValue::IfLet(ast::IfLet {
1155
        pattern: ast::PatternMatch { pattern, scrutinee, guard, kind, mutable },
1156
        thenBranch,
1157
        elseBranch,
1158
    }));
1159
}
1160
1161
/// Parse a `while let` statement.
1162
fn parseWhileLet(p: *mut Parser) -> *ast::Node
1163
    throws (ParseError)
1164
{
1165
    try expect(p, scanner::TokenKind::Let, "expected `let`");
1166
1167
    // Parse pattern: either `case <pattern>`, `mut <ident>`, or simple `<ident>`.
1168
    let mut pattern: *ast::Node = undefined;
1169
    let mut kind = ast::PatternKind::Binding;
1170
    let mut mutable = false;
1171
    if consume(p, scanner::TokenKind::Case) {
1172
        set pattern = try parseMatchPattern(p);
1173
        set kind = ast::PatternKind::Case;
1174
    } else {
1175
        set mutable = consume(p, scanner::TokenKind::Mut);
1176
        set pattern = try parseIdentOrPlaceholder(p, "expected `case`, `mut`, or identifier after `let`");
1177
    }
1178
    try expect(p, scanner::TokenKind::Equal, "expected `=` after pattern");
1179
1180
    let scrutinee = try parseCond(p);
1181
    let mut guard: ?*ast::Node = nil;
1182
1183
    if consume(p, scanner::TokenKind::Semicolon) {
1184
        set guard = try parseCond(p);
1185
    }
1186
    let body = try parseBlock(p);
1187
    let mut elseBranch: ?*ast::Node = nil;
1188
1189
    if consume(p, scanner::TokenKind::Else) {
1190
        set elseBranch = try parseBlock(p);
1191
    }
1192
    return node(p, ast::NodeValue::WhileLet(ast::WhileLet {
1193
        pattern: ast::PatternMatch { pattern, scrutinee, guard, kind, mutable },
1194
        body,
1195
        elseBranch,
1196
    }));
1197
}
1198
1199
/// Parse a `while` statement.
1200
fn parseWhile(p: *mut Parser) -> *ast::Node
1201
    throws (ParseError)
1202
{
1203
    try expect(p, scanner::TokenKind::While, "expected `while`");
1204
1205
    // Check for `while let` or `while let case` syntax.
1206
    if check(p, scanner::TokenKind::Let) {
1207
        return try parseWhileLet(p);
1208
    }
1209
    let condition = try parseCond(p);
1210
    let body = try parseBlock(p);
1211
    let mut elseBranch: ?*ast::Node = nil;
1212
1213
    if consume(p, scanner::TokenKind::Else) {
1214
        set elseBranch = try parseBlock(p);
1215
    }
1216
    return node(p, ast::NodeValue::While(ast::While {
1217
        condition, body, elseBranch,
1218
    }));
1219
}
1220
1221
/// Parse a `loop` statement.
1222
fn parseLoop(p: *mut Parser) -> *ast::Node
1223
    throws (ParseError)
1224
{
1225
    try expect(p, scanner::TokenKind::Loop, "expected `loop`");
1226
    let body = try parseBlock(p);
1227
1228
    return node(p, ast::NodeValue::Loop { body });
1229
}
1230
1231
/// Parse a `for` statement.
1232
fn parseFor(p: *mut Parser) -> *ast::Node
1233
    throws (ParseError)
1234
{
1235
    try expect(p, scanner::TokenKind::For, "expected `for`");
1236
1237
    let binding = try parseIdentOrPlaceholder(p, "expected identifier or `_`");
1238
    let mut index: ?*ast::Node = nil;
1239
1240
    if consume(p, scanner::TokenKind::Comma) {
1241
        set index = try parseIdentOrPlaceholder(p, "expected index identifier or `_` after `,`");
1242
    }
1243
    try expect(p, scanner::TokenKind::In, "expected `in`");
1244
1245
    let iterable = try parseCond(p);
1246
    let body = try parseBlock(p);
1247
    let mut elseBranch: ?*ast::Node = nil;
1248
1249
    if consume(p, scanner::TokenKind::Else) {
1250
        set elseBranch = try parseBlock(p);
1251
    }
1252
    return node(p, ast::NodeValue::For(ast::For {
1253
        binding, index, iterable, body, elseBranch,
1254
    }));
1255
}
1256
1257
/// Parse a `return` statement.
1258
fn parseReturn(p: *mut Parser) -> *ast::Node
1259
    throws (ParseError)
1260
{
1261
    try expect(p, scanner::TokenKind::Return, "expected `return`");
1262
1263
    // Speculatively try to parse a return value expression.
1264
    let saved = saveState(p);
1265
    let value: ?*ast::Node = try? parseExpr(p);
1266
    if value == nil {
1267
        restoreState(p, &saved);
1268
    }
1269
    return node(p, ast::NodeValue::Return { value });
1270
}
1271
1272
/// Parse a `throw` statement.
1273
fn parseThrow(p: *mut Parser) -> *ast::Node
1274
    throws (ParseError)
1275
{
1276
    try expect(p, scanner::TokenKind::Throw, "expected `throw`");
1277
    let expr = try parseExpr(p);
1278
1279
    return node(p, ast::NodeValue::Throw { expr });
1280
}
1281
1282
/// Parse a `panic` statement.
1283
fn parsePanic(p: *mut Parser) -> *ast::Node
1284
    throws (ParseError)
1285
{
1286
    try expect(p, scanner::TokenKind::Panic, "expected `panic`");
1287
1288
    // `panic { expr }`.
1289
    if consume(p, scanner::TokenKind::LBrace) {
1290
        let message: ?*ast::Node = try parseExpr(p);
1291
        try expect(p, scanner::TokenKind::RBrace, "expected closing `}` after expression");
1292
        return node(p, ast::NodeValue::Panic { message });
1293
    }
1294
    // `panic` or `panic "message"`.
1295
    let saved = saveState(p);
1296
    let message: ?*ast::Node = try? parseExpr(p);
1297
    if message == nil {
1298
        restoreState(p, &saved);
1299
    }
1300
    return node(p, ast::NodeValue::Panic { message });
1301
}
1302
1303
/// Parse an `assert` statement.
1304
///
1305
/// Forms:
1306
///   `assert <expr>`
1307
///   `assert <expr>, "message"`
1308
///   `assert { <expr> }, "message"`
1309
fn parseAssert(p: *mut Parser) -> *ast::Node
1310
    throws (ParseError)
1311
{
1312
    try expect(p, scanner::TokenKind::Assert, "expected `assert`");
1313
1314
    // `assert { expr }` block form or `assert <expr>`.
1315
    let mut condition: *ast::Node = undefined;
1316
    if consume(p, scanner::TokenKind::LBrace) {
1317
        set condition = try parseExpr(p);
1318
        try expect(p, scanner::TokenKind::RBrace, "expected closing `}` after expression");
1319
    } else {
1320
        set condition = try parseExpr(p);
1321
    }
1322
    let mut message: ?*ast::Node = nil;
1323
    if consume(p, scanner::TokenKind::Comma) {
1324
        set message = try parseExpr(p);
1325
    }
1326
    return node(p, ast::NodeValue::Assert { condition, message });
1327
}
1328
1329
/// Parse a `try` expression with optional `catch` clause(s).
1330
fn parseTryExpr(p: *mut Parser) -> *ast::Node
1331
    throws (ParseError)
1332
{
1333
    try expect(p, scanner::TokenKind::Try, "expected `try`");
1334
1335
    let shouldPanic = consume(p, scanner::TokenKind::Bang);
1336
    let returnsOptional = consume(p, scanner::TokenKind::Question);
1337
    let expr = try parseUnaryExpr(p);
1338
    let mut catches = ast::nodeSlice(p.arena, 4);
1339
1340
    while consume(p, scanner::TokenKind::Catch) {
1341
        let mut binding: ?*ast::Node = nil;
1342
        let mut typeNode: ?*ast::Node = nil;
1343
1344
        // Check for optional error binding: `catch ident { ... }` or
1345
        // `catch ident as Type { ... }`.
1346
        if check(p, scanner::TokenKind::Ident) {
1347
            set binding = try parseIdent(p, "expected identifier after `catch`");
1348
            if consume(p, scanner::TokenKind::As) {
1349
                set typeNode = try parseType(p);
1350
            }
1351
        }
1352
        if not check(p, scanner::TokenKind::LBrace) {
1353
            throw failParsing(p, "expected `{` after `catch`");
1354
        }
1355
        let body = try parseBlock(p);
1356
        let clause = node(p, ast::NodeValue::CatchClause(
1357
            ast::CatchClause { binding, typeNode, body }
1358
        ));
1359
        catches.append(clause, p.allocator);
1360
    }
1361
    return node(p, ast::NodeValue::Try(
1362
        ast::Try { expr, catches, shouldPanic, returnsOptional }
1363
    ));
1364
}
1365
1366
/// Parse an `if` expression, with optional `else` or `else if` clauses.
1367
///
1368
/// The `else if` construct is handled by creating a recursive structure:
1369
/// 1. When an `else` is followed by an `if`, we create a new block node.
1370
/// 2. We parse the nested `if` statement recursively using `parseIf`.
1371
/// 3. We put this nested `if` statement inside the block node.
1372
/// 4. This block node becomes the `elseBranch` of the parent `if`.
1373
///
1374
/// This approach naturally handles multiple `else if` chains through recursion.
1375
///
1376
/// For example:
1377
///   if x {
1378
///       a
1379
///   } else if y {
1380
///       b
1381
///   } else if z {
1382
///       c
1383
///   } else {
1384
///       d
1385
///   }
1386
///
1387
/// Is represented as a nested structure like:
1388
///
1389
///   if x {
1390
///       a
1391
///   } else {
1392
///       if y {
1393
///           b
1394
///       } else {
1395
///           if z {
1396
///               c
1397
///           } else {
1398
///               d
1399
///           }
1400
///       }
1401
///   }
1402
///
1403
fn parseIf(p: *mut Parser) -> *ast::Node throws (ParseError) {
1404
    try expect(p, scanner::TokenKind::If, "expected `if`");
1405
1406
    // Check for `if let` or `if let case` syntax.
1407
    if check(p, scanner::TokenKind::Let) {
1408
        return try parseIfLet(p);
1409
    }
1410
    // Regular if statement.
1411
    let cond = try parseCond(p);
1412
    let thenBranch = try parseBlock(p);
1413
    let mut elseBranch: ?*ast::Node = nil;
1414
1415
    if consume(p, scanner::TokenKind::Else) {
1416
        // Check for `else if` construct.
1417
        if check(p, scanner::TokenKind::If) {
1418
            // Set the else branch to a block containing the nested if.
1419
            set elseBranch = node(p, ast::NodeValue::Block(
1420
                mkBlockWith(p, try parseIf(p))
1421
            ));
1422
        } else {
1423
            // Regular else clause.
1424
            set elseBranch = try parseBlock(p);
1425
        }
1426
    }
1427
    return node(p, ast::NodeValue::If(ast::If {
1428
        condition: cond, thenBranch, elseBranch,
1429
    }));
1430
}
1431
1432
/// Parse a `match` statement.
1433
fn parseMatch(p: *mut Parser) -> *ast::Node
1434
    throws (ParseError)
1435
{
1436
    try expect(p, scanner::TokenKind::Match, "expected `match`");
1437
1438
    let subject = try parseCond(p);
1439
    try expect(p, scanner::TokenKind::LBrace, "expected `{` before match prongs");
1440
1441
    let mut prongs = ast::nodeSlice(p.arena, 128);
1442
    while not check(p, scanner::TokenKind::RBrace) and
1443
          not check(p, scanner::TokenKind::Eof) // TODO: We shouldn't have to manually check for EOF.
1444
    {
1445
        let prongNode = try parseMatchProng(p);
1446
        prongs.append(prongNode, p.allocator);
1447
        consume(p, scanner::TokenKind::Comma);
1448
    }
1449
    try expect(p, scanner::TokenKind::RBrace, "expected `}` after match prongs");
1450
1451
    return node(p, ast::NodeValue::Match(
1452
        ast::Match { subject, prongs }
1453
    ));
1454
}
1455
1456
/// Parse a single `match` prong.
1457
fn parseMatchProng(p: *mut Parser) -> *ast::Node
1458
    throws (ParseError)
1459
{
1460
    let mut guard: ?*ast::Node = nil;
1461
1462
    // Case prong: `case <pattern>, ... if <guard> => <body>`.
1463
    if consume(p, scanner::TokenKind::Case) {
1464
        let mut patterns = ast::nodeSlice(p.arena, 16);
1465
        loop {
1466
            let pattern = try parseMatchPattern(p);
1467
            patterns.append(pattern, p.allocator);
1468
1469
            if not consume(p, scanner::TokenKind::Comma) {
1470
                break;
1471
            }
1472
            // After a comma, check for tokens that start a new prong.
1473
            // This catches mistakes like `case A, case B`.
1474
            if check(p, scanner::TokenKind::Case) or check(p, scanner::TokenKind::Else) {
1475
                throw failParsing(p, "unexpected keyword after `,` in case pattern list");
1476
            }
1477
        }
1478
        if consume(p, scanner::TokenKind::If) {
1479
            set guard = try parseCond(p);
1480
        }
1481
        try expect(p, scanner::TokenKind::FatArrow, "expected `=>` after case pattern");
1482
        let body = try parseStmt(p);
1483
1484
        return node(p, ast::NodeValue::MatchProng(
1485
            ast::MatchProng { arm: ast::ProngArm::Case(patterns), guard, body }
1486
        ));
1487
    }
1488
    // Else prong: `else if <guard> => <body>`.
1489
    if consume(p, scanner::TokenKind::Else) {
1490
        if consume(p, scanner::TokenKind::If) {
1491
            set guard = try parseCond(p);
1492
        }
1493
        try expect(p, scanner::TokenKind::FatArrow, "expected `=>` after else");
1494
        let body = try parseStmt(p);
1495
1496
        return node(p, ast::NodeValue::MatchProng(
1497
            ast::MatchProng { arm: ast::ProngArm::Else, guard, body }
1498
        ));
1499
    }
1500
    // Binding prong: `<ident> if <guard> => <body>` or `_ if <guard> => <body>`.
1501
    let binding = try parseIdentOrPlaceholder(p, "expected `case`, `else`, or identifier");
1502
1503
    if consume(p, scanner::TokenKind::If) {
1504
        set guard = try parseCond(p);
1505
    }
1506
    try expect(p, scanner::TokenKind::FatArrow, "expected `=>` after binding");
1507
    let body = try parseStmt(p);
1508
1509
    return node(p, ast::NodeValue::MatchProng(
1510
        ast::MatchProng { arm: ast::ProngArm::Binding(binding), guard, body }
1511
    ));
1512
}
1513
1514
/// Parse a pattern expression used by `case` constructs.
1515
/// Uses `Pattern` context to allow record literals but not conditional expressions.
1516
fn parseMatchPattern(p: *mut Parser) -> *ast::Node
1517
    throws (ParseError)
1518
{
1519
    let saved = p.context;
1520
    set p.context = Context::Pattern;
1521
    let pattern = try parseExpr(p);
1522
    set p.context = saved;
1523
1524
    return pattern;
1525
}
1526
1527
/// Parse an identifier.
1528
fn parseIdent(p: *mut Parser, err: *[u8]) -> *ast::Node
1529
    throws (ParseError)
1530
{
1531
    let source = try expect(p, scanner::TokenKind::Ident, err);
1532
    return node(p, ast::NodeValue::Ident(source));
1533
}
1534
1535
/// Parse either an identifier or a placeholder (`_`).
1536
fn parseIdentOrPlaceholder(p: *mut Parser, err: *[u8]) -> *ast::Node
1537
    throws (ParseError)
1538
{
1539
    if consume(p, scanner::TokenKind::Underscore) {
1540
        return node(p, ast::NodeValue::Placeholder);
1541
    }
1542
    return try parseIdent(p, err);
1543
}
1544
1545
/// Parse an alignment specifier.
1546
///
1547
/// Syntax: `align(N)` where N is a power of 2.
1548
fn parseAlign(p: *mut Parser) -> *ast::Node
1549
    throws (ParseError)
1550
{
1551
    try expect(p, scanner::TokenKind::Align, "expected `align`");
1552
    let value = try parseParenthesized(p);
1553
    return node(p, ast::NodeValue::Align { value });
1554
}
1555
1556
/// Parse a comma-separated list of record fields.
1557
/// The opening delimiter should already be consumed.
1558
/// For labeled fields: `{ name: T, ... }`.
1559
/// For unlabeled fields: `(T, T, ...)`.
1560
fn parseRecordFields(
1561
    p: *mut Parser,
1562
    mode: RecordFieldMode
1563
) -> *mut [*ast::Node]
1564
    throws (ParseError)
1565
{
1566
    let terminator = scanner::TokenKind::RBrace if mode == RecordFieldMode::Labeled
1567
        else scanner::TokenKind::RParen;
1568
    let mut fields = ast::nodeSlice(p.arena, MAX_RECORD_FIELDS);
1569
    while not check(p, terminator) {
1570
        let mut recordField: ast::NodeValue = undefined;
1571
        match mode {
1572
            case RecordFieldMode::Labeled => {
1573
                // Allow optional `let` keyword before field name.
1574
                consume(p, scanner::TokenKind::Let);
1575
1576
                let field = try parseNameTypeValue(p);
1577
                let type = field.type else {
1578
                    throw failParsing(p, "expected type annotation in record field");
1579
                };
1580
                if field.alignment <> nil {
1581
                    throw failParsing(p, "record fields cannot specify alignment");
1582
                }
1583
                if field.value <> nil and mode <> RecordFieldMode::Labeled {
1584
                    throw failParsing(p, "record fields cannot have initializers");
1585
                }
1586
                set recordField = ast::NodeValue::RecordField {
1587
                    field: field.name, type, value: field.value,
1588
                };
1589
            }
1590
            case RecordFieldMode::Unlabeled => {
1591
                let type = try parseType(p);
1592
                set recordField = ast::NodeValue::RecordField {
1593
                    field: nil, type, value: nil,
1594
                };
1595
            }
1596
        }
1597
        fields.append(node(p, recordField), p.allocator);
1598
1599
        if not consume(p, scanner::TokenKind::Comma) {
1600
            break;
1601
        }
1602
    }
1603
    try expect(p, terminator, "expected closing delimiter after record fields");
1604
1605
    return fields;
1606
}
1607
1608
/// Parse an optional derives list (`: Trait + Trait`).
1609
fn parseDerives(p: *mut Parser) -> *mut [*ast::Node] throws (ParseError) {
1610
    let mut derives = ast::nodeSlice(p.arena, 4);
1611
1612
    if not consume(p, scanner::TokenKind::Colon) {
1613
        return derives;
1614
    }
1615
    loop {
1616
        let t = try parseIdent(p, "expected trait name in derive list");
1617
        derives.append(t, p.allocator);
1618
1619
        if not consume(p, scanner::TokenKind::Plus) {
1620
            break;
1621
        }
1622
    }
1623
    return derives;
1624
}
1625
1626
/// Parse a single record literal field.
1627
/// Can be either labeled, or shorthand.
1628
fn parseRecordLitField(p: *mut Parser) -> *ast::Node
1629
    throws (ParseError)
1630
{
1631
    let name = try parseIdent(p, "expected field name");
1632
    if consume(p, scanner::TokenKind::Colon) {
1633
        // Labeled field: `name: value`.
1634
        let value = try parseExpr(p);
1635
        return node(p, ast::NodeValue::RecordLitField(
1636
            ast::Arg { label: name, value }
1637
        ));
1638
    }
1639
    // Shorthand syntax: `{ x }` is equivalent to `{ x: x }`.
1640
    return node(p, ast::NodeValue::RecordLitField(
1641
        ast::Arg { label: name, value: name }
1642
    ));
1643
}
1644
1645
/// Parse a record literal body.
1646
/// Eg. `{ x: 1, y: 2 }`
1647
/// Eg. `{ x: 1, .. }`
1648
fn parseRecordLit(p: *mut Parser, typeName: ?*ast::Node) -> *ast::Node
1649
    throws (ParseError)
1650
{
1651
    let mut fields = ast::nodeSlice(p.arena, MAX_RECORD_FIELDS);
1652
    let mut ignoreRest = false;
1653
    try expect(p, scanner::TokenKind::LBrace, "expected `{` to begin record literal");
1654
1655
    while not check(p, scanner::TokenKind::RBrace) {
1656
        // Check for `..` to ignore remaining fields.
1657
        if consume(p, scanner::TokenKind::DotDot) {
1658
            set ignoreRest = true;
1659
            break;
1660
        }
1661
        let field = try parseRecordLitField(p);
1662
        fields.append(field, p.allocator);
1663
1664
        if not consume(p, scanner::TokenKind::Comma) {
1665
            break;
1666
        }
1667
    }
1668
    try expect(p, scanner::TokenKind::RBrace, "expected `}` to end record literal");
1669
1670
    return node(p, ast::NodeValue::RecordLit(
1671
        ast::RecordLit { typeName, fields, ignoreRest }
1672
    ));
1673
}
1674
1675
/// Parse a named record declaration.
1676
/// `record Point { x: i32, y: i32 }`, or `record Pair(i32, i32);`
1677
fn parseRecordDecl(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
1678
    throws (ParseError)
1679
{
1680
    try expect(p, scanner::TokenKind::Record, "expected `record`");
1681
1682
    let name = try parseIdent(p, "expected record name");
1683
    let derives = try parseDerives(p);
1684
1685
    if consume(p, scanner::TokenKind::LParen) {
1686
        let fields = try parseRecordFields(p, RecordFieldMode::Unlabeled);
1687
        try expect(p, scanner::TokenKind::Semicolon, "expected `;` after record");
1688
        return node(p, ast::NodeValue::RecordDecl(
1689
            ast::RecordDecl { name, fields, attrs, derives, labeled: false }
1690
        ));
1691
    } else {
1692
        try expect(p, scanner::TokenKind::LBrace, "expected `{` before record body");
1693
        let fields = try parseRecordFields(p, RecordFieldMode::Labeled);
1694
        return node(p, ast::NodeValue::RecordDecl(
1695
            ast::RecordDecl { name, fields, attrs, derives, labeled: true }
1696
        ));
1697
    }
1698
}
1699
1700
/// Parse a union declaration.
1701
/// Example: `union Color { Red, Green, Blue = 5 }`
1702
fn parseUnionDecl(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
1703
    throws (ParseError)
1704
{
1705
    try expect(p, scanner::TokenKind::Union, "expected `union`");
1706
1707
    let name = try parseIdent(p, "expected union name");
1708
    let derives = try parseDerives(p);
1709
1710
    try expect(p, scanner::TokenKind::LBrace, "expected `{` before union body");
1711
1712
    let mut variants = ast::nodeSlice(p.arena, 128);
1713
    while not check(p, scanner::TokenKind::RBrace) {
1714
        // Allow optional `case` keyword before variant name.
1715
        consume(p, scanner::TokenKind::Case);
1716
1717
        let variantName = try parseIdent(p, "expected variant name");
1718
        let mut payloadType: ?*ast::Node = nil;
1719
        let mut explicitValue: ?*ast::Node = nil;
1720
1721
        if consume(p, scanner::TokenKind::LParen) { // `Variant(T, U)`.
1722
            let fields = try parseRecordFields(p, RecordFieldMode::Unlabeled);
1723
            set payloadType = node(p, ast::NodeValue::TypeSig(
1724
                ast::TypeSig::Record { fields, labeled: false }
1725
            ));
1726
        } else if consume(p, scanner::TokenKind::LBrace) { // `Variant { x: T, y: T }`.
1727
            let fields = try parseRecordFields(p, RecordFieldMode::Labeled);
1728
            set payloadType = node(p, ast::NodeValue::TypeSig(
1729
                ast::TypeSig::Record { fields, labeled: true }
1730
            ));
1731
        } else if consume(p, scanner::TokenKind::Equal) {
1732
            // TODO: Support constant expressions.
1733
            try expect(p, scanner::TokenKind::Number, "expected integer literal after `=`");
1734
            let literal = try parseIntLiteral(p, p.previous.source);
1735
            set explicitValue = nodeNumber(p, literal);
1736
        }
1737
1738
        let variant = node(p, ast::NodeValue::UnionDeclVariant(
1739
            ast::UnionDeclVariant {
1740
                name: variantName, index: variants.len as u32, value: explicitValue, type: payloadType,
1741
            }
1742
        ));
1743
        variants.append(variant, p.allocator);
1744
1745
        if not consume(p, scanner::TokenKind::Comma) {
1746
            break;
1747
        }
1748
    }
1749
    try expect(p, scanner::TokenKind::RBrace, "expected `}`");
1750
1751
    return node(p, ast::NodeValue::UnionDecl(
1752
        ast::UnionDecl { name, variants, attrs, derives }
1753
    ));
1754
}
1755
1756
/// Parse a function parameter.
1757
fn parseFnParam(p: *mut Parser) -> *ast::Node
1758
    throws (ParseError)
1759
{
1760
    let ntv = try parseNameTypeValue(p);
1761
    let type = ntv.type
1762
        else throw failParsing(p, "missing type in function parameter");
1763
1764
    return node(p, ast::NodeValue::FnParam(
1765
        ast::FnParam { name: ntv.name, type }
1766
    ));
1767
}
1768
1769
/// Parse an optional `throws` clause and return the collected type list.
1770
fn parseThrowList(p: *mut Parser) -> *mut [*ast::Node]
1771
    throws (ParseError)
1772
{
1773
    if not consume(p, scanner::TokenKind::Throws) {
1774
        return ast::nodeSlice(p.arena, 0);
1775
    }
1776
    return try parseList(
1777
        p,
1778
        scanner::TokenKind::LParen,
1779
        scanner::TokenKind::RParen,
1780
        parseType
1781
    );
1782
}
1783
1784
/// Parse a function type signature.
1785
fn parseFnType(p: *mut Parser) -> *ast::Node
1786
    throws (ParseError)
1787
{
1788
    try expect(p, scanner::TokenKind::Fn, "expected `fn`");
1789
    let params = try parseList(
1790
        p,
1791
        scanner::TokenKind::LParen,
1792
        scanner::TokenKind::RParen,
1793
        parseType
1794
    );
1795
    let mut returnType: ?*ast::Node = nil;
1796
1797
    if consume(p, scanner::TokenKind::Arrow) {
1798
        set returnType = try parseType(p);
1799
    }
1800
    let throwList = try parseThrowList(p);
1801
    let sig = ast::FnSig { params, returnType, throwList };
1802
    return node(p, ast::NodeValue::TypeSig(
1803
        ast::TypeSig::Fn(sig)
1804
    ));
1805
}
1806
1807
/// Parse a function signature following the function name.
1808
fn parseFnTypeSig(p: *mut Parser) -> ast::FnSig
1809
    throws (ParseError)
1810
{
1811
    try expect(p, scanner::TokenKind::LParen, "expected `(` after function name");
1812
    let mut params = ast::nodeSlice(p.arena, 8);
1813
1814
    while not check(p, scanner::TokenKind::RParen) {
1815
        let param = try parseFnParam(p);
1816
        params.append(param, p.allocator);
1817
1818
        if not consume(p, scanner::TokenKind::Comma) {
1819
            break;
1820
        }
1821
    }
1822
    try expect(p, scanner::TokenKind::RParen, "expected `)` after function parameters");
1823
1824
    let mut returnType: ?*ast::Node = nil;
1825
    if consume(p, scanner::TokenKind::Arrow) {
1826
        set returnType = try parseType(p);
1827
    }
1828
    let throwList = try parseThrowList(p);
1829
1830
    return ast::FnSig { params, returnType, throwList };
1831
}
1832
1833
/// Parse a function declaration.
1834
fn parseFnDecl(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
1835
    throws (ParseError)
1836
{
1837
    try expect(p, scanner::TokenKind::Fn, "expected `fn`");
1838
1839
    // Method syntax: `fn (recv: *Type) name(params) { body }`.
1840
    if check(p, scanner::TokenKind::LParen) {
1841
        return try parseMethodDecl(p, attrs);
1842
    }
1843
    let name = try parseIdent(p, "expected function name");
1844
    let sig = try parseFnTypeSig(p);
1845
    let mut body: ?*ast::Node = nil;
1846
    let mut fnAttrs = attrs;
1847
1848
    if consume(p, scanner::TokenKind::Semicolon) {
1849
        if let a = attrs; ast::attributesContains(&a, ast::Attribute::Extern) {
1850
            // Keep existing attributes unchanged.
1851
        } else {
1852
            let mut list = ast::nodeSlice(p.arena, 4);
1853
            if let a = attrs {
1854
                for i in 0..a.list.len {
1855
                    list.append(a.list[i], p.allocator);
1856
                }
1857
            }
1858
            let attrNode = nodeAttribute(p, ast::Attribute::Extern);
1859
            list.append(attrNode, p.allocator);
1860
            set fnAttrs = ast::Attributes { list };
1861
        }
1862
    } else {
1863
        set body = try parseBlock(p);
1864
    }
1865
    return node(p, ast::NodeValue::FnDecl(
1866
        ast::FnDecl { name, sig, body, attrs: fnAttrs }
1867
    ));
1868
}
1869
1870
/// Parse a pointer-like type after its ownership prefix.
1871
fn parsePointerLikeType(
1872
    p: *mut Parser,
1873
    class: types::PointerClass,
1874
) -> *ast::Node throws (ParseError) {
1875
    let mutable = consume(p, scanner::TokenKind::Mut);
1876
1877
    if consume(p, scanner::TokenKind::LBracket) {
1878
        let itemType = try parseType(p);
1879
        try expect(p, scanner::TokenKind::RBracket, "expected `]` after slice element type");
1880
1881
        return node(p, ast::NodeValue::TypeSig(
1882
            ast::TypeSig::Slice { class, itemType, mutable }
1883
        ));
1884
    }
1885
    // Check for an opaque trait object.
1886
    if consume(p, scanner::TokenKind::Opaque) {
1887
        if check(p, scanner::TokenKind::Ident) or check(p, scanner::TokenKind::Super) {
1888
            let traitName = try parseTypePath(p);
1889
            return node(p, ast::NodeValue::TypeSig(
1890
                ast::TypeSig::TraitObject { class, traitName, mutable }
1891
            ));
1892
        }
1893
        // Plain opaque target.
1894
        let valueType = node(p, ast::NodeValue::TypeSig(ast::TypeSig::Opaque));
1895
        return node(p, ast::NodeValue::TypeSig(
1896
            ast::TypeSig::Pointer { class, valueType, mutable }
1897
        ));
1898
    }
1899
    let valueType = try parseType(p);
1900
1901
    return node(p, ast::NodeValue::TypeSig(
1902
        ast::TypeSig::Pointer { class, valueType, mutable }
1903
    ));
1904
}
1905
1906
/// Parse an array type.
1907
fn parseArrayType(p: *mut Parser) -> *ast::Node
1908
    throws (ParseError)
1909
{
1910
    try expect(p, scanner::TokenKind::LBracket, "expected `[`");
1911
    let itemType = try parseType(p);
1912
1913
    try expect(p, scanner::TokenKind::Semicolon, "expected `;` in array type");
1914
    let length = try parseExpr(p);
1915
1916
    try expect(p, scanner::TokenKind::RBracket, "expected `]` after array length");
1917
    return node(p, ast::NodeValue::TypeSig(
1918
        ast::TypeSig::Array { itemType, length }
1919
    ));
1920
}
1921
1922
/// Parse a type path: an identifier optionally followed by `::` scope access.
1923
/// Returns an identifier node or a scope access chain.
1924
fn parseTypePath(p: *mut Parser) -> *ast::Node
1925
    throws (ParseError)
1926
{
1927
    let mut path: *ast::Node = undefined;
1928
    if p.current.kind == scanner::TokenKind::Super {
1929
        advance(p);
1930
        set path = nodeSuper(p);
1931
    } else {
1932
        set path = try parseIdent(p, "expected type identifier");
1933
    }
1934
    while consume(p, scanner::TokenKind::ColonColon) {
1935
        let part = try parseIdent(p, "expected identifier after `::`");
1936
        set path = node(p, ast::NodeValue::ScopeAccess(
1937
            ast::Access { parent: path, child: part }
1938
        ));
1939
    }
1940
    return path;
1941
}
1942
1943
/// Parse a type annotation.
1944
export fn parseType(p: *mut Parser) -> *ast::Node
1945
    throws (ParseError)
1946
{
1947
    match p.current.kind {
1948
        case scanner::TokenKind::Question => {
1949
            advance(p);
1950
            let valueType = try parseType(p);
1951
1952
            return node(p, ast::NodeValue::TypeSig(
1953
                ast::TypeSig::Optional { valueType }
1954
            ));
1955
        }
1956
        case scanner::TokenKind::Star => {
1957
            advance(p);
1958
            let class = types::PointerClass::Unsafe
1959
                if consume(p, scanner::TokenKind::Unsafe)
1960
                else types::PointerClass::Owned;
1961
            return try parsePointerLikeType(p, class);
1962
        }
1963
        case scanner::TokenKind::Amp => {
1964
            advance(p);
1965
            return try parsePointerLikeType(p, types::PointerClass::Ref);
1966
        }
1967
        case scanner::TokenKind::LBracket => {
1968
            return try parseArrayType(p);
1969
        }
1970
        case scanner::TokenKind::Super, scanner::TokenKind::Ident => {
1971
            let path = try parseTypePath(p);
1972
1973
            return node(p, ast::NodeValue::TypeSig(
1974
                ast::TypeSig::Nominal(path)
1975
            ));
1976
        }
1977
        case scanner::TokenKind::U8 => {
1978
            advance(p);
1979
            return nodeTypeInt(p, 1, ast::Signedness::Unsigned);
1980
        }
1981
        case scanner::TokenKind::U16 => {
1982
            advance(p);
1983
            return nodeTypeInt(p, 2, ast::Signedness::Unsigned);
1984
        }
1985
        case scanner::TokenKind::U32 => {
1986
            advance(p);
1987
            return nodeTypeInt(p, 4, ast::Signedness::Unsigned);
1988
        }
1989
        case scanner::TokenKind::U64 => {
1990
            advance(p);
1991
            return nodeTypeInt(p, 8, ast::Signedness::Unsigned);
1992
        }
1993
        case scanner::TokenKind::I8 => {
1994
            advance(p);
1995
            return nodeTypeInt(p, 1, ast::Signedness::Signed);
1996
        }
1997
        case scanner::TokenKind::I16 => {
1998
            advance(p);
1999
            return nodeTypeInt(p, 2, ast::Signedness::Signed);
2000
        }
2001
        case scanner::TokenKind::I32 => {
2002
            advance(p);
2003
            return nodeTypeInt(p, 4, ast::Signedness::Signed);
2004
        }
2005
        case scanner::TokenKind::I64 => {
2006
            advance(p);
2007
            return nodeTypeInt(p, 8, ast::Signedness::Signed);
2008
        }
2009
        case scanner::TokenKind::Bool => {
2010
            advance(p);
2011
            return node(p, ast::NodeValue::TypeSig(ast::TypeSig::Bool));
2012
        }
2013
        case scanner::TokenKind::Opaque => {
2014
            advance(p);
2015
            return node(p, ast::NodeValue::TypeSig(ast::TypeSig::Opaque));
2016
        }
2017
        case scanner::TokenKind::Fn => {
2018
            return try parseFnType(p);
2019
        }
2020
        else => {
2021
            throw failParsing(p, "expected type");
2022
        }
2023
    }
2024
}
2025
2026
/// Parse a name, optional type, and optional value.
2027
///
2028
/// Used for record field declarations, variable declarations,
2029
/// and record field initializations.
2030
fn parseNameTypeValue(p: *mut Parser) -> NameTypeValue
2031
    throws (ParseError)
2032
{
2033
    let name = try parseIdentOrPlaceholder(p, "expected identifier or `_`");
2034
    let mut type: ?*ast::Node = nil;
2035
    let mut alignment: ?*ast::Node = nil;
2036
    let mut value: ?*ast::Node = nil;
2037
2038
    if consume(p, scanner::TokenKind::Colon) {
2039
        set type = try parseType(p);
2040
2041
        if check(p, scanner::TokenKind::Align) {
2042
            set alignment = try parseAlign(p);
2043
        }
2044
    }
2045
    if consume(p, scanner::TokenKind::Equal) {
2046
        set value = try parseExpr(p);
2047
    }
2048
    return NameTypeValue { name, type, value, alignment };
2049
}
2050
2051
/// Parse a constant declaration.
2052
fn parseConst(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
2053
    throws (ParseError)
2054
{
2055
    try expect(p, scanner::TokenKind::Constant, "expected `constant`");
2056
2057
    let ident = try parseIdent(p, "expected identifier in constant declaration");
2058
    try expect(p, scanner::TokenKind::Colon, "expected `:` after identifier");
2059
2060
    let type = try parseType(p);
2061
    try expect(p, scanner::TokenKind::Equal, "expected `=` in constant declaration");
2062
2063
    let value = try parseExpr(p);
2064
2065
    return node(p, ast::NodeValue::ConstDecl(
2066
        ast::ConstDecl { ident, type, value, attrs }
2067
    ));
2068
}
2069
2070
/// Parse a static declaration.
2071
fn parseStatic(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
2072
    throws (ParseError)
2073
{
2074
    try expect(p, scanner::TokenKind::Static, "expected `static`");
2075
2076
    let ident = try parseIdent(p, "expected identifier in static declaration");
2077
    try expect(p, scanner::TokenKind::Colon, "expected `:` after identifier");
2078
2079
    let type = try parseType(p);
2080
    try expect(p, scanner::TokenKind::Equal, "expected `=` in static declaration");
2081
2082
    let value = try parseExpr(p);
2083
2084
    return node(p, ast::NodeValue::StaticDecl(
2085
        ast::StaticDecl { ident, type, value, attrs }
2086
    ));
2087
}
2088
2089
/// Parse a `use` declaration.
2090
fn parseUse(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
2091
    throws (ParseError)
2092
{
2093
    try expect(p, scanner::TokenKind::Use, "expected `use`");
2094
2095
    // Allow `super` or identifier as the first part of the path.
2096
    let mut path: *ast::Node = undefined;
2097
    if consume(p, scanner::TokenKind::Super) {
2098
        set path = nodeSuper(p);
2099
    } else {
2100
        set path = try parseIdent(p, "expected module name or `super` after `use`");
2101
    }
2102
    while consume(p, scanner::TokenKind::ColonColon) {
2103
        // Check for wildcard import (e.g., `use parser::*`)
2104
        if consume(p, scanner::TokenKind::Star) {
2105
            return node(p, ast::NodeValue::Use(
2106
                ast::Use { path, wildcard: true, attrs }
2107
            ));
2108
        }
2109
        let part = try parseIdent(p, "expected identifier or `*` after `::`");
2110
        set path = node(p, ast::NodeValue::ScopeAccess(
2111
            ast::Access { parent: path, child: part }
2112
        ));
2113
    }
2114
    return node(p, ast::NodeValue::Use(
2115
        ast::Use { path, wildcard: false, attrs }
2116
    ));
2117
}
2118
2119
/// Parse a `mod` declaration.
2120
fn parseMod(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
2121
    throws (ParseError)
2122
{
2123
    try expect(p, scanner::TokenKind::Mod, "expected `mod`");
2124
    let name = try parseIdent(p, "expected module name after `mod`");
2125
2126
    return node(p, ast::NodeValue::Mod(
2127
        ast::Mod { name, attrs }
2128
    ));
2129
}
2130
2131
/// Parse a `let case` guard statement.
2132
///
2133
/// Eg. `let case <pattern> = <expr> else { ... };`
2134
/// Eg. `let case <pattern> = <expr> if <guard> else { ... };`
2135
///
2136
/// Expects `let case` tokens to have already been consumed.
2137
fn parseLetCase(p: *mut Parser) -> *ast::Node throws (ParseError) {
2138
    let pattern = try parseMatchPattern(p);
2139
2140
    try expect(p, scanner::TokenKind::Equal, "expected `=` after pattern");
2141
    let expr = try parseCond(p);
2142
2143
    let mut guard: ?*ast::Node = nil;
2144
    if consume(p, scanner::TokenKind::If) {
2145
        set guard = try parseCond(p);
2146
    }
2147
2148
    try expect(p, scanner::TokenKind::Else, "expected `else` after pattern");
2149
    let elseBranch = try parseLetElseBranch(p);
2150
2151
    return node(p, ast::NodeValue::LetElse(ast::LetElse {
2152
        pattern: ast::PatternMatch { pattern, scrutinee: expr, guard, kind: ast::PatternKind::Case, mutable: false },
2153
        elseBranch,
2154
    }));
2155
}
2156
2157
/// Parse a `let` binding statement.
2158
///
2159
/// Eg. `let <ident> = <expr>;`
2160
/// Eg. `let <ident> = <expr> else { ... };`
2161
/// Eg. `let mut <ident> = <expr> else { ... };`
2162
/// Eg. `let <ident> = <expr> if <guard> else { ... };`
2163
/// Eg. `mut <ident> = <expr>;`
2164
///
2165
/// Expects `let` or `mut` token to have already been consumed.
2166
fn parseLet(p: *mut Parser, mutable: bool) -> *ast::Node throws (ParseError) {
2167
    let binding = try parseNameTypeValue(p);
2168
    let value = binding.value
2169
        else throw failParsing(p, "expected value initializer");
2170
2171
    // Check for optional `else` clause (let-else).
2172
    if consume(p, scanner::TokenKind::Else) {
2173
        let elseBranch = try parseLetElseBranch(p);
2174
2175
        return node(p, ast::NodeValue::LetElse(ast::LetElse {
2176
            pattern: ast::PatternMatch { pattern: binding.name, scrutinee: value, guard: nil, kind: ast::PatternKind::Binding, mutable },
2177
            elseBranch,
2178
        }));
2179
    }
2180
    return node(p, ast::NodeValue::Let(ast::Let {
2181
        ident: binding.name, type: binding.type, value, alignment: binding.alignment, mutable,
2182
    }));
2183
}
2184
2185
/// Parse a module from source text using the provided arena for node storage.
2186
export fn parse(sourceLoc: scanner::SourceLoc, input: *[u8], arena: *mut ast::NodeArena, pool: *mut strings::Pool) -> *mut ast::Node
2187
    throws (ParseError)
2188
{
2189
    let mut p = mkParser(sourceLoc, input, arena, pool);
2190
    return try parseModule(&mut p) catch {
2191
        printErrors(&p);
2192
        throw ParseError::UnexpectedToken;
2193
    };
2194
}
2195
2196
/// Parse a complete module into a block of top-level statements.
2197
///
2198
/// This is the main entry point for parsing an entire Radiance source file.
2199
/// The parser must already be initialized with source code.
2200
export fn parseModule(p: *mut Parser) -> *mut ast::Node
2201
    throws (ParseError)
2202
{
2203
    advance(p); // Set the parser up with a first token.
2204
2205
    let mut blk = mkBlock(p, 512);
2206
    try parseStmtsUntil(p, scanner::TokenKind::Eof, &mut blk);
2207
    consume(p, scanner::TokenKind::Eof);
2208
2209
    return node(p, ast::NodeValue::Block(blk));
2210
}
2211
2212
/// Consume a token of the given kind if present.
2213
export fn consume(p: *mut Parser, kind: scanner::TokenKind) -> bool {
2214
    if check(p, kind) {
2215
        advance(p);
2216
        return true;
2217
    }
2218
    return false;
2219
}
2220
2221
/// Expect a token of the given kind or report an error.
2222
export fn expect(p: *mut Parser, kind: scanner::TokenKind, message: *[u8]) -> *[u8]
2223
    throws (ParseError)
2224
{
2225
    if not consume(p, kind) {
2226
        reportError(p, p.current, message);
2227
        throw ParseError::UnexpectedToken;
2228
    }
2229
    return p.previous.source;
2230
}
2231
2232
/// Return a generic expectation message for a delimiter token.
2233
fn listExpectMessage(kind: scanner::TokenKind) -> *[u8] {
2234
    match kind {
2235
        case scanner::TokenKind::LParen => return "expected `(`",
2236
        case scanner::TokenKind::RParen => return "expected `)`",
2237
        case scanner::TokenKind::LBracket => return "expected `[`",
2238
        case scanner::TokenKind::RBracket => return "expected `]`",
2239
        case scanner::TokenKind::LBrace => return "expected `{`",
2240
        case scanner::TokenKind::RBrace => return "expected `}`",
2241
        else => return "expected delimiter",
2242
    }
2243
}
2244
2245
/// Parse a trait declaration.
2246
/// Syntax: `trait Name { fn (*Trait) method(...) -> T; ... }`
2247
fn parseTraitDecl(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
2248
    throws (ParseError)
2249
{
2250
    try expect(p, scanner::TokenKind::Trait, "expected `trait`");
2251
    let name = try parseIdent(p, "expected trait name");
2252
    let supertraits = try parseDerives(p);
2253
    try expect(p, scanner::TokenKind::LBrace, "expected `{` after trait name");
2254
2255
    let mut methods = ast::nodeSlice(p.arena, ast::MAX_TRAIT_METHODS);
2256
    while not check(p, scanner::TokenKind::RBrace) and
2257
          not check(p, scanner::TokenKind::Eof)
2258
    {
2259
        let method = try parseTraitMethodSig(p);
2260
        methods.append(method, p.allocator);
2261
    }
2262
    try expect(p, scanner::TokenKind::RBrace, "expected `}` after trait methods");
2263
2264
    return node(p, ast::NodeValue::TraitDecl { name, supertraits, methods, attrs });
2265
}
2266
2267
/// Parse a trait method signature.
2268
/// Syntax: `fn (*Trait) fnord(<params>) -> ReturnType;`
2269
fn parseTraitMethodSig(p: *mut Parser) -> *ast::Node
2270
    throws (ParseError)
2271
{
2272
    let attrs = parseAttributes(p);
2273
    try expect(p, scanner::TokenKind::Fn, "expected `fn`");
2274
    try expect(p, scanner::TokenKind::LParen, "expected `(` before receiver");
2275
2276
    let receiver = try parseType(p);
2277
2278
    try expect(p, scanner::TokenKind::RParen, "expected `)` after receiver");
2279
2280
    let name = try parseIdent(p, "expected method name");
2281
    let sig = try parseFnTypeSig(p);
2282
    try expect(p, scanner::TokenKind::Semicolon, "expected `;` after method signature");
2283
2284
    return node(p, ast::NodeValue::TraitMethodSig { name, receiver, sig, attrs });
2285
}
2286
2287
/// Parse an instance block.
2288
/// Syntax: `instance Trait for Type { fn (t: *mut Type) fnord(..) {..} }`
2289
///
2290
/// Instance declarations do not accept attributes (e.g. `export`).
2291
/// Visibility is determined by the trait declaration itself.
2292
fn parseInstanceDecl(p: *mut Parser) -> *ast::Node
2293
    throws (ParseError)
2294
{
2295
    try expect(p, scanner::TokenKind::Instance, "expected `instance`");
2296
    let traitName = try parseTypePath(p);
2297
    try expect(p, scanner::TokenKind::For, "expected `for` after trait name");
2298
    let targetType = try parseTypePath(p);
2299
    try expect(p, scanner::TokenKind::LBrace, "expected `{` after target type");
2300
2301
    let mut methods = ast::nodeSlice(p.arena, ast::MAX_TRAIT_METHODS);
2302
2303
    while not check(p, scanner::TokenKind::RBrace) and
2304
          not check(p, scanner::TokenKind::Eof)
2305
    {
2306
        let attrs = parseAttributes(p);
2307
        try expect(p, scanner::TokenKind::Fn, "expected `fn`");
2308
        let method = try parseMethodDecl(p, attrs);
2309
2310
        methods.append(method, p.allocator);
2311
    }
2312
    try expect(p, scanner::TokenKind::RBrace, "expected `}` after instance methods");
2313
2314
    return node(p, ast::NodeValue::InstanceDecl { traitName, targetType, methods });
2315
}
2316
2317
/// Parse a method declaration with a receiver.
2318
/// Syntax: `fn (t: *mut Type) fnord(<params>) -> ReturnType { body }`
2319
///
2320
/// Used both inside `instance` blocks and as standalone methods at the top level.
2321
/// Expects the `fn` token to have already been consumed.
2322
fn parseMethodDecl(p: *mut Parser, attrs: ?ast::Attributes) -> *ast::Node
2323
    throws (ParseError)
2324
{
2325
    try expect(p, scanner::TokenKind::LParen, "expected `(` before receiver");
2326
2327
    let receiverName = try parseIdent(p, "expected receiver name");
2328
    try expect(p, scanner::TokenKind::Colon, "expected `:` after receiver name");
2329
    let receiverType = try parseType(p);
2330
2331
    try expect(p, scanner::TokenKind::RParen, "expected `)` after receiver type");
2332
2333
    let name = try parseIdent(p, "expected method name");
2334
    let sig = try parseFnTypeSig(p);
2335
    let body = try parseBlock(p);
2336
2337
    return node(p, ast::NodeValue::MethodDecl {
2338
        name, receiverName, receiverType, sig, body, attrs,
2339
    });
2340
}
2341
2342
/// Parse a comma-separated list enclosed by the given delimiters.
2343
fn parseList(
2344
    p: *mut Parser,
2345
    open: scanner::TokenKind,
2346
    close: scanner::TokenKind,
2347
    parseItem: fn (*mut Parser) -> *ast::Node throws (ParseError)
2348
) -> *mut [*ast::Node] throws (ParseError) {
2349
    try expect(p, open, listExpectMessage(open));
2350
    let mut items = ast::nodeSlice(p.arena, 8);
2351
2352
    while not check(p, close) {
2353
        let item = try parseItem(p);
2354
        items.append(item, p.allocator);
2355
2356
        if not consume(p, scanner::TokenKind::Comma) {
2357
            break;
2358
        }
2359
    }
2360
    try expect(p, close, listExpectMessage(close));
2361
2362
    return items;
2363
}