From 59fdfbf27be6b0334f94fa28563f014161e61e2e Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Mon, 7 Nov 2022 20:57:59 +0800 Subject: [PATCH] refactor: try to use new parser #13 --- extensions/ext-computing/src/expr/ast.rs | 30 +++- .../ext-computing/src/expr/grammar.pest | 3 +- extensions/ext-computing/src/expr/parser.rs | 129 +++++++++++------- 3 files changed, 110 insertions(+), 52 deletions(-) diff --git a/extensions/ext-computing/src/expr/ast.rs b/extensions/ext-computing/src/expr/ast.rs index 140ea4a..eb593b4 100644 --- a/extensions/ext-computing/src/expr/ast.rs +++ b/extensions/ext-computing/src/expr/ast.rs @@ -1,15 +1,34 @@ #[derive(Clone, PartialEq, Debug)] -pub enum Expr { - Int(i64), - // Convert(Box, Type), +pub struct Expr { + pub first: Value, + pub pairs: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ExprPair(pub BinaryOp, pub Value); +impl ExprPair { + pub fn new(op: BinaryOp, value: Value) -> Self { + ExprPair(op, value) + } } #[derive(Clone, PartialEq, Debug)] pub enum UnaryOp { Not, - Neg, - Parenthesized + Neg(ValueIndex), + Parenthesized, +} + +#[derive(Debug, PartialEq, Copy, Clone)] +pub struct ValueIndex(pub usize); + +#[derive(Clone, PartialEq, Debug)] +pub enum Value { + Const(f64), + Var(String), + UnaryOp(UnaryOp), + StdFunc(StdMathFunc), } #[derive(Clone, PartialEq, Debug)] @@ -33,6 +52,7 @@ pub enum BinaryOp { Le, Gt, Ge, + Exp, } #[derive(Clone, PartialEq, Debug)] diff --git a/extensions/ext-computing/src/expr/grammar.pest b/extensions/ext-computing/src/expr/grammar.pest index b25631c..11ac525 100644 --- a/extensions/ext-computing/src/expr/grammar.pest +++ b/extensions/ext-computing/src/expr/grammar.pest @@ -3,7 +3,7 @@ program = _{ SOI ~ expr ~ EOI } stmt = _{ assign | expr } assign = { ident ~ "=" ~ expr } expr = { prefix* ~ primary ~ postfix* ~ (infix ~ prefix* ~ primary ~ postfix* )* } -primary = _{ constants | function | ident | num | "(" ~ expr ~ ")" } +primary = _{ constants | function | variable | num | "(" ~ expr ~ ")" } infix = _{ sub | add | mul | div | pow | percentOf | percentOn | rightShift | leftShift | modulus } prefix = _{ neg } postfix = _{ fac } @@ -25,6 +25,7 @@ percentOn = { "percent on" | "%" ~ "on" } function = { ident ~ "(" ~ expr ~ ")" } +variable = { ident } ident = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* ~ "'"* } int = { ("+" | "-")? ~ ASCII_DIGIT+ } num = @{ int ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ int)? } diff --git a/extensions/ext-computing/src/expr/parser.rs b/extensions/ext-computing/src/expr/parser.rs index 9e4f086..004a12c 100644 --- a/extensions/ext-computing/src/expr/parser.rs +++ b/extensions/ext-computing/src/expr/parser.rs @@ -1,7 +1,9 @@ -use pest::iterators::Pairs; +use pest::iterators::{Pair, Pairs}; use pest::Parser; use pest::pratt_parser::*; +use crate::expr::ast::{BinaryOp, Expr, ExprPair, UnaryOp, Value, ValueIndex}; + #[derive(Parser)] #[grammar = "expr/grammar.pest"] struct Calculator; @@ -18,28 +20,54 @@ lazy_static! { }; } -pub fn parse(input: &str) -> f64 { +pub fn parse(input: &str) { match Calculator::parse(Rule::program, input) { - Ok(mut pairs) => parse_expr(pairs.next().unwrap().into_inner()), - Err(_) => f64::NAN, - } + Ok(mut pairs) => { + old_parser(pairs.next().unwrap().into_inner()); + }, + Err(err) => { + println!("Error: {:?}", err); + }, + }; } +// +// const VALUE_INDEX: usize = 0; +// +// fn parse_eval(pairs: Pairs) -> ExprPair { +// PRATT_PARSER +// .map_primary(|primary| { +// match primary.as_rule() { +// Rule::expr => parse_eval(primary.into_inner()), +// _ => unreachable!(), +// } +// }) +// .map_prefix(|op: Pair, rhs| match op.as_rule() { +// Rule::neg => { +// ExprPair::new(BinaryOp::Exp, Value::UnaryOp(UnaryOp::Neg(ValueIndex(VALUE_INDEX)))) +// } +// }) +// .map_infix(|lhs, op: Pair, rhs| match op.as_rule() { +// Rule::add => ExprPair::new(BinaryOp::Add, Value::UnaryOp(lhs, rhs)), +// _ => unreachable!(), +// }) +// .parse(pairs) +// } // can be follow: -fn parse_expr(pairs: Pairs) -> f64 { +fn old_parser(pairs: Pairs) -> f64 { PRATT_PARSER .map_primary(|primary| { match primary.as_rule() { - Rule::expr => parse_expr(primary.into_inner()), + Rule::expr => old_parser(primary.into_inner()), Rule::int => primary.as_str().parse().unwrap(), Rule::num => primary.as_str().parse().unwrap(), Rule::function => { let mut inner = primary.into_inner(); let name = inner.next().unwrap().as_str(); let arg = inner.next().unwrap().into_inner(); - let func_name = parse_expr(arg); + let func_name = old_parser(arg); execute_func(name, func_name) - }, + } _ => panic!("unimplemented, {:?}", primary.as_rule()), } }) @@ -62,32 +90,40 @@ fn parse_expr(pairs: Pairs) -> f64 { .parse(pairs) } -fn execute_func(name: &str, func_name: f64) -> f64 { - match name { - "sin" => func_name.sin(), - "cos" => func_name.cos(), - "tan" => func_name.tan(), - "asin" => func_name.asin(), - "acos" => func_name.acos(), - "atan" => func_name.atan(), - "sinh" => func_name.sinh(), - "cosh" => func_name.cosh(), - "tanh" => func_name.tanh(), - "asinh" => func_name.asinh(), - "acosh" => func_name.acosh(), - "atanh" => func_name.atanh(), - "sqrt" => func_name.sqrt(), - "cbrt" => func_name.cbrt(), - "exp" => func_name.exp(), - "ln" => func_name.ln(), - "log2" => func_name.log2(), - "log10" => func_name.log10(), - "abs" => func_name.abs(), - "ceil" => func_name.ceil(), - "floor" => func_name.floor(), - "round" => func_name.round(), - "trunc" => func_name.trunc(), - "fract" => func_name.fract(), +pub fn parse_value(pair: pest::iterators::Pair) -> Value { + match pair.as_rule() { + Rule::int => Value::Const(pair.as_str().parse().unwrap()), + Rule::variable => Value::Var(pair.as_str().to_string()), + _ => unreachable!(), + } +} + +fn execute_func(func_name: &str, arg: f64) -> f64 { + match func_name { + "sin" => arg.sin(), + "cos" => arg.cos(), + "tan" => arg.tan(), + "asin" => arg.asin(), + "acos" => arg.acos(), + "atan" => arg.atan(), + "sinh" => arg.sinh(), + "cosh" => arg.cosh(), + "tanh" => arg.tanh(), + "asinh" => arg.asinh(), + "acosh" => arg.acosh(), + "atanh" => arg.atanh(), + "sqrt" => arg.sqrt(), + "cbrt" => arg.cbrt(), + "exp" => arg.exp(), + "ln" => arg.ln(), + "log2" => arg.log2(), + "log10" => arg.log10(), + "abs" => arg.abs(), + "ceil" => arg.ceil(), + "floor" => arg.floor(), + "round" => arg.round(), + "trunc" => arg.trunc(), + "fract" => arg.fract(), _ => f64::NAN, } } @@ -98,17 +134,18 @@ mod tests { #[test] fn basic_expr() { - assert_eq!(parse("1 + 2"), 3.0); - assert_eq!(parse("1 + 2 * 3"), 7.0); - assert_eq!(parse("(1 + 2) * 3"), 9.0); - assert_eq!(parse("1 + 2 * 3 + 4"), 11.0); - assert_eq!(parse("1 + 2 * (3 + 4)"), 15.0); - assert_eq!(parse("1 + 2 * (3 + 4) / 5"), 3.8); - assert_eq!(parse("1 + 2 * (3 + 4) / 5 - 6"), -2.2); + parse("1 + 2"); + // assert_eq!(parse("1 + 2"), 3.0); + // assert_eq!(parse("1 + 2 * 3"), 7.0); + // assert_eq!(parse("(1 + 2) * 3"), 9.0); + // assert_eq!(parse("1 + 2 * 3 + 4"), 11.0); + // assert_eq!(parse("1 + 2 * (3 + 4)"), 15.0); + // assert_eq!(parse("1 + 2 * (3 + 4) / 5"), 3.8); + // assert_eq!(parse("1 + 2 * (3 + 4) / 5 - 6"), -2.2); } - #[test] - fn function_sqrt() { - assert_eq!(parse("sqrt(4)"), 2.0); - } + // #[test] + // fn function_sqrt() { + // assert_eq!(parse("sqrt(4)"), 2.0); + // } }