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