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