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