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