voltaic-parser 0.2.0

Hand-written recursive-descent parser for the Voltaic language.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
import crate::ParseError
import crate::block::check_callback_tails
import crate::block::condition
import crate::block::control_flow
import crate::block::ladder_condition
import crate::block::stmt
import crate::datatype::data_decl
import crate::datatype::derive_template
import crate::datatype::errors_decl
import crate::datatype::generalise
import crate::expr::parse_expr
import crate::expr::parse_spine
import crate::item::const_decl
import crate::item::declares_an_operator
import crate::item::extern_block
import crate::item::import_decl
import crate::item::module_decl
import crate::item::operator_decl
import crate::item::pattern_synonym
import crate::item::test_decl
import crate::item::type_alias
import crate::item::visibility
import crate::pattern::pattern_alt
import crate::pattern::patterns
import crate::signature::SignatureHead
import crate::signature::TypeStop
import crate::signature::capture_type
import crate::signature::clause
import crate::signature::signature_from
import crate::signature::signature_only
import crate::signature::signature_unsigned
import crate::support::MAX_NESTING
import crate::support::nesting_depth
import crate::token::inline_rust
import crate::type_class::class_decl
import crate::type_class::constraints
import crate::type_class::given_clause
import crate::type_class::instance_decl
import crate::where_clause::where_predicates
import voltaic_ast::Binding
import voltaic_ast::Block
import voltaic_ast::Expr
import voltaic_ast::Fixity
import voltaic_ast::FnDecl
import voltaic_ast::Guard
import voltaic_ast::Ident
import voltaic_ast::Item
import voltaic_ast::Program
import voltaic_ast::Stmt
import voltaic_ast::TypeExpr
import voltaic_ast::Visibility
import voltaic_diag::Code
import voltaic_lexer::Keyword
import voltaic_lexer::Span
import voltaic_lexer::Token
import voltaic_lexer::TokenKind
import voltaic_lexer::Trivia

export parse : &[Token] -> usize -> Result<Program, Vec<ParseError>>
parse toks src_len =
  deepest = nesting_depth toks
  if deepest > MAX_NESTING
    message = format! \-> "this input nests brackets #{deepest} deep, and the limit is #{MAX_NESTING}: deeper than that overflows the parser's stack"
    return Err (vec! \-> ParseError { code = Code::NestingTooDeep, message, span = (0, 0), help = None })
  .run src_len $ Parser::new toks

export(crate) data Parser { toks &'a [Token], pos usize, export(crate) r#errors Vec<ParseError>, class_heads std::collections::BTreeMap<(String, String), SignatureHead>, export(crate) fixities std::collections::BTreeMap<String, (Fixity, u8, String)> }

instance (Parser 'a)
  export(crate) new : &'a [Token] -> Self
  new toks = Parser { toks, pos = 0, r#errors = Vec::new (), class_heads = std::collections::BTreeMap::new (), fixities = std::collections::BTreeMap::new () }
  export(crate) run : usize -> mut self -> Result<Program, Vec<ParseError>>
  run src_len self =
    items = .program self
    if .is_empty self.r#errors
      probe = Program { items = .clone items, span = (0, src_len), trailing = Vec::new () }
      .extend (check_callback_tails (&probe)) self.r#errors
    if .is_empty self.r#errors
      trailing = .eof_trivia self
      return Ok (Program { items, span = (0, src_len), trailing })
    Err self.r#errors
  program : &mut self -> Vec<Item>
  program self =
    mut items = Vec::new ()
    .skip_separators self
    while !.at_eof self
      case .item self of
        Ok found -> .push found items
        Err e ->
          .push e self.r#errors
          .recover_to_item self
      .skip_separators self
    items
  export(crate) items_until_dedent : &mut self -> Result<Vec<Item>, ParseError>
  items_until_dedent self =
    mut items = Vec::new ()
    loop
      .skip_separators self
      if .check (&TokenKind::Dedent) self || .at_eof self
        break
      case .item self of
        Ok found -> .push found items
        Err e ->
          .push e self.r#errors
          .recover_to_item self
    (.expect (&TokenKind::Dedent) "expected the module body to end" self)?
    Ok items
  export(crate) item : &mut self -> Result<Item, ParseError>
  item self =
    leading = .peek_leading self
    start = (.peek_span self).0
    marker = (visibility self)?
    if .check (&TokenKind::Kw Keyword::Data) self || .check (&TokenKind::Kw Keyword::Newtype) self || .check (&TokenKind::Kw Keyword::Union) self
      decl = (data_decl self leading start marker)?
      (.newline_with_trailing "expected a line break after the declaration" self)?
      return Ok (Item::Data decl)
    if .check (&TokenKind::Kw Keyword::Type) self
      alias = (type_alias self leading start marker)?
      (.newline_with_trailing "expected a line break after the alias" self)?
      return Ok (Item::Type alias)
    if .check (&TokenKind::Kw Keyword::Const) self || .check (&TokenKind::Kw Keyword::Static) self
      decl = (const_decl self leading start marker)?
      (.newline_with_trailing "expected a line break after the binding" self)?
      return Ok (Item::Const decl)
    if .check (&TokenKind::Kw Keyword::Import) self
      decl = (import_decl self leading start marker)?
      (.newline_with_trailing "expected a line break after the import" self)?
      return Ok (Item::Import decl)
    if .check (&TokenKind::Kw Keyword::Module) self
      decl = (module_decl self leading start marker)?
      (.newline_with_trailing "expected a line break after the module" self)?
      return Ok (Item::Module decl)
    if .check (&TokenKind::Kw Keyword::Test) self
      decl = (test_decl self leading start)?
      (.newline_with_trailing "expected a line break after the test" self)?
      return Ok (Item::Test decl)
    if .check (&TokenKind::Kw Keyword::Rust) self
      block = (inline_rust self leading start)?
      (.newline_with_trailing "expected a line break after the inline Rust" self)?
      return Ok (Item::InlineRust block)
    word_is_pattern = case &(.peek self).kind of
      TokenKind::Ident text -> text == "pattern"
      _ -> false
    names_a_constructor = .is_some_and (\t -> case &t.kind of
      TokenKind::Ident next -> .is_some_and char::is_uppercase (.next (.chars next))
      _ -> false) (.peek_at 1 self)
    if word_is_pattern && names_a_constructor
      decl = (pattern_synonym self leading start)?
      return Ok (Item::PatternSynonym decl)
    if declares_an_operator self
      decl = (operator_decl self leading start)?
      return Ok (Item::OperatorDecl decl)
    if .check (&TokenKind::Kw Keyword::Deriving) self
      decl = (derive_template self leading start)?
      (.newline_with_trailing "expected a line break after the deriving template" self)?
      return Ok (Item::DeriveTemplate decl)
    if .check (&TokenKind::Kw Keyword::Extern) self
      block = (extern_block self leading start)?
      return Ok (Item::Extern block)
    if .check (&TokenKind::Kw Keyword::Errors) self
      decl = (errors_decl self leading start marker)?
      (.newline_with_trailing "expected a line break after the declaration" self)?
      return Ok (Item::Errors decl)
    if .check (&TokenKind::Kw Keyword::Class) self
      decl = (class_decl self leading start marker)?
      (.newline_with_trailing "expected a line break after the class" self)?
      return Ok (Item::Class decl)
    if .check (&TokenKind::Kw Keyword::Instance) self
      decl = (instance_decl self leading start)?
      (.newline_with_trailing "expected a line break after the instance" self)?
      return Ok (Item::Instance decl)
    mut decl = (.function (&[]) self)?
    decl.leading := leading
    decl.visibility := marker
    decl.span := (start, decl.span.1)
    Ok $ Item::Fn decl
  export(crate) function : &[String] -> &mut self -> Result<FnDecl, ParseError>
  function reserved self =
    leading = .peek_leading self
    start = (.peek_span self).0
    if !.signed self
      name = (.peeked_name "expected a name to begin a declaration" self)?
      return .unsigned_equations name leading start reserved false self
    name = (.ident "expected a name to begin a declaration" self)?
    head = (.signature_head (&name) self)?
    decl = (.equations (.clone name) leading start (&head) reserved true self)?
    if .is_empty decl.clauses
      message = format! \-> "`#{name.text}` has a signature and no equations; write its body, or delete the signature and let it be inferred"
      return Err (ParseError::r#with Code::EmptyBody message name.span)
    Ok decl
  export(crate) where_function : &mut self -> Result<FnDecl, ParseError>
  where_function self =
    leading = .peek_leading self
    start = (.peek_span self).0
    if !.signed self
      name = (.peeked_name "expected a name to begin a declaration" self)?
      return .unsigned_equations name leading start (&[]) true self
    name = (.ident "expected a name to begin a declaration" self)?
    head = (.signature_head (&name) self)?
    .equations name leading start (&head) (&[]) true self
  export(crate) signed : &self -> bool
  signed self = case &(.peek self).kind of
    TokenKind::Ident _ -> .is_some_and (\t -> t.kind == TokenKind::Colon) (.peek_at 1 self)
    _ -> true
  export(crate) peeked_name : &str -> &self -> Result<Ident, ParseError>
  peeked_name message self = case &(.peek self).kind of
    TokenKind::Ident text -> Ok (Ident { text = .clone text, span = .peek_span self })
    _ -> Err (ParseError::r#with Code::ExpectedName (.to_string message) (.peek_span self))
  export(crate) signature_head : &Ident -> &mut self -> Result<SignatureHead, ParseError>
  signature_head name self =
    binds_on_this_line = .check (&TokenKind::Eq) self && .is_some_and (\t -> t.kind != TokenKind::Newline) (.peek_at 1 self)
    if binds_on_this_line
      message = format! \-> "a module-scope binding needs `const` or `static` and a type: `const #{name.text} : T = …`. Rust forbids `let` at module scope, and doc 03 §13.4 corrects doc 01 §4.3 accordingly"
      return Err (ParseError::r#with Code::ModuleScopeBinding message name.span)
    (.expect (&TokenKind::Colon) "expected `:` after the name, to begin the signature" self)?
    binder = (given_clause self)?
    bounds = if .is_some binder
      Vec::new ()
    else
      (constraints self)?
    is_const = .eat_keyword Keyword::Const self
    is_async = .eat_keyword Keyword::Async self
    is_unsafe = .eat_keyword Keyword::Unsafe self
    spine = (parse_spine self)?
    predicates = (where_predicates self)?
    (.newline_with_trailing "expected a line break after the signature" self)?
    Ok (SignatureHead { types = spine, bounds, r#given = binder, predicates, is_const, is_async, is_unsafe })
  export(crate) record_head : &str -> &str -> &SignatureHead -> &mut self -> ()
  record_head class_name member head self =
    key = (.to_string class_name, .to_string member)
    .insert key (.clone head) self.class_heads
    ()
  export(crate) borrowed_head : &str -> &str -> &self -> Option<SignatureHead>
  borrowed_head class_name member self =
    key = (.to_string class_name, .to_string member)
    (self.class_heads.get (&key)).cloned ()
  export(crate) equations : Ident -> Vec<Trivia> -> usize -> &SignatureHead -> &[String] -> bool -> &mut self -> Result<FnDecl, ParseError>
  equations name leading start head reserved ends_on_a_new_name self =
    spine = &head.types
    bounds = &head.bounds
    mut clauses = Vec::new ()
    mut sig = None
    loop
      is_equation = case &(.peek self).kind of
        TokenKind::Ident _ -> !.is_some_and (\t -> t.kind == TokenKind::Colon) (.peek_at 1 self)
        _ -> false
      if !is_equation
        break
      if declares_an_operator self
        break
      same_name = case &(.peek self).kind of
        TokenKind::Ident text | text == &name.text -> true
        _ -> false
      if ends_on_a_new_name && !same_name
        break
      again = (.ident "expected the equation to repeat the name" self)?
      if again.text != name.text
        message = format! \-> "this equation defines `#{again.text}`, but the signature above it is for `#{name.text}`"
        return Err (ParseError::r#with Code::ExpectedName message again.span)
      row = (patterns self)?
      built = (signature_from spine (&row) (again.span.0, (.prev_span self).1))?
      returns_unit = .returns_unit built
      if .is_none sig
        sig := Some built
      .push (clause row (&name) returns_unit self)? clauses
      .skip_separators self
    mut settled = .unwrap_or_else (\-> signature_only spine (name.span.0, (.prev_span self).1)) sig
    settled.r#given := .clone head.r#given
    settled.predicates := .clone head.predicates
    generalise (&mut settled) bounds reserved
    settled.is_const := head.is_const
    settled.is_async := head.is_async
    settled.is_unsafe := head.is_unsafe
    end = (.prev_span self).1
    trailing = .and_then (\c -> .clone c.trailing) (.last clauses)
    Ok (FnDecl { name, sig = settled, clauses, visibility = Visibility::Private, span = (start, end), leading, trailing })
  export(crate) unsigned_equations : Ident -> Vec<Trivia> -> usize -> &[String] -> bool -> &mut self -> Result<FnDecl, ParseError>
  unsigned_equations name leading start reserved ends_on_a_new_name self =
    if .check (&TokenKind::Eq) self && .is_some_and (\t -> t.kind != TokenKind::Newline) (.peek_at 1 self)
      message = format! \-> "a module-scope binding needs `const` or `static` and a type: `const #{name.text} : T = …`. Rust forbids `let` at module scope, and doc 03 §13.4 corrects doc 01 §4.3 accordingly"
      return Err (ParseError::r#with Code::ModuleScopeBinding message name.span)
    mut clauses = Vec::new ()
    mut sig = None
    loop
      is_equation = case &(.peek self).kind of
        TokenKind::Ident _ -> !.is_some_and (\t -> t.kind == TokenKind::Colon) (.peek_at 1 self)
        _ -> false
      if !is_equation
        break
      if declares_an_operator self
        break
      same_name = case &(.peek self).kind of
        TokenKind::Ident text | text == &name.text -> true
        _ -> false
      if !same_name && (ends_on_a_new_name || !.is_empty clauses)
        break
      again = (.ident "expected the equation to repeat the name" self)?
      if again.text != name.text
        message = format! \-> "this equation defines `#{again.text}`, but the one above it defines `#{name.text}`"
        return Err (ParseError::r#with Code::ExpectedName message again.span)
      row = (patterns self)?
      if .check (&TokenKind::Eq) self && .is_some_and (\t -> t.kind != TokenKind::Newline) (.peek_at 1 self) && .is_empty row
        message = format! \-> "a module-scope binding needs `const` or `static` and a type: `const #{name.text} : T = …`. Rust forbids `let` at module scope, and doc 03 §13.4 corrects doc 01 §4.3 accordingly"
        return Err (ParseError::r#with Code::ModuleScopeBinding message again.span)
      built = signature_unsigned (&row) (again.span.0, (.prev_span self).1)
      if .is_none sig
        sig := Some built
      .push (clause row (&name) false self)? clauses
      .skip_separators self
    mut settled = .unwrap_or_else (\-> signature_unsigned (&[]) (name.span.0, (.prev_span self).1)) sig
    generalise (&mut settled) (&[]) reserved
    end = (.prev_span self).1
    trailing = .and_then (\c -> .clone c.trailing) (.last clauses)
    Ok (FnDecl { name, sig = settled, clauses, visibility = Visibility::Private, span = (start, end), leading, trailing })
  export(crate) statements : &mut self -> Result<Block, ParseError>
  statements self =
    start = (.peek_span self).0
    mut stmts = Vec::new ()
    loop
      .skip_separators self
      if .check (&TokenKind::Dedent) self || .at_eof self
        break
      case stmt self of
        Ok found -> .push found stmts
        Err e ->
          .push e self.r#errors
          .recover_to_stmt self
    end = (.prev_span self).1
    (.expect (&TokenKind::Dedent) "expected the body to end" self)?
    if .is_empty stmts && .is_empty self.r#errors
      return Err (ParseError::r#with Code::EmptyBody "a declaration body must contain at least one statement" (start, start))
    Ok (Block { stmts, span = (start, end) })
  export(crate) indented_block : Code -> &str -> &mut self -> Result<Block, ParseError>
  indented_block code message self =
    (.expect_with code (&TokenKind::Indent) message self)?
    .statements self
  export(crate) statement_block : &str -> &mut self -> Result<Block, ParseError>
  statement_block message self =
    (.newline_with_trailing "expected a line break before the body" self)?
    .indented_block Code::EmptyBody message self
  export(crate) at_statement_end : &self -> bool
  at_statement_end self = .check (&TokenKind::Newline) self || .check (&TokenKind::Dedent) self || .at_eof self
  export(crate) if_statement : &mut self -> Result<Expr, ParseError>
  if_statement self =
    open = (.peek_span self).0
    (.expect (&TokenKind::Kw Keyword::If) "expected `if`" self)?
    cond = (condition self)?
    then_block = (.statement_block "expected an indented `if` body" self)?
    .skip_separators self
    if !.check (&TokenKind::Kw Keyword::Else) self
      return Ok (Expr::If { condition = cond, then_block, r#otherwise = None, span = (open, (.prev_span self).1) })
    .advance self
    if .check (&TokenKind::Kw Keyword::If) self
      start = (.peek_span self).0
      nested = (.if_statement self)?
      end = (.prev_span self).1
      only = Stmt { expr = nested, span = (start, end), leading = Vec::new (), trailing = None }
      chained = Block { stmts = vec! \-> only, span = (start, end) }
      return Ok (Expr::If { condition = cond, then_block, r#otherwise = Some chained, span = (open, end) })
    fallback = (.statement_block "expected an indented `else` body" self)?
    Ok (Expr::If { condition = cond, then_block, r#otherwise = Some fallback, span = (open, (.prev_span self).1) })
  export(crate) inline_body : &mut self -> Result<Block, ParseError>
  inline_body self =
    start = (.peek_span self).0
    value = (parse_expr self 0)?
    end = (.prev_span self).1
    only = Stmt { expr = value, span = (start, end), leading = Vec::new (), trailing = None }
    Ok (Block { stmts = vec! \-> only, span = (start, end) })
  export(crate) opens_a_guard_list : &self -> bool
  opens_a_guard_list self = .check (&TokenKind::Newline) self && .is_some_and (\t -> t.kind == TokenKind::Indent) (.peek_at 1 self) && .is_some_and (\t -> t.kind == TokenKind::Or) (.peek_at 2 self)
  export(crate) guards : &mut self -> Result<Vec<Guard>, ParseError>
  guards self =
    mut rows = Vec::new ()
    loop
      .skip_separators self
      if !.check (&TokenKind::Or) self
        break
      start = (.peek_span self).0
      .advance self
      if .names_the_retired_catch_all self
        message = .to_string "`otherwise` is no longer the catch-all arm of a guard ladder"
        return Err (ParseError::with_help Code::RetiredSpelling message "write `_`, which is the same wildcard a `case` arm and a parameter pattern use. Row 99 wave 2 deleted the keyword: one spelling for one meaning" (.peek_span self))
      cond = if .is_wildcard self
        .advance self
        None
      else
        Some (ladder_condition self)?
      (.expect (&TokenKind::Eq) "expected `=` after a guard's condition" self)?
      body = (.inline_body self)?
      (.newline_with_trailing "expected a line break after a guard's body" self)?
      .push (Guard { condition = cond, body, span = (start, (.prev_span self).1) }) rows
    debug_assert! \-> !.is_empty rows \-> "`opens_a_guard_list` guarantees a first `|`"
    Ok rows
  export(crate) is_wildcard : &self -> bool
  is_wildcard self = case &(.peek self).kind of
    TokenKind::Ident text | text == "_" -> true
    _ -> false
  export(crate) names_the_retired_catch_all : &self -> bool
  names_the_retired_catch_all self =
    if !.is_some_and (\t -> t.kind == TokenKind::Eq) (.peek_at 1 self)
      return false
    case &(.peek self).kind of
      TokenKind::Ident text | text == "otherwise" -> true
      _ -> false
  export(crate) try_draw : &mut self -> Result<Option<Expr>, ParseError>
  try_draw self =
    if !.check (&TokenKind::Kw Keyword::With) self
      return Ok None
    start = (.peek_span self).0
    .advance self
    name = (.ident "expected a name after `with`" self)?
    (.expect (&TokenKind::Eq) "expected `=` after a `with` binder — doc 30 §3.3" self)?
    value = Box::new (parse_expr self 0)?
    Ok $ Some $ Expr::Draw { name, value, span = (start, (.prev_span self).1) }
  export(crate) try_binding : &mut self -> Result<Option<Binding>, ParseError>
  try_binding self =
    is_mut = .check (&TokenKind::Kw Keyword::Mut) self
    if !is_mut && !.looks_like_a_binding self
      return Ok None
    start = (.peek_span self).0
    if is_mut
      .advance self
    bound = (pattern_alt self)?
    ty = if .check (&TokenKind::Colon) self
      .advance self
      Some (.type_expr "expected a type after `:`" self)?
    else
      None
    (.expect (&TokenKind::Eq) "expected `=` in a binding" self)?
    value = (.value_or_ladder self)?
    fallback = (.else_tail self)?
    Ok $ Some $ Binding { pattern = bound, ty, value, is_mut, r#otherwise = fallback, span = (start, (.prev_span self).1) }
  export(crate) else_tail : &mut self -> Result<Option<Block>, ParseError>
  else_tail self =
    if !.check (&TokenKind::Kw Keyword::Else) self
      return Ok None
    .advance self
    if .check (&TokenKind::Newline) self
      return .map Some (.statement_block "expected an indented `else` body after the binding" self)
    start = (.peek_span self).0
    if .check (&TokenKind::Kw Keyword::Return) self
      .advance self
      value = if .at_statement_end self
        None
      else
        Some $ Box::new (parse_expr self 0)?
      return Ok (Some (.one_statement (Expr::Return { value, span = (start, (.prev_span self).1) }) start self))
    if (control_flow self)? is Some diverging
      return Ok (Some (.one_statement diverging start self))
    .map Some (.inline_body self)
  one_statement : Expr -> usize -> &self -> Block
  one_statement expr start self =
    end = (.prev_span self).1
    only = Stmt { expr, span = (start, end), leading = Vec::new (), trailing = None }
    Block { stmts = vec! \-> only, span = (start, end) }
  export(crate) value_or_ladder : &mut self -> Result<Expr, ParseError>
  value_or_ladder self =
    if !.opens_a_guard_list self
      return parse_expr self 0
    start = (.peek_span self).0
    .advance self
    .advance self
    rows = (.guards self)?
    (.expect (&TokenKind::Dedent) "expected the ladder to end" self)?
    Ok (Expr::Ladder { rows, span = (start, (.prev_span self).1) })
  looks_like_a_binding : &self -> bool
  looks_like_a_binding self = case &(.peek self).kind of
    TokenKind::Ident _ ->
      opener = if .peek_at 1 self is Some next
        case next.kind of
          TokenKind::Eq or TokenKind::Colon or TokenKind::LBrace -> true
          _ -> false
      else
        false
      (opener || .reaches_an_else_tail self) && .reaches_a_binding_eq self
    TokenKind::LParen or TokenKind::LBracket -> .reaches_a_binding_eq self
    _ -> false
  export(crate) reaches_an_else_tail : &self -> bool
  reaches_an_else_tail self =
    mut depth : i32 = 0
    mut i = 0
    mut past_eq = false
    while .peek_at i self is Some tok
      case &tok.kind of
        TokenKind::Eq | depth == 0 ->
          past_eq := true
        TokenKind::Kw (Keyword::Else) | depth == 0 && past_eq ->
          return true
        TokenKind::LParen or TokenKind::LBracket or TokenKind::LBrace -> depth += 1
        TokenKind::RParen or TokenKind::RBracket or TokenKind::RBrace ->
          depth -= 1
          if depth < 0
            return false
        TokenKind::Newline or TokenKind::Indent or TokenKind::Dedent or TokenKind::Eof ->
          return false
        _ -> ()
      i += 1
    false
  export(crate) reaches_a_binding_eq : &self -> bool
  reaches_a_binding_eq self =
    mut depth : i32 = 0
    mut i = 0
    while .peek_at i self is Some tok
      case &tok.kind of
        TokenKind::Eq | depth == 0 ->
          return true
        TokenKind::LParen or TokenKind::LBracket or TokenKind::LBrace -> depth += 1
        TokenKind::RParen or TokenKind::RBracket or TokenKind::RBrace ->
          depth -= 1
          if depth < 0
            return false
        TokenKind::Newline or TokenKind::Indent or TokenKind::Dedent or TokenKind::Eof ->
          return false
        _ -> ()
      i += 1
    false
  export(crate) type_expr : &str -> &mut self -> Result<TypeExpr, ParseError>
  type_expr message self = capture_type self message TypeStop::Greedy

  export(crate) peek : &self -> &'a Token
  peek self =
    .unwrap_or_else (\-> .expect "the token stream always contains at least Eof" (.last self.toks)) (.get self.pos self.toks)
  export(crate) peek_at : usize -> &self -> Option<&'a Token>
  peek_at n self = .get (self.pos + n) self.toks
  export(crate) peek_span : &self -> Span
  peek_span self = (.peek self).span
  export(crate) peek_leading : &self -> Vec<Trivia>
  peek_leading self = .clone (.peek self).leading
  export(crate) prev_span : &self -> Span
  prev_span self =
    if self.pos == 0
      return (0, 0)
    self.toks[self.pos - 1].span
  export(crate) at_eof : &self -> bool
  at_eof self = case (.peek self).kind of
    TokenKind::Eof -> true
    _ -> false
  export(crate) check : &TokenKind -> &self -> bool
  check kind self = &(.peek self).kind == kind
  export(crate) advance : &mut self -> ()
  advance self =
    if !.at_eof self
      self.pos += 1
    ()
  export(crate) expect : &TokenKind -> &str -> &mut self -> Result<(), ParseError>
  expect kind message self = .expect_with Code::ExpectedToken kind message self
  export(crate) expect_with : Code -> &TokenKind -> &str -> &mut self -> Result<(), ParseError>
  expect_with code kind message self =
    if .check kind self
      .advance self
      return Ok ()
    Err $ ParseError::r#with code message (.peek_span self)
  export(crate) eat_keyword : Keyword -> &mut self -> bool
  eat_keyword kw self =
    if .check (&TokenKind::Kw kw) self
      .advance self
      return true
    false
  export(crate) position : &self -> usize
  position self = self.pos
  export(crate) rewind : usize -> &mut self -> ()
  rewind mark self =
    self.pos := mark
    ()
  export(crate) try_ident : &mut self -> Option<Ident>
  try_ident self =
    if &(.peek self).kind is TokenKind::Ident text
      found = Ident { text = .clone text, span = .peek_span self }
      .advance self
      return Some found
    None
  export(crate) ident : &str -> &mut self -> Result<Ident, ParseError>
  ident message self =
    if &(.peek self).kind is TokenKind::Ident text
      found = Ident { text = .clone text, span = .peek_span self }
      .advance self
      return Ok found
    Err $ ParseError::r#with Code::ExpectedName message (.peek_span self)
  export(crate) newline_with_trailing : &str -> &mut self -> Result<Option<Trivia>, ParseError>
  newline_with_trailing message self =
    if .check (&TokenKind::Newline) self
      trailing = .clone (.peek self).trailing
      .advance self
      return Ok trailing
    if .at_eof self || .check (&TokenKind::Dedent) self || .just_dedented self
      return Ok None
    Err $ ParseError::expected message (.peek_span self)
  export(crate) just_dedented : &self -> bool
  just_dedented self =
    ((self.pos.checked_sub 1).and_then (\i -> .get i self.toks)).is_some_and (\t -> t.kind == TokenKind::Dedent)
  export(crate) skip_separators : &mut self -> ()
  skip_separators self =
    while .check (&TokenKind::Newline) self
      .advance self
    ()
  export(crate) skip_layout : &mut self -> ()
  skip_layout self =
    while .check (&TokenKind::Newline) self || .check (&TokenKind::Indent) self || .check (&TokenKind::Dedent) self
      .advance self
    ()
  eof_trivia : &self -> Vec<Trivia>
  eof_trivia self =
    guard .last self.toks is Some last else
      return Vec::new ()
    ends = case last.kind of
      TokenKind::Eof -> true
      _ -> false
    if !ends
      return Vec::new ()
    .clone last.leading
  recover_to_item : &mut self -> ()
  recover_to_item self =
    mut depth : usize = 0
    mut running = true
    while running
      case &(.peek self).kind of
        TokenKind::Eof -> running := false
        TokenKind::Indent ->
          depth += 1
          .advance self
        TokenKind::Dedent ->
          depth := .saturating_sub 1 depth
          .advance self
        TokenKind::Ident _ | depth == 0 -> running := false
        _ -> .advance self
    ()
  recover_to_stmt : &mut self -> ()
  recover_to_stmt self =
    mut depth : usize = 0
    mut running = true
    while running
      case &(.peek self).kind of
        TokenKind::Eof -> running := false
        TokenKind::Newline | depth == 0 ->
          .advance self
          running := false
        TokenKind::Dedent | depth == 0 -> running := false
        TokenKind::Indent ->
          depth += 1
          .advance self
        TokenKind::Dedent ->
          depth := .saturating_sub 1 depth
          .advance self
        _ -> .advance self
    ()