1use crate::ast::{Bound, Decl, Def, ExceptPath, Expr, LetInstance, Module, Param, QuantKind, Unit};
2use crate::error::{Error, Result};
3use crate::lexer::lex;
4use crate::token::{Kw, Op, Tok, Token};
5
6pub fn parse_module(src: &str) -> Result<Module> {
7 parse_module_bounded(src, DEFAULT_NESTING_LIMIT)
8}
9
10pub fn parse_module_bounded(src: &str, nesting_limit: usize) -> Result<Module> {
13 Parser::new(lex(src)?, nesting_limit).module()
14}
15
16pub fn parse_expression(src: &str) -> Result<Expr> {
19 parse_expression_bounded(src, DEFAULT_NESTING_LIMIT)
20}
21
22pub fn parse_expression_bounded(src: &str, nesting_limit: usize) -> Result<Expr> {
24 let mut p = Parser::new(lex(src)?, nesting_limit);
25 let e = p.expr(0)?;
26 if matches!(p.peek(), Tok::Eof) {
27 Ok(e)
28 } else {
29 Err(p.err(format!("unexpected {:?} after the expression", p.peek())))
30 }
31}
32
33pub const DEFAULT_NESTING_LIMIT: usize = 256;
49
50struct Parser {
51 toks: Vec<Token>,
52 pos: usize,
53 depth: usize,
54 nesting_limit: usize,
55 fences: Vec<u32>,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63enum Shape {
64 MapsTo { bounded: bool },
65 Colon { bounded: bool },
66 Arrow,
67 Except,
68 Closed,
69}
70
71impl Parser {
72 fn new(toks: Vec<Token>, nesting_limit: usize) -> Self {
73 Self {
74 toks,
75 pos: 0,
76 depth: 0,
77 nesting_limit,
78 fences: Vec::new(),
79 }
80 }
81
82 fn peek(&self) -> &Tok {
83 &self.toks[self.pos].tok
84 }
85
86 fn peek_at(&self, offset: usize) -> &Tok {
87 let i = (self.pos + offset).min(self.toks.len() - 1);
88 &self.toks[i].tok
89 }
90
91 fn col(&self) -> u32 {
92 self.toks[self.pos].col
93 }
94
95 fn advance(&mut self) -> Tok {
96 let t = self.toks[self.pos].tok.clone();
97 if self.pos + 1 < self.toks.len() {
98 self.pos += 1;
99 }
100 t
101 }
102
103 fn eat(&mut self, tok: &Tok) -> bool {
104 if self.peek() == tok {
105 self.advance();
106 true
107 } else {
108 false
109 }
110 }
111
112 fn expect(&mut self, tok: &Tok) -> Result<()> {
113 if self.eat(tok) {
114 Ok(())
115 } else {
116 Err(self.err(format!("expected {tok:?}, found {:?}", self.peek())))
117 }
118 }
119
120 fn expect_ident(&mut self) -> Result<String> {
121 let at = self.pos;
122 match self.advance() {
123 Tok::Ident(name) => Ok(name),
124 other => Err(self.err_at(at, format!("expected an identifier, found {other:?}"))),
125 }
126 }
127
128 fn err(&self, message: impl Into<String>) -> Error {
129 self.err_at(self.pos, message)
130 }
131
132 fn err_at(&self, at: usize, message: impl Into<String>) -> Error {
135 let t = &self.toks[at];
136 Error::parse(message, t.line, t.col)
137 }
138
139 fn fenced(&self) -> bool {
142 self.fences.last().is_some_and(|&f| self.col() <= f)
143 }
144
145 fn bracketed<T>(&mut self, f: impl FnOnce(&mut Self) -> Result<T>) -> Result<T> {
146 self.fences.push(0);
147 let out = f(self);
148 self.fences.pop();
149 out
150 }
151
152 fn module(&mut self) -> Result<Module> {
155 while !(matches!(self.peek(), Tok::Separator)
156 && matches!(self.peek_at(1), Tok::Kw(Kw::Module)))
157 {
158 if matches!(self.peek(), Tok::Eof) {
159 return Err(self.err("no `---- MODULE ----` header found"));
160 }
161 self.advance();
162 }
163 self.advance();
164 self.module_body()
165 }
166
167 fn module_body(&mut self) -> Result<Module> {
170 self.expect(&Tok::Kw(Kw::Module))?;
171 let name = self.expect_ident()?;
172 self.expect(&Tok::Separator)?;
173
174 let mut extends = Vec::new();
175 let mut units = Vec::new();
176 loop {
177 while self.eat(&Tok::Separator) {}
178 match self.peek() {
179 Tok::ModuleEnd | Tok::Eof => break,
180 Tok::Kw(Kw::Module) => {
181 let inner = self.module_body()?;
182 self.expect(&Tok::ModuleEnd)?;
183 units.push(Unit::Inner(Box::new(inner)));
184 }
185 Tok::Kw(Kw::Extends) => {
186 self.advance();
187 extends.push(self.expect_ident()?);
188 while self.eat(&Tok::Comma) {
189 extends.push(self.expect_ident()?);
190 }
191 }
192 _ => {
193 let before = self.pos;
197 let unit = self.unit_body()?;
198 if self.pos == before {
199 return Err(self.err(format!(
200 "cannot make sense of {:?}, and cannot get past it",
201 self.peek()
202 )));
203 }
204 units.push(unit);
205 }
206 }
207 }
208 Ok(Module {
209 name,
210 extends,
211 units,
212 })
213 }
214
215 fn unit_body(&mut self) -> Result<Unit> {
216 if self.at_proof() {
217 self.skip_proof();
218 return Ok(Unit::Opaque);
219 }
220 let local = self.eat(&Tok::Kw(Kw::Local));
221 match self.peek().clone() {
222 Tok::Kw(Kw::Constant) => {
223 self.advance();
224 Ok(Unit::Constants(self.decl_list()?))
225 }
226 Tok::Kw(Kw::Recursive) => {
227 self.advance();
228 Ok(Unit::Recursive(self.decl_list()?))
229 }
230 Tok::Kw(Kw::Variable) => {
231 self.advance();
232 let mut names = vec![self.expect_ident()?];
233 while self.eat(&Tok::Comma) {
234 names.push(self.expect_ident()?);
235 }
236 Ok(Unit::Variables(names))
237 }
238 Tok::Kw(Kw::Assume) => {
239 self.advance();
240 self.skip_label();
241 match self.recover(|p| p.expr(0)) {
242 Some(e) => Ok(Unit::Assume(e)),
243 None => Ok(Unit::Opaque),
244 }
245 }
246 Tok::Kw(Kw::Theorem) => {
247 self.advance();
248 self.skip_label();
249 let statement = self.recover(|p| p.expr(0));
250 self.skip_proof();
251 match statement {
252 Some(e) => Ok(Unit::Theorem(e)),
253 None => Ok(Unit::Opaque),
254 }
255 }
256 Tok::Kw(Kw::Proof) => {
257 self.skip_proof();
258 Ok(Unit::Opaque)
259 }
260 Tok::Kw(Kw::Instance) => {
261 let (module, subs) = self.instance_tail()?;
262 Ok(Unit::Instance {
263 name: None,
264 module,
265 subs,
266 })
267 }
268 Tok::Op(op) => {
271 self.advance();
272 self.eat(&Tok::Dot);
273 let operand = self.param()?;
274 self.expect(&Tok::DefEq)?;
275 Ok(Unit::Def(Def {
276 name: op.symbol().to_string(),
277 params: vec![operand],
278 body: self.expr(0)?,
279 local,
280 }))
281 }
282 Tok::Ident(name) => self.named_definition(name, local),
283 Tok::Kw(kw) if matches!(self.peek_at(1), Tok::DefEq) && kw.text().is_some() => {
286 let name = kw.text().expect("checked").to_string();
287 self.named_definition(name, local)
288 }
289 other => Err(self.err(format!("expected a declaration, found {other:?}"))),
290 }
291 }
292
293 fn named_definition(&mut self, name: String, local: bool) -> Result<Unit> {
297 self.advance();
298
299 if let Tok::Op(op) = self.peek().clone() {
300 self.advance();
301 let left = Param::value(name);
302 let params = if self.eat(&Tok::DefEq) {
303 vec![left]
304 } else {
305 let right = self.param()?;
306 self.expect(&Tok::DefEq)?;
307 vec![left, right]
308 };
309 return Ok(Unit::Def(Def {
310 name: op.symbol().to_string(),
311 params,
312 body: self.expr(0)?,
313 local,
314 }));
315 }
316
317 if matches!(self.peek(), Tok::LBrack) {
319 self.advance();
320 let bounds = self.bracketed(|p| p.bounds(&Tok::RBrack))?;
321 self.expect(&Tok::RBrack)?;
322 self.expect(&Tok::DefEq)?;
323 let body = self.expr(0)?;
324 return Ok(Unit::Def(Def {
325 name,
326 params: Vec::new(),
327 body: Expr::FnDef {
328 bounds,
329 body: Box::new(body),
330 },
331 local,
332 }));
333 }
334
335 let params = self.opt_params()?;
336 self.expect(&Tok::DefEq)?;
337 if matches!(self.peek(), Tok::Kw(Kw::Instance)) {
338 let (module, subs) = self.instance_tail()?;
339 return Ok(Unit::Instance {
340 name: Some(name),
341 module,
342 subs,
343 });
344 }
345 Ok(Unit::Def(Def {
346 name,
347 params,
348 body: self.expr(0)?,
349 local,
350 }))
351 }
352
353 fn skip_label(&mut self) {
356 if matches!(self.peek(), Tok::Ident(_)) && matches!(self.peek_at(1), Tok::DefEq) {
357 self.advance();
358 self.advance();
359 }
360 }
361
362 fn recover<T>(&mut self, f: impl FnOnce(&mut Self) -> Result<T>) -> Option<T> {
364 let mark = self.pos;
365 let fences = self.fences.len();
366 let depth = self.depth;
367 let Ok(value) = f(self) else {
368 self.pos = mark;
369 self.fences.truncate(fences);
370 self.depth = depth;
371 self.skip_to_unit();
372 return None;
373 };
374 Some(value)
375 }
376
377 fn skip_proof(&mut self) {
383 if !self.at_proof() {
384 return;
385 }
386 self.advance();
390 while !matches!(self.peek(), Tok::Eof | Tok::ModuleEnd | Tok::Separator) {
391 if self.at_unit_start() {
392 return;
393 }
394 self.advance();
395 }
396 }
397
398 fn skip_to_unit(&mut self) {
400 self.advance();
401 while !matches!(self.peek(), Tok::Eof | Tok::ModuleEnd | Tok::Separator) {
402 if self.at_unit_start() {
403 return;
404 }
405 self.advance();
406 }
407 }
408
409 fn at_unit_start_after(&self, ahead: usize) -> bool {
412 self.toks.get(self.pos + ahead).is_some_and(|t| t.col == 1)
413 }
414
415 fn at_proof(&self) -> bool {
416 if matches!(self.peek(), Tok::Kw(Kw::Proof)) {
417 return true;
418 }
419 self.begins_line()
423 && matches!(self.peek(), Tok::Op(Op::Lt))
424 && matches!(self.peek_at(2), Tok::Op(Op::Gt))
425 }
426
427 fn begins_line(&self) -> bool {
428 self.pos == 0 || self.toks[self.pos - 1].line < self.toks[self.pos].line
429 }
430
431 fn at_unit_start(&self) -> bool {
434 if self.col() != 1 {
435 return false;
436 }
437 match self.peek() {
438 Tok::Kw(
439 Kw::Variable
440 | Kw::Constant
441 | Kw::Assume
442 | Kw::Theorem
443 | Kw::Local
444 | Kw::Instance
445 | Kw::Recursive
446 | Kw::Extends,
447 ) => true,
448 Tok::Ident(_) | Tok::Op(_) => self.at_definition(),
449 _ => false,
450 }
451 }
452
453 fn at_definition(&self) -> bool {
467 let defeq = |offset: usize| matches!(self.peek_at(offset), Tok::DefEq);
468 if matches!(self.peek(), Tok::Ident(_)) {
469 return match self.peek_at(1) {
470 Tok::DefEq | Tok::LParen | Tok::LBrack => true,
473 Tok::Op(_) => defeq(2) || (matches!(self.peek_at(2), Tok::Ident(_)) && defeq(3)),
476 _ => false,
477 };
478 }
479 let after = usize::from(matches!(self.peek_at(1), Tok::Dot)) + 1;
482 matches!(self.peek_at(after), Tok::Ident(_) | Tok::Underscore) && defeq(after + 1)
483 }
484
485 fn decl_list(&mut self) -> Result<Vec<Decl>> {
486 let mut out = vec![self.decl()?];
487 while self.eat(&Tok::Comma) {
488 out.push(self.decl()?);
489 }
490 Ok(out)
491 }
492
493 fn decl(&mut self) -> Result<Decl> {
494 if let Some(param) = self.fixity_declaration() {
495 return Ok(Decl {
496 name: param.name,
497 arity: param.arity,
498 });
499 }
500 let name = self.expect_ident()?;
501 let mut arity = 0;
502 if self.eat(&Tok::LParen) {
503 loop {
504 if !self.eat(&Tok::Underscore) {
505 self.expect_ident()?;
506 }
507 arity += 1;
508 if !self.eat(&Tok::Comma) {
509 break;
510 }
511 }
512 self.expect(&Tok::RParen)?;
513 }
514 Ok(Decl { name, arity })
515 }
516
517 fn opt_params(&mut self) -> Result<Vec<Param>> {
518 let mut params = Vec::new();
519 if self.eat(&Tok::LParen) {
520 loop {
521 params.push(self.param()?);
522 if !self.eat(&Tok::Comma) {
523 break;
524 }
525 }
526 self.expect(&Tok::RParen)?;
527 }
528 Ok(params)
529 }
530
531 fn fixity_declaration(&mut self) -> Option<Param> {
535 let mark = self.pos;
536 if matches!(self.peek(), Tok::Underscore)
538 && let Tok::Op(op) = *self.peek_at(1)
539 {
540 self.advance();
541 self.advance();
542 let arity = if self.eat(&Tok::Underscore) { 2 } else { 1 };
543 return Some(Param {
544 name: op.symbol().to_string(),
545 arity,
546 });
547 }
548 if let Tok::Op(op) = *self.peek() {
550 self.advance();
551 self.eat(&Tok::Dot);
552 if self.eat(&Tok::Underscore) {
553 return Some(Param {
554 name: op.symbol().to_string(),
555 arity: 1,
556 });
557 }
558 self.pos = mark;
559 }
560 None
561 }
562
563 fn param(&mut self) -> Result<Param> {
566 if let Some(operator) = self.fixity_declaration() {
567 return Ok(operator);
568 }
569 let name = self.expect_ident()?;
570 let mut arity = 0;
571 if self.eat(&Tok::LParen) {
572 loop {
573 if !self.eat(&Tok::Underscore) {
574 self.expect_ident()?;
575 }
576 arity += 1;
577 if !self.eat(&Tok::Comma) {
578 break;
579 }
580 }
581 self.expect(&Tok::RParen)?;
582 }
583 Ok(Param { name, arity })
584 }
585
586 fn instance_tail(&mut self) -> Result<(String, Vec<(String, Expr)>)> {
587 self.expect(&Tok::Kw(Kw::Instance))?;
588 let module = self.expect_ident()?;
589 let mut subs = Vec::new();
590 if self.eat(&Tok::Kw(Kw::With)) {
591 loop {
592 let name = self.expect_ident()?;
593 self.expect(&Tok::Gets)?;
594 let replacement = if matches!(self.peek_at(1), Tok::Comma | Tok::Eof)
595 || self.at_unit_start_after(1)
596 {
597 self.operator_by_symbol()
598 } else {
599 None
600 };
601 match replacement {
602 Some(operator) => subs.push((name, operator)),
603 None => subs.push((name, self.expr(0)?)),
604 }
605 if !self.eat(&Tok::Comma) {
606 break;
607 }
608 }
609 }
610 Ok((module, subs))
611 }
612
613 fn expr(&mut self, min_prec: u8) -> Result<Expr> {
616 if self.depth >= self.nesting_limit {
617 let limit = self.nesting_limit;
618 return Err(self.err(format!("expressions nest more than {limit} deep")));
619 }
620 self.depth += 1;
621 let parsed = self.expr_inner(min_prec);
622 self.depth -= 1;
623 parsed
624 }
625
626 fn expr_inner(&mut self, min_prec: u8) -> Result<Expr> {
627 let mut lhs = match *self.peek() {
635 Tok::Op(op @ (Op::And | Op::Or)) => self.junction(op)?,
636 _ => self.prefix()?,
637 };
638 loop {
639 if self.fenced() || self.at_unit_start() || self.at_proof() {
640 break;
641 }
642 let Tok::Op(op) = *self.peek() else { break };
643 let Some(prec) = op.infix_prec() else { break };
644 if prec < min_prec {
645 break;
646 }
647 self.advance();
648 let next_min = if op.is_right_assoc() { prec } else { prec + 1 };
649 let rhs = self.expr(next_min)?;
650 lhs = Expr::Binary(op, Box::new(lhs), Box::new(rhs));
651 }
652 Ok(lhs)
653 }
654
655 fn junction(&mut self, op: Op) -> Result<Expr> {
657 let col = self.col();
658 self.fences.push(col);
659 let mut items = Vec::new();
660 while *self.peek() == Tok::Op(op) && self.col() == col {
661 self.advance();
662 items.push(self.expr(0)?);
663 }
664 self.fences.pop();
665 Ok(if op == Op::And {
666 Expr::conjunction(items)
667 } else {
668 Expr::disjunction(items)
669 })
670 }
671
672 fn prefix(&mut self) -> Result<Expr> {
673 if let Some(labelled) = self.skip_expression_label() {
674 return labelled;
675 }
676 let op = match *self.peek() {
677 Tok::Op(o @ (Op::Forall | Op::Exists | Op::TemporalForall | Op::TemporalExists)) => {
678 self.advance();
679 let kind = match o {
680 Op::Forall => QuantKind::Forall,
681 Op::Exists => QuantKind::Exists,
682 Op::TemporalForall => QuantKind::TemporalForall,
683 _ => QuantKind::TemporalExists,
684 };
685 let bounds = self.bounds(&Tok::Colon)?;
686 self.expect(&Tok::Colon)?;
687 let body = self.expr(0)?;
688 return Ok(Expr::Quant {
689 kind,
690 bounds,
691 body: Box::new(body),
692 });
693 }
694 Tok::Op(o @ (Op::Not | Op::Always | Op::Eventually | Op::Minus)) => o,
695 Tok::Kw(Kw::Domain) => Op::Domain,
696 Tok::Kw(Kw::Subset) => Op::Subset,
697 Tok::Kw(Kw::Union) => Op::BigUnion,
698 Tok::Kw(Kw::Enabled) => Op::Enabled,
699 Tok::Kw(Kw::Unchanged) => Op::Unchanged,
700 _ => return self.postfix(),
701 };
702 self.advance();
703 let operand_prec = match op {
706 Op::Minus => 11,
707 Op::Domain | Op::Subset | Op::BigUnion => 9,
708 _ => 5,
709 };
710 let operand = self.expr(operand_prec)?;
711 Ok(Expr::Unary(op, Box::new(operand)))
712 }
713
714 fn skip_expression_label(&mut self) -> Option<Result<Expr>> {
717 if !matches!(self.peek(), Tok::Ident(_)) {
718 return None;
719 }
720 let mut ahead = 1;
721 if matches!(self.peek_at(1), Tok::LParen) {
722 let mut depth = 0usize;
723 loop {
724 match self.peek_at(ahead) {
725 Tok::LParen => depth += 1,
726 Tok::RParen => {
727 depth -= 1;
728 if depth == 0 {
729 ahead += 1;
730 break;
731 }
732 }
733 Tok::Eof => return None,
734 _ => {}
735 }
736 ahead += 1;
737 }
738 }
739 if !matches!(self.peek_at(ahead), Tok::ColonColon) {
740 return None;
741 }
742 for _ in 0..=ahead {
743 self.advance();
744 }
745 Some(self.expr(0))
746 }
747
748 fn postfix(&mut self) -> Result<Expr> {
749 let e = self.primary()?;
750 self.continue_postfix(e)
751 }
752
753 fn continue_postfix(&mut self, head: Expr) -> Result<Expr> {
754 let mut e = head;
755 loop {
756 if self.fenced() || self.at_unit_start() {
757 break;
758 }
759 match self.peek() {
760 Tok::Prime => {
761 self.advance();
762 e = Expr::Prime(Box::new(e));
763 }
764 Tok::Op(op) if op.is_postfix() => {
765 let op = *op;
766 self.advance();
767 e = Expr::Unary(op, Box::new(e));
768 }
769 Tok::Dot => {
770 self.advance();
771 e = Expr::Field(Box::new(e), self.expect_ident()?);
772 }
773 Tok::LBrack => {
774 self.advance();
775 let args = self.bracketed(|p| p.expr_list(&Tok::RBrack))?;
776 self.expect(&Tok::RBrack)?;
777 e = Expr::FnApply(Box::new(e), args);
778 }
779 Tok::LParen if matches!(e, Expr::Ident(_)) => {
780 self.advance();
781 let args = self.bracketed(|p| p.expr_list(&Tok::RParen))?;
782 self.expect(&Tok::RParen)?;
783 e = Expr::Apply(Box::new(e), args);
784 }
785 Tok::Bang => {
786 let instance = match &e {
787 Expr::Ident(name) => name.clone(),
788 Expr::Qualified { instance, name, .. } => format!("{instance}!{name}"),
789 Expr::Apply(head, _) => head.to_string(),
790 _ => return Err(self.err("`!` must follow an instance name")),
791 };
792 self.advance();
793 let name = match self.peek().clone() {
798 Tok::Num(n) => {
799 self.advance();
800 n.to_string()
801 }
802 Tok::Op(op) => {
803 self.advance();
804 op.symbol().to_string()
805 }
806 Tok::At => {
807 self.advance();
808 "@".to_string()
809 }
810 Tok::LTup => {
811 self.advance();
812 "<<".to_string()
813 }
814 Tok::RTup => {
815 self.advance();
816 ">>".to_string()
817 }
818 Tok::Colon => {
819 self.advance();
820 String::new()
821 }
822 _ => self.expect_ident()?,
823 };
824 let mut args = Vec::new();
825 if self.eat(&Tok::LParen) {
826 args = self.bracketed(|p| p.expr_list(&Tok::RParen))?;
827 self.expect(&Tok::RParen)?;
828 }
829 e = Expr::Qualified {
830 instance,
831 name,
832 args,
833 };
834 }
835 _ => break,
836 }
837 }
838 Ok(e)
839 }
840
841 fn expr_list(&mut self, close: &Tok) -> Result<Vec<Expr>> {
842 let mut out = Vec::new();
843 if self.peek() == close {
844 return Ok(out);
845 }
846 loop {
847 if (matches!(self.peek_at(1), Tok::Comma) || self.peek_at(1) == close)
851 && let Some(operator) = self.operator_by_symbol()
852 {
853 out.push(operator);
854 if !self.eat(&Tok::Comma) {
855 return Ok(out);
856 }
857 continue;
858 }
859 out.push(self.expr(0)?);
860 if !self.eat(&Tok::Comma) {
861 return Ok(out);
862 }
863 }
864 }
865
866 fn operator_by_symbol(&mut self) -> Option<Expr> {
868 let symbol = match self.peek() {
869 Tok::Op(op) => op.symbol(),
870 Tok::Prime => "'",
871 Tok::Kw(Kw::Enabled) => "ENABLED",
872 Tok::Kw(Kw::Unchanged) => "UNCHANGED",
873 Tok::Kw(Kw::Domain) => "DOMAIN",
874 Tok::Kw(Kw::Subset) => "SUBSET",
875 Tok::Kw(Kw::Union) => "UNION",
876 _ => return None,
877 };
878 self.advance();
879 Some(Expr::Ident(symbol.to_string()))
880 }
881
882 fn primary(&mut self) -> Result<Expr> {
883 let at = self.pos;
884 match self.advance() {
885 Tok::Num(n) => Ok(Expr::Num(n)),
886 Tok::Decimal(text) => Ok(Expr::Decimal(text)),
887 Tok::Str(s) => Ok(Expr::Str(s)),
888 Tok::Kw(Kw::True) => Ok(Expr::Bool(true)),
889 Tok::Kw(Kw::False) => Ok(Expr::Bool(false)),
890 Tok::Ident(name) => Ok(Expr::Ident(name)),
891 Tok::At => Ok(Expr::At),
892 Tok::LParen => {
893 let e = self.bracketed(|p| p.expr(0))?;
894 self.expect(&Tok::RParen)?;
895 Ok(e)
896 }
897 Tok::LTup => self.tuple_or_action(),
898 Tok::LBrace => self.brace_form(),
899 Tok::LBrack => self.bracket_form(),
900 Tok::Kw(Kw::If) => {
901 let cond = self.expr(0)?;
902 self.expect(&Tok::Kw(Kw::Then))?;
903 let then = self.expr(0)?;
904 self.expect(&Tok::Kw(Kw::Else))?;
905 let otherwise = self.expr(0)?;
906 Ok(Expr::If {
907 cond: Box::new(cond),
908 then: Box::new(then),
909 otherwise: Box::new(otherwise),
910 })
911 }
912 Tok::Kw(Kw::Let) => self.let_form(),
913 Tok::Kw(Kw::Choose) => {
914 let mut bounds = self.bounds(&Tok::Colon)?;
915 self.expect(&Tok::Colon)?;
916 let body = self.expr(0)?;
917 if bounds.len() != 1 {
918 return Err(self.err("CHOOSE takes exactly one bound variable"));
919 }
920 Ok(Expr::Choose {
921 bound: Box::new(bounds.remove(0)),
922 body: Box::new(body),
923 })
924 }
925 Tok::Kw(Kw::Case) => self.case_form(),
926 Tok::Kw(Kw::Lambda) => {
927 let mut params = vec![self.param()?];
928 while self.eat(&Tok::Comma) {
929 params.push(self.param()?);
930 }
931 self.expect(&Tok::Colon)?;
932 Ok(Expr::Lambda {
933 params,
934 body: Box::new(self.expr(0)?),
935 })
936 }
937 Tok::Fair { strong, subscript } => {
940 let subscript = if subscript.is_empty() {
941 self.postfix()?
942 } else {
943 Expr::Ident(subscript)
944 };
945 self.expect(&Tok::LParen)?;
946 let action = self.bracketed(|p| p.expr(0))?;
947 self.expect(&Tok::RParen)?;
948 Ok(Expr::Fairness {
949 strong,
950 subscript: Box::new(subscript),
951 action: Box::new(action),
952 })
953 }
954 other => Err(self.err_at(at, format!("expected an expression, found {other:?}"))),
955 }
956 }
957
958 fn let_form(&mut self) -> Result<Expr> {
959 let mut defs = Vec::new();
960 let mut instances = Vec::new();
961 while !matches!(self.peek(), Tok::Kw(Kw::In)) {
962 if self.eat(&Tok::Kw(Kw::Recursive)) {
963 self.decl_list()?;
964 continue;
965 }
966 if matches!(self.peek(), Tok::Kw(Kw::Instance)) {
967 let (module, subs) = self.instance_tail()?;
968 instances.push(LetInstance {
969 name: None,
970 module,
971 subs,
972 });
973 continue;
974 }
975 let Tok::Ident(name) = self.peek().clone() else {
976 return Err(self.err("expected a definition inside LET"));
977 };
978 match self.named_definition(name, false)? {
979 Unit::Def(def) => defs.push(def),
980 Unit::Instance { name, module, subs } => {
981 instances.push(LetInstance { name, module, subs });
982 }
983 _ => return Err(self.err("only definitions may appear inside LET")),
984 }
985 }
986 self.advance();
987 let body = self.expr(0)?;
988 Ok(Expr::Let {
989 defs,
990 instances,
991 body: Box::new(body),
992 })
993 }
994
995 fn case_form(&mut self) -> Result<Expr> {
996 let mut arms = Vec::new();
997 let mut other = None;
998 loop {
999 if self.eat(&Tok::Kw(Kw::Other)) {
1000 self.expect(&Tok::Arrow)?;
1001 other = Some(Box::new(self.expr(0)?));
1002 } else {
1003 let guard = self.expr(0)?;
1004 self.expect(&Tok::Arrow)?;
1005 arms.push((guard, self.expr(0)?));
1006 }
1007 if other.is_some() || !self.eat(&Tok::Op(Op::Always)) {
1008 return Ok(Expr::Case { arms, other });
1009 }
1010 }
1011 }
1012
1013 fn tuple_or_action(&mut self) -> Result<Expr> {
1014 let items = self.bracketed(|p| p.expr_list(&Tok::RTup))?;
1015 self.expect(&Tok::RTup)?;
1016 if self.at_subscript() {
1017 if items.len() != 1 {
1018 return Err(self.err("`<<A>>_v` takes a single action"));
1019 }
1020 let subscript = self.subscript()?;
1021 return Ok(Expr::ActionAngle {
1022 action: Box::new(items.into_iter().next().expect("length checked")),
1023 subscript: Box::new(subscript),
1024 });
1025 }
1026 Ok(Expr::Tuple(items))
1027 }
1028
1029 fn at_subscript(&self) -> bool {
1032 match self.peek() {
1033 Tok::Underscore => true,
1034 Tok::Ident(name) => name.starts_with('_'),
1035 _ => false,
1036 }
1037 }
1038
1039 fn subscript(&mut self) -> Result<Expr> {
1041 if let Tok::Ident(name) = self.peek()
1042 && let Some(rest) = name.strip_prefix('_')
1043 && !rest.is_empty()
1044 {
1045 let head = Expr::Ident(rest.to_string());
1046 self.advance();
1047 return self.continue_postfix(head);
1050 }
1051 self.expect(&Tok::Underscore)?;
1052 self.postfix()
1053 }
1054
1055 fn brace_form(&mut self) -> Result<Expr> {
1060 if self.eat(&Tok::RBrace) {
1061 return Ok(Expr::SetEnum(Vec::new()));
1062 }
1063 self.bracketed(|p| {
1064 let first = p.expr(0)?;
1065 if p.eat(&Tok::Colon) {
1066 if let Some(bound) = as_bound(&first) {
1067 let pred = p.expr(0)?;
1068 p.expect(&Tok::RBrace)?;
1069 return Ok(Expr::SetFilter {
1070 bound: Box::new(bound),
1071 pred: Box::new(pred),
1072 });
1073 }
1074 let bounds = p.bounds(&Tok::RBrace)?;
1075 p.expect(&Tok::RBrace)?;
1076 return Ok(Expr::SetMap {
1077 expr: Box::new(first),
1078 bounds,
1079 });
1080 }
1081 let mut items = vec![first];
1082 while p.eat(&Tok::Comma) {
1083 items.push(p.expr(0)?);
1084 }
1085 p.expect(&Tok::RBrace)?;
1086 Ok(Expr::SetEnum(items))
1087 })
1088 }
1089
1090 fn bracket_form(&mut self) -> Result<Expr> {
1091 let shape = if self.subscript_follows_bracket() {
1092 Shape::Closed
1093 } else {
1094 self.shape()
1095 };
1096 let inner = self.bracketed(|p| match shape {
1097 Shape::MapsTo { bounded: true } => {
1098 let bounds = p.bounds(&Tok::MapsTo)?;
1099 p.expect(&Tok::MapsTo)?;
1100 let body = p.expr(0)?;
1101 p.expect(&Tok::RBrack)?;
1102 Ok(Expr::FnDef {
1103 bounds,
1104 body: Box::new(body),
1105 })
1106 }
1107 Shape::MapsTo { bounded: false } => {
1108 let fields = p.field_list(&Tok::MapsTo)?;
1109 p.expect(&Tok::RBrack)?;
1110 Ok(Expr::Record(fields))
1111 }
1112 Shape::Colon { .. } => {
1113 let fields = p.field_list(&Tok::Colon)?;
1114 p.expect(&Tok::RBrack)?;
1115 Ok(Expr::RecordSet(fields))
1116 }
1117 Shape::Arrow => {
1118 let domain = p.expr(0)?;
1119 p.expect(&Tok::Arrow)?;
1120 let range = p.expr(0)?;
1121 p.expect(&Tok::RBrack)?;
1122 Ok(Expr::FnSet {
1123 domain: Box::new(domain),
1124 range: Box::new(range),
1125 })
1126 }
1127 Shape::Except => {
1128 let base = p.expr(0)?;
1129 p.expect(&Tok::Kw(Kw::Except))?;
1130 let updates = p.except_updates()?;
1131 p.expect(&Tok::RBrack)?;
1132 Ok(Expr::Except {
1133 base: Box::new(base),
1134 updates,
1135 })
1136 }
1137 Shape::Closed => {
1138 let action = p.expr(0)?;
1139 p.expect(&Tok::RBrack)?;
1140 Ok(action)
1141 }
1142 })?;
1143 if shape != Shape::Closed {
1144 return Ok(inner);
1145 }
1146 let subscript = self.subscript()?;
1147 Ok(Expr::ActionBox {
1148 action: Box::new(inner),
1149 subscript: Box::new(subscript),
1150 })
1151 }
1152
1153 fn field_list(&mut self, sep: &Tok) -> Result<Vec<(String, Expr)>> {
1154 let mut out = Vec::new();
1155 loop {
1156 let name = self.expect_ident()?;
1157 self.expect(sep)?;
1158 out.push((name, self.expr(0)?));
1159 if !self.eat(&Tok::Comma) {
1160 return Ok(out);
1161 }
1162 }
1163 }
1164
1165 fn except_updates(&mut self) -> Result<Vec<(Vec<ExceptPath>, Expr)>> {
1166 let mut out = Vec::new();
1167 loop {
1168 self.expect(&Tok::Bang)?;
1169 let mut path = Vec::new();
1170 loop {
1171 if self.eat(&Tok::LBrack) {
1172 let indices = self.bracketed(|p| p.expr_list(&Tok::RBrack))?;
1173 self.expect(&Tok::RBrack)?;
1174 path.push(ExceptPath::Index(if indices.len() == 1 {
1175 indices.into_iter().next().expect("length checked")
1176 } else {
1177 Expr::Tuple(indices)
1178 }));
1179 } else if self.eat(&Tok::Dot) {
1180 path.push(ExceptPath::Field(self.expect_ident()?));
1181 } else {
1182 break;
1183 }
1184 }
1185 if path.is_empty() {
1186 return Err(self.err("EXCEPT update needs a `[...]` or `.field` path"));
1187 }
1188 self.expect(&Tok::Op(Op::Eq))?;
1189 out.push((path, self.expr(0)?));
1190 if !self.eat(&Tok::Comma) {
1191 return Ok(out);
1192 }
1193 }
1194 }
1195
1196 fn bounds(&mut self, terminator: &Tok) -> Result<Vec<Bound>> {
1197 let mut out = Vec::new();
1198 loop {
1199 let mut destructure = false;
1200 let mut names = Vec::new();
1201 if self.eat(&Tok::LTup) {
1202 destructure = true;
1203 loop {
1204 names.push(self.expect_ident()?);
1205 if !self.eat(&Tok::Comma) {
1206 break;
1207 }
1208 }
1209 self.expect(&Tok::RTup)?;
1210 } else {
1211 names.push(self.expect_ident()?);
1212 while *self.peek() == Tok::Comma && matches!(self.peek_at(1), Tok::Ident(_)) {
1213 self.advance();
1214 names.push(self.expect_ident()?);
1215 }
1216 }
1217 let domain = if self.eat(&Tok::Op(Op::In)) {
1218 Some(self.expr(0)?)
1219 } else {
1220 None
1221 };
1222 out.push(Bound {
1223 names,
1224 domain,
1225 destructure,
1226 });
1227 if self.peek() == terminator || !self.eat(&Tok::Comma) {
1228 return Ok(out);
1229 }
1230 }
1231 }
1232
1233 fn subscript_follows_bracket(&self) -> bool {
1237 let mut depth = 0usize;
1238 for (offset, t) in self.toks[self.pos..].iter().enumerate() {
1239 match &t.tok {
1240 Tok::LParen | Tok::LBrack | Tok::LBrace | Tok::LTup => depth += 1,
1241 Tok::RBrack if depth == 0 => {
1242 return match &self.peek_at(offset + 1) {
1243 Tok::Underscore => true,
1244 Tok::Ident(name) => name.starts_with('_'),
1245 _ => false,
1246 };
1247 }
1248 Tok::RParen | Tok::RBrack | Tok::RBrace | Tok::RTup => {
1249 if depth == 0 {
1250 return false;
1251 }
1252 depth -= 1;
1253 }
1254 Tok::Eof => return false,
1255 _ => {}
1256 }
1257 }
1258 false
1259 }
1260
1261 fn shape(&self) -> Shape {
1264 let mut depth = 0usize;
1265 let mut saw_in = false;
1266 for t in &self.toks[self.pos..] {
1267 match &t.tok {
1268 Tok::LParen | Tok::LBrack | Tok::LBrace | Tok::LTup => depth += 1,
1269 Tok::RParen | Tok::RBrack | Tok::RBrace | Tok::RTup => {
1270 if depth == 0 {
1271 return Shape::Closed;
1272 }
1273 depth -= 1;
1274 }
1275 Tok::Eof => break,
1276 _ if depth > 0 => {}
1277 Tok::Op(Op::In) => saw_in = true,
1278 Tok::MapsTo => return Shape::MapsTo { bounded: saw_in },
1279 Tok::Colon => return Shape::Colon { bounded: saw_in },
1280 Tok::Arrow => return Shape::Arrow,
1281 Tok::Kw(Kw::Except) => return Shape::Except,
1282 _ => {}
1283 }
1284 }
1285 Shape::Closed
1286 }
1287}
1288
1289fn as_bound(e: &Expr) -> Option<Bound> {
1292 let Expr::Binary(Op::In, lhs, domain) = e else {
1293 return None;
1294 };
1295 let (names, destructure) = match &**lhs {
1296 Expr::Ident(name) => (vec![name.clone()], false),
1297 Expr::Tuple(items) => {
1298 let mut names = Vec::with_capacity(items.len());
1299 for item in items {
1300 let Expr::Ident(name) = item else {
1301 return None;
1302 };
1303 names.push(name.clone());
1304 }
1305 (names, true)
1306 }
1307 _ => return None,
1308 };
1309 Some(Bound {
1310 names,
1311 domain: Some((**domain).clone()),
1312 destructure,
1313 })
1314}