pub struct Parser {
pub expr_len_limit: usize,
pub expr_depth_limit: usize,
}
Fields§
§expr_len_limit: usize
§expr_depth_limit: usize
Implementations§
Source§impl Parser
impl Parser
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Examples found in repository?
examples/compile.rs (line 7)
6fn main() -> Result<(), fasteval3::Error> {
7 let parser = fasteval3::Parser::new();
8 let mut slab = fasteval3::Slab::new();
9 let mut map = BTreeMap::new();
10
11 let expr_str = "sin(deg/360 * 2*pi())";
12 let compiled = parser
13 .parse(expr_str, &mut slab.ps)?
14 .from(&slab.ps)
15 .compile(&slab.ps, &mut slab.cs, &mut EmptyNamespace);
16 for deg in 0..360 {
17 map.insert(String::from("deg"), f64::from(deg));
18 // When working with compiled constant expressions, you can use the
19 // eval_compiled*!() macros to save a function call:
20 let val = fasteval3::eval_compiled!(compiled, &slab, &mut map);
21 eprintln!("sin({deg}°) = {val}");
22 }
23
24 Ok(())
25}
More examples
examples/slab.rs (line 6)
5fn main() -> Result<(), fasteval3::Error> {
6 let parser = fasteval3::Parser::new();
7 let mut slab = fasteval3::Slab::new();
8
9 // See the `parse` documentation to understand why we use `from` like this:
10 let expr_ref = parser.parse("x + 1", &mut slab.ps)?.from(&slab.ps);
11
12 // Let's evaluate the expression a couple times with different 'x' values:
13
14 let mut map: BTreeMap<String, f64> = BTreeMap::new();
15 map.insert(String::from("x"), 1.0);
16 let val = expr_ref.eval(&slab, &mut map)?;
17 assert!((val - 2.0).abs() < f64::EPSILON);
18
19 map.insert(String::from("x"), 2.5);
20 let val = expr_ref.eval(&slab, &mut map)?;
21 assert!((val - 3.5).abs() < f64::EPSILON);
22
23 // Now, let's re-use the Slab for a new expression.
24 // (This is much cheaper than allocating a new Slab.)
25 // The Slab gets cleared by 'parse()', so you must avoid using
26 // the old expr_ref after parsing the new expression.
27 // One simple way to avoid this problem is to shadow the old variable:
28
29 let expr_ref = parser.parse("x * 10", &mut slab.ps)?.from(&slab.ps);
30
31 let val = expr_ref.eval(&slab, &mut map)?;
32 assert!((val - 25.0).abs() < f64::EPSILON);
33
34 Ok(())
35}
examples/internals.rs (line 5)
4fn main() -> Result<(), fasteval3::Error> {
5 let parser = fasteval3::Parser::new();
6 let mut slab = fasteval3::Slab::new();
7
8 let expr_str = "sin(deg/360 * 2*pi())";
9 let expr_ref = parser.parse(expr_str, &mut slab.ps)?.from(&slab.ps);
10
11 // Let's take a look at the parsed AST inside the Slab:
12 // If you find this structure confusing, take a look at the compilation
13 // AST below because it is simpler.
14 assert_eq!(
15 format!("{:?}", slab.ps),
16 r#"ParseSlab{ exprs:{ 0:Expression { first: EStdFunc(EVar("deg")), pairs: [ExprPair(EDiv, EConstant(360.0)), ExprPair(EMul, EConstant(2.0)), ExprPair(EMul, EStdFunc(EFuncPi))] }, 1:Expression { first: EStdFunc(EFuncSin(ExpressionI(0))), pairs: [] } }, vals:{} }"#
17 );
18 // Pretty-Print:
19 // ParseSlab{
20 // exprs:{
21 // 0:Expression { first: EStdFunc(EVar("deg")),
22 // pairs: [ExprPair(EDiv, EConstant(360.0)),
23 // ExprPair(EMul, EConstant(2.0)),
24 // ExprPair(EMul, EStdFunc(EFuncPi))]
25 // },
26 // 1:Expression { first: EStdFunc(EFuncSin(ExpressionI(0))),
27 // pairs: [] }
28 // },
29 // vals:{}
30 // }
31
32 let compiled = expr_ref.compile(&slab.ps, &mut slab.cs, &mut EmptyNamespace);
33
34 // Let's take a look at the compilation results and the AST inside the Slab:
35 // Notice that compilation has performed constant-folding: 1/360 * 2*pi = 0.017453292519943295
36 // In the results below: IFuncSin(...) represents the sin function.
37 // InstructionI(1) represents the Instruction stored at index 1.
38 // IMul(...) represents the multiplication operator.
39 // 'C(0.017...)' represents a constant value of 0.017... .
40 // IVar("deg") represents a variable named "deg".
41 assert_eq!(format!("{compiled:?}"), "IFuncSin(InstructionI(1))");
42 assert_eq!(
43 format!("{:?}", slab.cs),
44 r#"CompileSlab{ instrs:{ 0:IVar("deg"), 1:IMul(InstructionI(0), C(0.017453292519943295)) } }"#
45 );
46
47 Ok(())
48}
examples/repl.rs (line 55)
54fn repl() {
55 let parser = Parser::new();
56 let mut slab = Slab::new();
57 let mut ns_stack = vec![BTreeMap::new()];
58
59 let stdin = io::stdin();
60
61 loop {
62 eprint!(">>> ");
63 io::stderr().flush().unwrap();
64
65 let mut ans_key = String::from("_");
66
67 let mut line: String = if let Some(Ok(string)) = stdin.lock().lines().next() {
68 string.trim().to_owned()
69 } else {
70 break
71 };
72
73 if line.is_empty() {
74 continue;
75 }
76
77 let pieces: Vec<&str> = line.split_whitespace().collect();
78 if pieces[0] == "let" {
79 if pieces.len() < 4 || pieces[2] != "=" {
80 eprintln!("incorrect 'let' syntax. Should be: let x = ...");
81 continue;
82 }
83 ans_key = pieces[1].to_owned();
84 line = pieces[3..].join(" ");
85 } else if pieces[0] == "push" {
86 ns_stack.push(BTreeMap::new());
87 eprintln!("Entered scope[{}]", ns_stack.len() - 1);
88 continue;
89 } else if pieces[0] == "pop" {
90 let mut return_value = std::f64::NAN;
91 let mut has_return_value = false;
92 if let Some(v) = ns_stack.last().unwrap().get(&ans_key) {
93 return_value = *v;
94 has_return_value = true;
95 }
96
97 ns_stack.pop();
98 eprintln!("Exited scope[{}]", ns_stack.len());
99 if ns_stack.is_empty() {
100 ns_stack.push(BTreeMap::new());
101 } // All scopes have been removed. Add a new one.
102
103 if has_return_value {
104 ns_stack.last_mut().unwrap().insert(ans_key, return_value);
105 }
106
107 continue;
108 }
109
110 let expr_ref = match parser.parse(&line, &mut slab.ps) {
111 Ok(expr_i) => slab.ps.get_expr(expr_i),
112 Err(err) => {
113 eprintln!("parse error: {err}");
114 continue;
115 }
116 };
117
118 let ans = match expr_ref.eval(&slab, &mut ns_stack) {
119 Ok(val) => val,
120 Err(err) => {
121 eprintln!("eval error: {err}");
122 continue;
123 }
124 };
125
126 println!("{ans}");
127 ns_stack.last_mut().unwrap().insert(ans_key, ans);
128 }
129
130 println!();
131}
Sourcepub fn parse(
&self,
expr_str: &str,
slab: &mut ParseSlab,
) -> Result<ExpressionI, Error>
pub fn parse( &self, expr_str: &str, slab: &mut ParseSlab, ) -> Result<ExpressionI, Error>
Use this function to parse an expression String. The Slab
will be cleared first.
§Errors
Will return Err
if length of expr_str
exceeds limit.
Examples found in repository?
examples/compile.rs (line 13)
6fn main() -> Result<(), fasteval3::Error> {
7 let parser = fasteval3::Parser::new();
8 let mut slab = fasteval3::Slab::new();
9 let mut map = BTreeMap::new();
10
11 let expr_str = "sin(deg/360 * 2*pi())";
12 let compiled = parser
13 .parse(expr_str, &mut slab.ps)?
14 .from(&slab.ps)
15 .compile(&slab.ps, &mut slab.cs, &mut EmptyNamespace);
16 for deg in 0..360 {
17 map.insert(String::from("deg"), f64::from(deg));
18 // When working with compiled constant expressions, you can use the
19 // eval_compiled*!() macros to save a function call:
20 let val = fasteval3::eval_compiled!(compiled, &slab, &mut map);
21 eprintln!("sin({deg}°) = {val}");
22 }
23
24 Ok(())
25}
More examples
examples/slab.rs (line 10)
5fn main() -> Result<(), fasteval3::Error> {
6 let parser = fasteval3::Parser::new();
7 let mut slab = fasteval3::Slab::new();
8
9 // See the `parse` documentation to understand why we use `from` like this:
10 let expr_ref = parser.parse("x + 1", &mut slab.ps)?.from(&slab.ps);
11
12 // Let's evaluate the expression a couple times with different 'x' values:
13
14 let mut map: BTreeMap<String, f64> = BTreeMap::new();
15 map.insert(String::from("x"), 1.0);
16 let val = expr_ref.eval(&slab, &mut map)?;
17 assert!((val - 2.0).abs() < f64::EPSILON);
18
19 map.insert(String::from("x"), 2.5);
20 let val = expr_ref.eval(&slab, &mut map)?;
21 assert!((val - 3.5).abs() < f64::EPSILON);
22
23 // Now, let's re-use the Slab for a new expression.
24 // (This is much cheaper than allocating a new Slab.)
25 // The Slab gets cleared by 'parse()', so you must avoid using
26 // the old expr_ref after parsing the new expression.
27 // One simple way to avoid this problem is to shadow the old variable:
28
29 let expr_ref = parser.parse("x * 10", &mut slab.ps)?.from(&slab.ps);
30
31 let val = expr_ref.eval(&slab, &mut map)?;
32 assert!((val - 25.0).abs() < f64::EPSILON);
33
34 Ok(())
35}
examples/internals.rs (line 9)
4fn main() -> Result<(), fasteval3::Error> {
5 let parser = fasteval3::Parser::new();
6 let mut slab = fasteval3::Slab::new();
7
8 let expr_str = "sin(deg/360 * 2*pi())";
9 let expr_ref = parser.parse(expr_str, &mut slab.ps)?.from(&slab.ps);
10
11 // Let's take a look at the parsed AST inside the Slab:
12 // If you find this structure confusing, take a look at the compilation
13 // AST below because it is simpler.
14 assert_eq!(
15 format!("{:?}", slab.ps),
16 r#"ParseSlab{ exprs:{ 0:Expression { first: EStdFunc(EVar("deg")), pairs: [ExprPair(EDiv, EConstant(360.0)), ExprPair(EMul, EConstant(2.0)), ExprPair(EMul, EStdFunc(EFuncPi))] }, 1:Expression { first: EStdFunc(EFuncSin(ExpressionI(0))), pairs: [] } }, vals:{} }"#
17 );
18 // Pretty-Print:
19 // ParseSlab{
20 // exprs:{
21 // 0:Expression { first: EStdFunc(EVar("deg")),
22 // pairs: [ExprPair(EDiv, EConstant(360.0)),
23 // ExprPair(EMul, EConstant(2.0)),
24 // ExprPair(EMul, EStdFunc(EFuncPi))]
25 // },
26 // 1:Expression { first: EStdFunc(EFuncSin(ExpressionI(0))),
27 // pairs: [] }
28 // },
29 // vals:{}
30 // }
31
32 let compiled = expr_ref.compile(&slab.ps, &mut slab.cs, &mut EmptyNamespace);
33
34 // Let's take a look at the compilation results and the AST inside the Slab:
35 // Notice that compilation has performed constant-folding: 1/360 * 2*pi = 0.017453292519943295
36 // In the results below: IFuncSin(...) represents the sin function.
37 // InstructionI(1) represents the Instruction stored at index 1.
38 // IMul(...) represents the multiplication operator.
39 // 'C(0.017...)' represents a constant value of 0.017... .
40 // IVar("deg") represents a variable named "deg".
41 assert_eq!(format!("{compiled:?}"), "IFuncSin(InstructionI(1))");
42 assert_eq!(
43 format!("{:?}", slab.cs),
44 r#"CompileSlab{ instrs:{ 0:IVar("deg"), 1:IMul(InstructionI(0), C(0.017453292519943295)) } }"#
45 );
46
47 Ok(())
48}
examples/repl.rs (line 110)
54fn repl() {
55 let parser = Parser::new();
56 let mut slab = Slab::new();
57 let mut ns_stack = vec![BTreeMap::new()];
58
59 let stdin = io::stdin();
60
61 loop {
62 eprint!(">>> ");
63 io::stderr().flush().unwrap();
64
65 let mut ans_key = String::from("_");
66
67 let mut line: String = if let Some(Ok(string)) = stdin.lock().lines().next() {
68 string.trim().to_owned()
69 } else {
70 break
71 };
72
73 if line.is_empty() {
74 continue;
75 }
76
77 let pieces: Vec<&str> = line.split_whitespace().collect();
78 if pieces[0] == "let" {
79 if pieces.len() < 4 || pieces[2] != "=" {
80 eprintln!("incorrect 'let' syntax. Should be: let x = ...");
81 continue;
82 }
83 ans_key = pieces[1].to_owned();
84 line = pieces[3..].join(" ");
85 } else if pieces[0] == "push" {
86 ns_stack.push(BTreeMap::new());
87 eprintln!("Entered scope[{}]", ns_stack.len() - 1);
88 continue;
89 } else if pieces[0] == "pop" {
90 let mut return_value = std::f64::NAN;
91 let mut has_return_value = false;
92 if let Some(v) = ns_stack.last().unwrap().get(&ans_key) {
93 return_value = *v;
94 has_return_value = true;
95 }
96
97 ns_stack.pop();
98 eprintln!("Exited scope[{}]", ns_stack.len());
99 if ns_stack.is_empty() {
100 ns_stack.push(BTreeMap::new());
101 } // All scopes have been removed. Add a new one.
102
103 if has_return_value {
104 ns_stack.last_mut().unwrap().insert(ans_key, return_value);
105 }
106
107 continue;
108 }
109
110 let expr_ref = match parser.parse(&line, &mut slab.ps) {
111 Ok(expr_i) => slab.ps.get_expr(expr_i),
112 Err(err) => {
113 eprintln!("parse error: {err}");
114 continue;
115 }
116 };
117
118 let ans = match expr_ref.eval(&slab, &mut ns_stack) {
119 Ok(val) => val,
120 Err(err) => {
121 eprintln!("eval error: {err}");
122 continue;
123 }
124 };
125
126 println!("{ans}");
127 ns_stack.last_mut().unwrap().insert(ans_key, ans);
128 }
129
130 println!();
131}
Sourcepub fn parse_noclear(
&self,
expr_str: &str,
slab: &mut ParseSlab,
) -> Result<ExpressionI, Error>
pub fn parse_noclear( &self, expr_str: &str, slab: &mut ParseSlab, ) -> Result<ExpressionI, Error>
This is exactly the same as parse()
but the Slab
will NOT be cleared.
This is useful in performance-critical sections, when you know that you
already have an empty Slab
.
This function cannot return Result<&Expression> because it would
prolong the mut ref. / That’s why we return an ExpressionI
instead.
§Errors
Will return Err
if length of expr_str
exceeds limit.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Parser
impl RefUnwindSafe for Parser
impl Send for Parser
impl Sync for Parser
impl Unpin for Parser
impl UnwindSafe for Parser
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more