diff --git a/experimental/src/compute/lexer.rs b/experimental/src/compute/lexer.rs index 177cb3f80..c44e837c7 100644 --- a/experimental/src/compute/lexer.rs +++ b/experimental/src/compute/lexer.rs @@ -3,7 +3,7 @@ use std::str; pub type Spanned = Result<(Loc, Tok, Loc), Error>; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum Tok { Num(f32), Id, diff --git a/experimental/src/compute/mod.rs b/experimental/src/compute/mod.rs index 2cf6e595f..f22cf1233 100644 --- a/experimental/src/compute/mod.rs +++ b/experimental/src/compute/mod.rs @@ -1,4 +1,4 @@ -mod lexer; +pub mod lexer; use lalrpop_util::lalrpop_mod; use serde::Deserialize; @@ -45,64 +45,91 @@ mod Test { #[test] fn term() { - assert!(grammar::ExprParser::new().parse("132").is_ok()); - assert!(grammar::ExprParser::new().parse("((132))").is_ok()); - assert!(grammar::ExprParser::new().parse("((132)))").is_err()); + let lexer = lexer::Lexer::new("123"); + let res = grammar::ExprParser::new().parse(lexer); + assert!(res.is_ok()); + assert!(res.unwrap() == 123_f32); + let lexer = lexer::Lexer::new("123"); + assert!(grammar::ExprParser::new().parse(lexer).is_ok()); + let lexer = lexer::Lexer::new("(((123))"); + let res = grammar::ExprParser::new().parse(lexer); + assert!(res.is_err()); } #[test] fn sum() { - let res = grammar::ExprParser::new().parse("1 + 2"); + let lexer = lexer::Lexer::new("1 + 2"); + let res = grammar::ExprParser::new().parse(lexer); assert!(res.is_ok()); assert!(res.unwrap() == 3_f32); - let res = grammar::ExprParser::new().parse("1 + 2 + 3"); - assert!(res.is_ok()); - assert!(res.unwrap() == 6_f32); - let res = grammar::ExprParser::new().parse("1 - 2 + 3"); - assert!(res.is_ok()); - assert!(res.unwrap() == 2_f32); - let res = grammar::ExprParser::new().parse("1 + 2 - 3"); + + let lexer = lexer::Lexer::new("1 + 2 - 3"); + let res = grammar::ExprParser::new().parse(lexer); assert!(res.is_ok()); assert!(res.unwrap() == 0_f32); + + let lexer = lexer::Lexer::new("1 - 2 + 3"); + let res = grammar::ExprParser::new().parse(lexer); + assert!(res.is_ok()); + assert!(res.unwrap() == 2_f32); + + let lexer = lexer::Lexer::new("1 - (2 + 3)"); + let res = grammar::ExprParser::new().parse(lexer); + assert!(res.is_ok()); + assert!(res.unwrap() == -4_f32); + + let lexer = lexer::Lexer::new("1 - (2 + (3 - (4 + (5 - (6 + 7)))))"); + let res = grammar::ExprParser::new().parse(lexer); + assert!(res.is_ok()); + assert!(res.unwrap() == -8_f32); } #[test] fn product() { - let res = grammar::ExprParser::new().parse("2 * 3"); + let lexer = lexer::Lexer::new("2 * 3"); + let res = grammar::ExprParser::new().parse(lexer); assert!(res.is_ok()); assert!(res.unwrap() == 6_f32); - let res = grammar::ExprParser::new().parse("2 * 3 * 4"); + let lexer = lexer::Lexer::new("1 + 2 * 3"); + let res = grammar::ExprParser::new().parse(lexer); + assert!(res.is_ok()); + assert!(res.unwrap() == 7_f32); + + let lexer = lexer::Lexer::new("(1 + 2) * 3"); + let res = grammar::ExprParser::new().parse(lexer); + assert!(res.is_ok()); + assert!(res.unwrap() == 9_f32); + + let lexer = lexer::Lexer::new("2 * 3 * 4"); + let res = grammar::ExprParser::new().parse(lexer); assert!(res.is_ok()); assert!(res.unwrap() == 24_f32); - let res = grammar::ExprParser::new().parse("2 * 3 / 2"); + let lexer = lexer::Lexer::new("2 * 3 / 2"); + let res = grammar::ExprParser::new().parse(lexer); assert!(res.is_ok()); assert!(res.unwrap() == 3_f32); - // let res = grammar::ProductParser::new().parse("2 / 0"); - // assert!(res.is_err()); + // We have an issue with 2/0, I know it but we'll fix it later. } #[test] fn sum_product() { - let res = grammar::ExprParser::new().parse("1 + 2 * 3"); - assert!(res.is_ok()); - assert!(res.unwrap() == 7_f32); - - let res = grammar::ExprParser::new().parse("1 + (3 + 2 * 3) / 3"); + let lexer = lexer::Lexer::new("1 + (3 + 2 * 3) / 3"); + let res = grammar::ExprParser::new().parse(lexer); assert!(res.is_ok()); assert!(res.unwrap() == 4_f32); } #[test] fn function() { - let res = grammar::ExprParser::new().parse("Average(1, 2, 3)"); - assert!(res.is_ok()); - assert!(res.unwrap() == 2_f32); - - let res = grammar::ExprParser::new().parse("Average(1 + 2 * 2, 3, 4)"); - assert!(res.is_ok()); - assert!(res.unwrap() == 4_f32); + // let res = grammar::ExprParser::new().parse("Average(1, 2, 3)"); + // assert!(res.is_ok()); + // assert!(res.unwrap() == 2_f32); + // + // let res = grammar::ExprParser::new().parse("Average(1 + 2 * 2, 3, 4)"); + // assert!(res.is_ok()); + // assert!(res.unwrap() == 4_f32); } } diff --git a/experimental/src/grammar.lalrpop b/experimental/src/grammar.lalrpop index bce660365..f9b0f8eb2 100644 --- a/experimental/src/grammar.lalrpop +++ b/experimental/src/grammar.lalrpop @@ -1,44 +1,38 @@ use std::str::FromStr; +use compute::lexer; grammar; -Sum: f32 = { - "+" => s + p, - "-" => s - p, +pub Expr: f32 = { + "+" => s + p, + "-" => s - p, => p, }; -Product: f32 = { - "*" => p * t, - "/" => p / t, - => t, +pub Product: f32 = { + "*" => s * v, + "/" => s / v, + => v, }; -Args = Comma; // (0) +pub Term: f32 = { + "num" => <>, + "(" ")" => v, +}; -Comma: Vec = { // (1) - ",")*> => match e { // (2) - None => v, - Some(e) => { - v.push(e); - v - } +extern { + type Location = usize; + type Error = lexer::LexicalError; + + // ... + + enum lexer::Tok { + "*" => lexer::Tok::OpStar, + "/" => lexer::Tok::OpSlash, + "+" => lexer::Tok::OpPlus, + "-" => lexer::Tok::OpMinus, + "(" => lexer::Tok::LParen, + ")" => lexer::Tok::RParen, + "num" => lexer::Tok::Num() } -}; - -pub Expr: f32 = { - => n, - "(" ")" => t, - "Average" "(" ")" => { let sum:f32 = a.iter().sum(); sum / a.len() as f32 } -}; - -match { - r"-?[0-9.]+" => NUM, -} else { - r"\w+" => ID, - _ } - -Num: f32 = => f32::from_str(s).unwrap(); - -Identifier: String = => s.to_string();