From 90ba7f37d3c03d0debaacf5b2601dfe7ff301f58 Mon Sep 17 00:00:00 2001 From: GreasySlug <9619abgoni@gmail.com> Date: Sun, 18 Dec 2022 15:35:22 +0900 Subject: [PATCH 1/3] fix: infinite loop when `#[` is more than `]#` --- compiler/erg_parser/lex.rs | 84 ++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs index 68d1fd76..485e6812 100644 --- a/compiler/erg_parser/lex.rs +++ b/compiler/erg_parser/lex.rs @@ -316,57 +316,51 @@ impl Lexer /*<'a>*/ { fn lex_multi_line_comment(&mut self) -> LexResult<()> { let mut s = "".to_string(); let mut nest_level = 0; - loop { - match self.peek_cur_ch() { - Some(c) => { - if let Some(next_c) = self.peek_next_ch() { - match (c, next_c) { - ('#', '[') => nest_level += 1, - (']', '#') => { - nest_level -= 1; - if nest_level == 0 { - return Ok(()); - } - } - _ => {} + while let Some(c) = self.peek_cur_ch() { + if let Some(next_c) = self.peek_next_ch() { + match (c, next_c) { + ('#', '[') => nest_level += 1, + (']', '#') => { + nest_level -= 1; + if nest_level == 0 { + return Ok(()); } - if c == '\n' { - self.lineno_token_starts += 1; - self.col_token_starts = 0; - } - s.push(self.consume().unwrap()); - } - if Self::is_bidi(self.peek_cur_ch().unwrap()) { - let comment = self.emit_token(Illegal, &s); - return Err(LexError::syntax_error( - line!() as usize, - comment.loc(), - switch_lang!( - "japanese" => "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています", - "simplified_chinese" => "注释中使用了非法的unicode字符(双向覆盖)", - "traditional_chinese" => "註釋中使用了非法的unicode字符(雙向覆蓋)", - "english" => "invalid unicode character (bi-directional override) in comments", - ), - None, - )); } + _ => {} } - None => { - let comment = self.emit_token(Illegal, &s); - return Err(LexError::syntax_error( - line!() as usize, - comment.loc(), - switch_lang!( - "japanese" => "複数行コメントが]#で閉じられていません", - "simplified_chinese" => "未用]#号结束的多处评论", - "traditional_chinese" => "多條評論未用]#關閉", - "english" => "Multi-comment is not closed with ]#", - ), - None, - )); + if c == '\n' { + self.lineno_token_starts += 1; + self.col_token_starts = 0; } } + if Self::is_bidi(c) { + let comment = self.emit_token(Illegal, &s); + return Err(LexError::syntax_error( + line!() as usize, + comment.loc(), + switch_lang!( + "japanese" => "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています", + "simplified_chinese" => "注释中使用了非法的unicode字符(双向覆盖)", + "traditional_chinese" => "註釋中使用了非法的unicode字符(雙向覆蓋)", + "english" => "invalid unicode character (bi-directional override) in comments", + ), + None, + )); + } + s.push(self.consume().unwrap()); } + let comment = self.emit_token(Illegal, &s); + Err(LexError::syntax_error( + line!() as usize, + comment.loc(), + switch_lang!( + "japanese" => "複数行コメントが]#で閉じられていません", + "simplified_chinese" => "未用]#号结束的多处评论", + "traditional_chinese" => "多條評論未用]#關閉", + "english" => "multi-comment is not closed with ]#", + ), + None, + )) } fn lex_space_indent_dedent(&mut self) -> Option> { From ca359b4f7cf695c7ae3301feb225e3f93c82af15 Mon Sep 17 00:00:00 2001 From: GreasySlug <9619abgoni@gmail.com> Date: Tue, 20 Dec 2022 13:39:19 +0900 Subject: [PATCH 2/3] update: add hint and show nest count --- compiler/erg_parser/lex.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs index 485e6812..b7700f8f 100644 --- a/compiler/erg_parser/lex.rs +++ b/compiler/erg_parser/lex.rs @@ -331,6 +331,9 @@ impl Lexer /*<'a>*/ { if c == '\n' { self.lineno_token_starts += 1; self.col_token_starts = 0; + s.clear(); + self.consume(); + continue; } } if Self::is_bidi(c) { @@ -350,6 +353,12 @@ impl Lexer /*<'a>*/ { s.push(self.consume().unwrap()); } let comment = self.emit_token(Illegal, &s); + let hint = switch_lang!( + "japanese" => format!("`]#`の数があと{}個必要です", nest_level), + "simplified_chinese" => format!("需要{}个`]#`", nest_level), + "traditional_chinese" => format!("需要{}個`]#`", nest_level), + "english" => format!("{} `]#`(s) are needed", nest_level), + ); Err(LexError::syntax_error( line!() as usize, comment.loc(), @@ -359,7 +368,7 @@ impl Lexer /*<'a>*/ { "traditional_chinese" => "多條評論未用]#關閉", "english" => "multi-comment is not closed with ]#", ), - None, + Some(hint), )) } From e87e5739260abf5b8d16e3464bffed63b7498dfc Mon Sep 17 00:00:00 2001 From: GreasySlug <9619abgoni@gmail.com> Date: Tue, 20 Dec 2022 13:39:30 +0900 Subject: [PATCH 3/3] test: invalid nest err --- tests/should_err/multi_line_invalid_nest.er | 10 ++++++++++ tests/test.rs | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 tests/should_err/multi_line_invalid_nest.er diff --git a/tests/should_err/multi_line_invalid_nest.er b/tests/should_err/multi_line_invalid_nest.er new file mode 100644 index 00000000..e3d88cc6 --- /dev/null +++ b/tests/should_err/multi_line_invalid_nest.er @@ -0,0 +1,10 @@ +#[ + #[ + #[ + #[ + #[ + + ] + ] + ]# +]# \ No newline at end of file diff --git a/tests/test.rs b/tests/test.rs index 391e4c83..de18b5b0 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -209,3 +209,8 @@ fn exec_subtyping() -> Result<(), ()> { fn exec_callable() -> Result<(), ()> { expect_failure("tests/should_err/callable.er", 4) } + +#[test] +fn exec_multiline_invalid_next() -> Result<(), ()> { + expect_failure("tests/should_err/multi_line_invalid_nest.er", 1) +}