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