diff --git a/src/fun/parser.rs b/src/fun/parser.rs index ab3f0f34..747f0219 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -451,7 +451,39 @@ impl<'a> TermParser<'a> { // Switch if self.try_parse_keyword("switch") { unexpected_tag(self)?; - return self.parse_switch(); + let (bnd, arg, with) = self.parse_match_header()?; + + self.consume("{")?; + self.try_consume("|"); + self.consume("0")?; + self.consume(":")?; + let zero = self.parse_term()?; + self.try_consume(";"); + + let mut arms = vec![zero]; + let mut expected_num = 1; + loop { + self.try_consume("|"); + // case _ + if self.try_consume("_") { + self.consume(":")?; + arms.push(self.parse_term()?); + self.try_consume(";"); + self.consume("}")?; + break; + } + // case num + let val = self.parse_u32()?; + if val != expected_num { + return self.expected(&format!("'{}'", &expected_num.to_string())); + } + expected_num += 1; + self.consume(":")?; + arms.push(self.parse_term()?); + self.try_consume(";"); + } + let pred = Some(Name::new(format!("{}-{}", bnd.as_ref().unwrap(), arms.len() - 1))); + return Ok(Term::Swt { arg: Box::new(arg), bnd, with, pred, arms }); } // Do (monadic block) @@ -612,44 +644,6 @@ impl<'a> TermParser<'a> { let bod = self.parse_term()?; Ok((nam, vec![], bod)) } - - fn parse_switch(&mut self) -> ParseResult { - let (bnd, arg, with) = self.parse_match_header()?; - self.consume("{")?; - let mut expected_num = 0; - let mut arms = vec![]; - let mut to_continue = true; - self.skip_trivia(); - while to_continue && !self.starts_with("}") { - self.try_consume("|"); - self.skip_trivia(); - let Some(head) = self.peek_one() else { return self.expected("switch pattern") }; - match head { - '_' => { - if expected_num == 0 { - return self.expected("0"); - } else { - self.consume("_")?; - to_continue = false; - } - } - c if c.is_ascii_digit() => { - let val = self.parse_u32()?; - if val != expected_num { - return self.expected(&expected_num.to_string()); - } - } - _ => return self.expected("switch pattern"), - }; - self.consume(":")?; - arms.push(self.parse_term()?); - self.try_consume(";"); - expected_num += 1; - } - let pred = Some(Name::new(format!("{}-{}", bnd.as_ref().unwrap(), arms.len() - 1))); - self.consume("}")?; - Ok(Term::Swt { arg: Box::new(arg), bnd, with, pred, arms }) - } } impl<'a> Parser<'a> for TermParser<'a> { diff --git a/src/imp/parser.rs b/src/imp/parser.rs index 8387e983..5f25ac14 100644 --- a/src/imp/parser.rs +++ b/src/imp/parser.rs @@ -594,9 +594,11 @@ impl<'a> PyParser<'a> { indent.enter_level(); self.consume_indent_exactly(*indent)?; + let ini_idx = *self.index(); let (fst_case, fst_stmt, mut nxt_indent) = self.parse_switch_case(indent)?; + let end_idx = *self.index(); if fst_case != Some(0) { - return self.expected("case 0"); + return self.expected_spanned("case 0", ini_idx, end_idx); } let mut arms = vec![fst_stmt]; let mut should_continue = fst_case == Some(0); @@ -640,10 +642,10 @@ impl<'a> PyParser<'a> { None } c if c.is_ascii_digit() => Some(self.parse_u32()?), - _ => return self.expected("Number pattern"), + _ => return self.expected("number or '_'"), } } else { - return self.expected("Switch pattern")?; + return self.expected("number or '_'")?; }; self.advance_trivia_inline(); diff --git a/tests/golden_tests/compile_file/switch_incomplete.bend b/tests/golden_tests/compile_file/switch_incomplete.bend new file mode 100644 index 00000000..d15af027 --- /dev/null +++ b/tests/golden_tests/compile_file/switch_incomplete.bend @@ -0,0 +1,2 @@ +# This should be interpreted as a switch with a SUP argument that is missing its elements. +main = switch {} \ No newline at end of file diff --git a/tests/snapshots/compile_file__switch_all_patterns.bend.snap b/tests/snapshots/compile_file__switch_all_patterns.bend.snap index af5971be..3478deee 100644 --- a/tests/snapshots/compile_file__switch_all_patterns.bend.snap +++ b/tests/snapshots/compile_file__switch_all_patterns.bend.snap @@ -4,6 +4,6 @@ input_file: tests/golden_tests/compile_file/switch_all_patterns.bend --- Errors: In tests/golden_tests/compile_file/switch_all_patterns.bend : -- expected: 0 +- expected: '0' - detected:  7 | _: x-1 diff --git a/tests/snapshots/compile_file__switch_incomplete.bend.snap b/tests/snapshots/compile_file__switch_incomplete.bend.snap new file mode 100644 index 00000000..e12910f6 --- /dev/null +++ b/tests/snapshots/compile_file__switch_incomplete.bend.snap @@ -0,0 +1,9 @@ +--- +source: tests/golden_tests.rs +input_file: tests/golden_tests/compile_file/switch_incomplete.bend +--- +Errors: +In tests/golden_tests/compile_file/switch_incomplete.bend : +- expected: term +- detected: + 2 | main = switch {}