From b4a63b45f70cc8997f15d6772b235882e7fb0094 Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Sun, 9 Oct 2022 00:06:13 +0800 Subject: [PATCH] cleanup expr parser --- src/cozoscript.pest | 3 +- src/parse/expr.rs | 71 +++++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/cozoscript.pest b/src/cozoscript.pest index 08d59cf7..1043c1f4 100644 --- a/src/cozoscript.pest +++ b/src/cozoscript.pest @@ -68,7 +68,7 @@ named_apply_args = {(named_apply_pair ~ ",")* ~ named_apply_pair?} named_apply_pair = {ident ~ (":" ~ expr)?} grouped = _{"(" ~ rule_body ~ ")"} -expr = {unary ~ (operation ~ unary)*} +expr = {unary_op* ~ term ~ (operation ~ unary_op* ~ term)*} operation = _{ (op_and | op_or | op_pow | op_concat | op_add | op_sub | op_mul | op_div | op_mod | op_ge | op_le | op_gt | op_lt | op_eq | op_ne)} op_or = { "||" } @@ -86,7 +86,6 @@ op_lt = { "<" } op_ge = { ">=" } op_le = { "<=" } op_pow = { "^" } -unary = { (unary_op ~ unary) | term } unary_op = _{ minus | negate } minus = { "-" } negate = { "!" } diff --git a/src/parse/expr.rs b/src/parse/expr.rs index 3d5eee40..011ffdaa 100644 --- a/src/parse/expr.rs +++ b/src/parse/expr.rs @@ -34,6 +34,8 @@ lazy_static! { | Op::infix(Rule::op_concat, Left)) .op(Op::infix(Rule::op_mul, Left) | Op::infix(Rule::op_div, Left)) .op(Op::infix(Rule::op_pow, Right)) + .op(Op::prefix(Rule::minus)) + .op(Op::prefix(Rule::negate)) }; } @@ -49,8 +51,25 @@ pub(crate) fn build_expr(pair: Pair<'_>, param_pool: &BTreeMap Expr::Apply { + op: &OP_MINUS, + args: [rhs].into(), + span: op.extract_span().merge(rhs_span), + }, + Rule::negate => Expr::Apply { + op: &OP_NEGATE, + args: [rhs].into(), + span: op.extract_span().merge(rhs_span), + }, + _ => unreachable!(), + }) + }) .parse(pair.into_inner()) } @@ -84,16 +103,12 @@ fn build_expr_infix(lhs: Result, op: Pair<'_>, rhs: Result) -> Resul }) } -fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Result { +fn build_term(pair: Pair<'_>, param_pool: &BTreeMap) -> Result { let span = pair.extract_span(); - let s = pair.as_str(); - let mut inner = pair.into_inner(); - let p = inner.next().unwrap(); - let op = p.as_rule(); + let op = pair.as_rule(); Ok(match op { - Rule::term => build_unary(p, param_pool)?, Rule::var => Expr::Binding { - var: Symbol::new(s, p.extract_span()), + var: Symbol::new(pair.as_str(), pair.extract_span()), tuple_pos: None, }, Rule::param => { @@ -102,7 +117,7 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu #[diagnostic(code(parser::param_not_found))] struct ParamNotFoundError(String, #[label] SourceSpan); - let param_str = s.strip_prefix('$').unwrap(); + let param_str = pair.as_str().strip_prefix('$').unwrap(); Expr::Const { val: param_pool .get(param_str) @@ -111,29 +126,14 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu span, } } - Rule::minus => { - let inner = build_unary(inner.next().unwrap(), param_pool)?; - Expr::Apply { - op: &OP_MINUS, - args: [inner].into(), - span, - } - } - Rule::negate => { - let inner = build_unary(inner.next().unwrap(), param_pool)?; - Expr::Apply { - op: &OP_NEGATE, - args: [inner].into(), - span, - } - } Rule::pos_int => { #[derive(Error, Diagnostic, Debug)] #[error("Cannot parse integer")] #[diagnostic(code(parser::bad_pos_int))] struct BadIntError(#[label] SourceSpan); - let i = s + let i = pair + .as_str() .replace('_', "") .parse::() .map_err(|_| BadIntError(span))?; @@ -143,21 +143,21 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu } } Rule::hex_pos_int => { - let i = parse_int(s, 16); + let i = parse_int(pair.as_str(), 16); Expr::Const { val: DataValue::from(i), span, } } Rule::octo_pos_int => { - let i = parse_int(s, 8); + let i = parse_int(pair.as_str(), 8); Expr::Const { val: DataValue::from(i), span, } } Rule::bin_pos_int => { - let i = parse_int(s, 2); + let i = parse_int(pair.as_str(), 2); Expr::Const { val: DataValue::from(i), span, @@ -169,7 +169,8 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu #[diagnostic(code(parser::bad_float))] struct BadFloatError(#[label] SourceSpan); - let f = s + let f = pair + .as_str() .replace('_', "") .parse::() .map_err(|_| BadFloatError(span))?; @@ -183,11 +184,11 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu span, }, Rule::boolean => Expr::Const { - val: DataValue::Bool(s == "true"), + val: DataValue::Bool(pair.as_str() == "true"), span, }, Rule::quoted_string | Rule::s_quoted_string | Rule::raw_string => { - let s = parse_string(p)?; + let s = parse_string(pair)?; Expr::Const { val: DataValue::Str(s), span, @@ -195,7 +196,7 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu } Rule::list => { let mut collected = vec![]; - for p in p.into_inner() { + for p in pair.into_inner() { collected.push(build_expr(p, param_pool)?) } Expr::Apply { @@ -205,7 +206,7 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu } } Rule::apply => { - let mut p = p.into_inner(); + let mut p = pair.into_inner(); let ident_p = p.next().unwrap(); let ident = ident_p.as_str(); let mut args: Vec<_> = p @@ -302,7 +303,7 @@ fn build_unary(pair: Pair<'_>, param_pool: &BTreeMap) -> Resu } } } - Rule::grouping => build_expr(p.into_inner().next().unwrap(), param_pool)?, + Rule::grouping => build_expr(pair.into_inner().next().unwrap(), param_pool)?, r => unreachable!("Encountered unknown op {:?}", r), }) }