Skip to content

Handle Unmatched RParen #542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/erg_common/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ fn main() -> std::io::Result<()> {
} else {
true
};
println!("cargo:rustc-env=CASE_SENSITIVE={}", case_sensitive);
println!("cargo:rustc-env=CASE_SENSITIVE={case_sensitive}");
Ok(())
}
4 changes: 2 additions & 2 deletions crates/erg_compiler/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1982,8 +1982,8 @@ pub enum GuardClause {
impl NestedDisplay for GuardClause {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
match self {
GuardClause::Condition(cond) => write!(f, "{}", cond),
GuardClause::Bind(bind) => write!(f, "{}", bind),
GuardClause::Condition(cond) => write!(f, "{cond}"),
GuardClause::Bind(bind) => write!(f, "{bind}"),
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/erg_compiler/ty/codeobj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,14 +642,14 @@ impl CodeObj {
write!(instrs, "{arg} ({})", self.cellvars[arg]).unwrap();
}
Opcode308::JUMP_ABSOLUTE => {
write!(instrs, "{arg} (to {})", arg).unwrap();
write!(instrs, "{arg} (to {arg})").unwrap();
}
Opcode308::JUMP_FORWARD => {
write!(instrs, "{arg} (to {})", idx + arg + 2).unwrap();
}
// REVIEW: *2?
Opcode308::POP_JUMP_IF_FALSE | Opcode308::POP_JUMP_IF_TRUE => {
write!(instrs, "{arg} (to {})", arg).unwrap();
write!(instrs, "{arg} (to {arg})").unwrap();
}
Opcode308::BINARY_ADD
| Opcode308::BINARY_SUBTRACT
Expand Down Expand Up @@ -690,14 +690,14 @@ impl CodeObj {
write!(instrs, "{arg} ({})", self.cellvars[arg]).unwrap();
}
Opcode309::JUMP_ABSOLUTE => {
write!(instrs, "{arg} (to {})", arg).unwrap();
write!(instrs, "{arg} (to {arg})").unwrap();
}
Opcode309::JUMP_FORWARD => {
write!(instrs, "{arg} (to {})", idx + arg + 2).unwrap();
}
// REVIEW: *2?
Opcode309::POP_JUMP_IF_FALSE | Opcode309::POP_JUMP_IF_TRUE => {
write!(instrs, "{arg} (to {})", arg).unwrap();
write!(instrs, "{arg} (to {arg})").unwrap();
}
Opcode309::BINARY_ADD
| Opcode309::BINARY_SUBTRACT
Expand Down
4 changes: 2 additions & 2 deletions crates/erg_compiler/ty/constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,12 @@ pub fn try_v_enum(s: Set<ValueObj>) -> Result<Type, Set<ValueObj>> {
}

pub fn v_enum(s: Set<ValueObj>) -> Type {
try_v_enum(s).unwrap_or_else(|set| panic!("not homogeneous: {}", set))
try_v_enum(s).unwrap_or_else(|set| panic!("not homogeneous: {set}"))
}

pub fn t_enum(s: Set<Type>) -> Type {
try_v_enum(s.into_iter().map(ValueObj::builtin_type).collect())
.unwrap_or_else(|set| panic!("not homogeneous: {}", set))
.unwrap_or_else(|set| panic!("not homogeneous: {set}"))
}

pub fn t_singleton(t: Type) -> Type {
Expand Down
2 changes: 1 addition & 1 deletion crates/erg_compiler/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ impl LimitedDisplay for SubrType {
}
write!(f, "*")?;
if let Some(name) = var_params.name() {
write!(f, "{}: ", name)?;
write!(f, "{name}: ")?;
}
var_params.typ().limited_fmt(f, limit - 1)?;
}
Expand Down
24 changes: 12 additions & 12 deletions crates/erg_parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2162,19 +2162,19 @@ impl NestedDisplay for Call {
if i != 0 {
write!(f, ", ")?;
}
write!(f, "{}", arg)?;
write!(f, "{arg}")?;
}
if let Some(rest) = self.args.var_args.as_ref() {
if !self.args.pos_args().is_empty() {
write!(f, ", ")?;
}
write!(f, "*{}", rest)?;
write!(f, "*{rest}")?;
}
for (i, kw_arg) in self.args.kw_args().iter().enumerate() {
if i != 0 || !self.args.pos_args().is_empty() || self.args.var_args.is_some() {
write!(f, ", ")?;
}
write!(f, "{}", kw_arg)?;
write!(f, "{kw_arg}")?;
}
write!(f, ")")
} else {
Expand Down Expand Up @@ -3194,7 +3194,7 @@ impl NestedDisplay for ConstApp {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
writeln!(f, "{}", self.obj)?;
if let Some(attr_name) = &self.attr_name {
writeln!(f, "{}", attr_name)?;
writeln!(f, "{attr_name}")?;
}
writeln!(f, "(")?;
self.args.fmt_nest(f, level + 1)?;
Expand Down Expand Up @@ -4446,11 +4446,11 @@ impl fmt::Display for VarName {
#[pymethods]
impl VarName {
pub fn __repr__(&self) -> String {
format!("VarName({})", self)
format!("VarName({self})")
}

pub fn __str__(&self) -> String {
format!("VarName({})", self)
format!("VarName({self})")
}

#[staticmethod]
Expand Down Expand Up @@ -4715,11 +4715,11 @@ impl From<Identifier> for Expr {
#[pymethods]
impl Identifier {
pub fn __repr__(&self) -> String {
format!("Identifier({})", self)
format!("Identifier({self})")
}

pub fn __str__(&self) -> String {
format!("Identifier({})", self)
format!("Identifier({self})")
}

pub fn is_const(&self) -> bool {
Expand Down Expand Up @@ -5245,11 +5245,11 @@ impl VarSignature {
}

pub fn __repr__(&self) -> String {
format!("VarSignature({})", self)
format!("VarSignature({self})")
}

pub fn __str__(&self) -> String {
format!("VarSignature({})", self)
format!("VarSignature({self})")
}
}

Expand Down Expand Up @@ -5704,8 +5704,8 @@ pub enum GuardClause {
impl NestedDisplay for GuardClause {
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
match self {
Self::Condition(cond) => write!(f, "{}", cond),
Self::Bind(def) => write!(f, "{}", def),
Self::Condition(cond) => write!(f, "{cond}"),
Self::Bind(def) => write!(f, "{def}"),
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions crates/erg_parser/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
7 changes: 7 additions & 0 deletions crates/erg_parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions crates/erg_parser/tests/parse_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions crates/erg_parser/tests/unmatched_paren.er
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
func a, b) = a + b
2 changes: 1 addition & 1 deletion src/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ impl PackageManagerRunner {
{
Ok(out) => ExitStatus::new(out.status.code().unwrap_or(0), 0, 0),
Err(err) => {
eprintln!("Error: {}", err);
eprintln!("Error: {err}");
ExitStatus::ERR1
}
}
Expand Down