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