enh(generic-snmp): the lexer works with the grammar now

This commit is contained in:
David Boucher 2025-04-15 15:46:18 +02:00
parent 29d8949621
commit 1ecfbb7d11
3 changed files with 83 additions and 62 deletions

View File

@ -3,7 +3,7 @@ use std::str;
pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>; pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone)]
pub enum Tok { pub enum Tok {
Num(f32), Num(f32),
Id, Id,

View File

@ -1,4 +1,4 @@
mod lexer; pub mod lexer;
use lalrpop_util::lalrpop_mod; use lalrpop_util::lalrpop_mod;
use serde::Deserialize; use serde::Deserialize;
@ -45,64 +45,91 @@ mod Test {
#[test] #[test]
fn term() { fn term() {
assert!(grammar::ExprParser::new().parse("132").is_ok()); let lexer = lexer::Lexer::new("123");
assert!(grammar::ExprParser::new().parse("((132))").is_ok()); let res = grammar::ExprParser::new().parse(lexer);
assert!(grammar::ExprParser::new().parse("((132)))").is_err()); 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] #[test]
fn sum() { 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.is_ok());
assert!(res.unwrap() == 3_f32); assert!(res.unwrap() == 3_f32);
let res = grammar::ExprParser::new().parse("1 + 2 + 3");
assert!(res.is_ok()); let lexer = lexer::Lexer::new("1 + 2 - 3");
assert!(res.unwrap() == 6_f32); let res = grammar::ExprParser::new().parse(lexer);
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");
assert!(res.is_ok()); assert!(res.is_ok());
assert!(res.unwrap() == 0_f32); 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] #[test]
fn product() { 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.is_ok());
assert!(res.unwrap() == 6_f32); 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.is_ok());
assert!(res.unwrap() == 24_f32); 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.is_ok());
assert!(res.unwrap() == 3_f32); assert!(res.unwrap() == 3_f32);
// let res = grammar::ProductParser::new().parse("2 / 0"); // We have an issue with 2/0, I know it but we'll fix it later.
// assert!(res.is_err());
} }
#[test] #[test]
fn sum_product() { fn sum_product() {
let res = grammar::ExprParser::new().parse("1 + 2 * 3"); let lexer = lexer::Lexer::new("1 + (3 + 2 * 3) / 3");
assert!(res.is_ok()); let res = grammar::ExprParser::new().parse(lexer);
assert!(res.unwrap() == 7_f32);
let res = grammar::ExprParser::new().parse("1 + (3 + 2 * 3) / 3");
assert!(res.is_ok()); assert!(res.is_ok());
assert!(res.unwrap() == 4_f32); assert!(res.unwrap() == 4_f32);
} }
#[test] #[test]
fn function() { fn function() {
let res = grammar::ExprParser::new().parse("Average(1, 2, 3)"); // let res = grammar::ExprParser::new().parse("Average(1, 2, 3)");
assert!(res.is_ok()); // assert!(res.is_ok());
assert!(res.unwrap() == 2_f32); // assert!(res.unwrap() == 2_f32);
//
let res = grammar::ExprParser::new().parse("Average(1 + 2 * 2, 3, 4)"); // let res = grammar::ExprParser::new().parse("Average(1 + 2 * 2, 3, 4)");
assert!(res.is_ok()); // assert!(res.is_ok());
assert!(res.unwrap() == 4_f32); // assert!(res.unwrap() == 4_f32);
} }
} }

View File

@ -1,44 +1,38 @@
use std::str::FromStr; use std::str::FromStr;
use compute::lexer;
grammar; grammar;
Sum: f32 = { pub Expr: f32 = {
<s:Sum> "+" <p:Product> => s + p, <s:Expr> "+" <p:Product> => s + p,
<s:Sum> "-" <p:Product> => s - p, <s:Expr> "-" <p:Product> => s - p,
<p:Product> => p, <p:Product> => p,
}; };
Product: f32 = { pub Product: f32 = {
<p:Product> "*" <t:Expr> => p * t, <s:Product> "*" <v:Term> => s * v,
<p:Product> "/" <t:Expr> => p / t, <s:Product> "/" <v:Term> => s / v,
<t:Expr> => t, <v:Term> => v,
}; };
Args = Comma<Sum>; // (0) pub Term: f32 = {
"num" => <>,
"(" <v:Expr> ")" => v,
};
Comma<T>: Vec<f32> = { // (1) extern {
<mut v:(<T> ",")*> <e:T?> => match e { // (2) type Location = usize;
None => v, type Error = lexer::LexicalError;
Some(e) => {
v.push(e); // ...
v
} 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(<f32>)
} }
};
pub Expr: f32 = {
<n:Num> => n,
"(" <t:Sum> ")" => t,
"Average" "(" <a:Args> ")" => { let sum:f32 = a.iter().sum(); sum / a.len() as f32 }
};
match {
r"-?[0-9.]+" => NUM,
} else {
r"\w+" => ID,
_
} }
Num: f32 = <s:NUM> => f32::from_str(s).unwrap();
Identifier: String = <s:ID> => s.to_string();