From c90bf34bb76744fc523bbec2a7e39ecd17a031a7 Mon Sep 17 00:00:00 2001 From: GreasySlug <9619abgoni@gmail.com> Date: Wed, 31 Dec 2025 20:28:34 +0900 Subject: [PATCH 1/2] fix(parser): handle unmatched closing parenthesis --- crates/erg_parser/error.rs | 17 +++++++++++++++++ crates/erg_parser/parse.rs | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/crates/erg_parser/error.rs b/crates/erg_parser/error.rs index ea9211442..ad990ffde 100644 --- a/crates/erg_parser/error.rs +++ b/crates/erg_parser/error.rs @@ -175,6 +175,23 @@ impl LexError { )) } + pub fn parenthesize_error(errno: usize, loc: Location, got: &str) -> Self { + let msg = switch_lang!( + "japanese" => "不適切な閉じ括弧があります", + "simplified_chinese" => "存在不匹配的右括号", + "traditional_chinese" => "存在不匹配的右括號", + "english" => "unmatched closing parenthesis found", + ); + let got = StyledStr::new(got, Some(ERR), Some(ATTR)); + let hint = switch_lang!( + "japanese" => format!("この{}は対応する開き括弧がないため、削除するか開き括弧を追加してください", got), + "simplified_chinese" => format!("{}缺少对应的左括号,请删除或添加左括号", got), + "traditional_chinese" => format!("{}缺少對應的左括號,請刪除或添加左括號", got), + "english" => format!("{} has no matching opening parenthesis - either remove it or add an opening parenthesis", got), + ); + Self::syntax_error(errno, loc, msg, Some(hint)) + } + pub fn expect_next_line_error(errno: usize, loc: Location, caused: &str) -> Self { Self::new(ErrorCore::new( vec![SubMessage::ambiguous_new( diff --git a/crates/erg_parser/parse.rs b/crates/erg_parser/parse.rs index 6236de1d7..cde39f981 100644 --- a/crates/erg_parser/parse.rs +++ b/crates/erg_parser/parse.rs @@ -2050,6 +2050,13 @@ impl Parser { debug_exit_info!(self); return Err(()); } + Some(t) if t.is(RParen) => { + let err = ParseError::parenthesize_error(line!() as usize, t.loc(), ")"); + self.errs.push(err); + self.next_expr(); + debug_exit_info!(self); + return Err(()); + } _ => { if stack.len() <= 1 { break; From f09f704cc1e4555740f2597002eedb35c0e497bd Mon Sep 17 00:00:00 2001 From: GreasySlug <9619abgoni@gmail.com> Date: Wed, 31 Dec 2025 20:32:56 +0900 Subject: [PATCH 2/2] test(parse): add neg test --- crates/erg_parser/tests/parse_test.rs | 5 +++++ crates/erg_parser/tests/unmatched_paren.er | 1 + 2 files changed, 6 insertions(+) create mode 100644 crates/erg_parser/tests/unmatched_paren.er diff --git a/crates/erg_parser/tests/parse_test.rs b/crates/erg_parser/tests/parse_test.rs index 8b780a362..6f56729f1 100644 --- a/crates/erg_parser/tests/parse_test.rs +++ b/crates/erg_parser/tests/parse_test.rs @@ -84,6 +84,11 @@ fn parse_invalid_class_definition() -> Result<(), ()> { expect_failure("tests/invalid_class_definition.er", 0, 7) } +#[test] +fn parse_missing_paren() -> Result<(), ()> { + expect_failure("tests/unmatched_paren.er", 0, 1) +} + #[test] fn parse_warns() -> Result<(), ()> { expect_success("tests/warns.er", 1) diff --git a/crates/erg_parser/tests/unmatched_paren.er b/crates/erg_parser/tests/unmatched_paren.er new file mode 100644 index 000000000..fdcb10430 --- /dev/null +++ b/crates/erg_parser/tests/unmatched_paren.er @@ -0,0 +1 @@ +func a, b) = a + b \ No newline at end of file