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