From cf5d0aa525512b0eb4d358a35607391d193da9c0 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Mon, 31 Jan 2022 15:28:55 -0600 Subject: [PATCH] Relops, strs --- rust/src/parser.rs | 98 +++++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/rust/src/parser.rs b/rust/src/parser.rs index f2c9ce3..9dad759 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -1,38 +1,51 @@ #[derive(Debug,PartialEq)] -pub enum Statement { - Assignment(String, Expression), - Funcall(Funcall), +pub enum Statement<'a> { + Assignment(&'a str, Expression<'a>), + Funcall(Funcall<'a>), } #[derive(Debug,PartialEq)] -pub enum Expression { - Id(String), +pub enum Expression<'a> { + Id(&'a str), Num(f64), - Funcall(Funcall) + Funcall(Funcall<'a>), + Plus(Box>, Box>), + Minus(Box>, Box>), + Mult(Box>, Box>), } + #[derive(Debug,PartialEq)] -pub struct Funcall { - id: String, - args: Vec, +pub struct Funcall<'a> { + id: &'a str, + args: Vec>, } peg::parser! { grammar deelang_parser() for str { - pub rule program() -> Vec + pub rule program() -> Vec> = __* s:statement()* eof() { s } - pub rule statement() -> Statement + pub rule statement() -> Statement<'input> = i:id() "<-" _ e:expr() __* { Statement::Assignment(i, e) } / f:funcall() __* { Statement::Funcall(f)} - rule expr() -> Expression - = f:funcall() _ { Expression::Funcall(f) } / - i:id() _ { Expression::Id(i) } / - n:num() _ { Expression::Num(n) } - rule id() -> String - = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() } + rule expr() -> Expression<'input> = precedence!{ + e1:(@) "+" _ e2:@ { Expression::Plus(Box::new(e1), Box::new(e2)) } + e1:(@) "-" _ e2:@ { Expression::Minus(Box::new(e1), Box::new(e2)) } + -- + e1:(@) "*" _ e2:@ { Expression::Mult(Box::new(e1), Box::new(e2)) } + -- + "(" _ e:expr() ")" _ { e } + f:funcall() _ { Expression::Funcall(f) } + i:id() _ { Expression::Id(i) } + n:num() _ { Expression::Num(n) } + } + + rule id() -> &'input str + = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i } rule num() -> f64 - = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.to_string().parse().unwrap() } - rule funcall() -> Funcall + = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() } + rule funcall() -> Funcall<'input> = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Funcall{id: i, args: e} } + rule letter() = ['A'..='Z'] / ['a'..='z'] rule digit() @@ -65,10 +78,10 @@ mod test { #[test] fn test_funcall() { let expected = vec![ - Statement::Funcall(Funcall{id: "pear".to_string(), args: vec![]}), + Statement::Funcall(Funcall{id: "pear", args: vec![]}), Statement::Funcall(Funcall { - id: "pear".to_string(), - args: vec![Expression::Id("x".to_string()), Expression::Id("y".to_string())], + id: "pear", + args: vec![Expression::Id("x"), Expression::Id("y")], }) ]; let prgm = r"pear() @@ -81,15 +94,44 @@ pear(x, y)"; let prgm = r"apple <- 1 apple <- pear(x, y)"; let expected = vec![ - Statement::Assignment("apple".to_string(), + Statement::Assignment("apple", Expression::Num(1.0)), - Statement::Assignment("apple".to_string(), + Statement::Assignment("apple", Expression::Funcall(Funcall { - id: "pear".to_string(), + id: "pear", args: vec![ - Expression::Id("x".to_string()), - Expression::Id("y".to_string()) - ]}))]; + Expression::Id("x"), + Expression::Id("y"), + ]})), + ]; + assert_eq!(deelang_parser::program(prgm).unwrap(), expected); + } + + #[test] + fn test_operators() { + let prgm = r"three <- 1 + 2 +one <- 3 - 2 +four <- (3 - 1) * 2"; + let expected = vec![ + Statement::Assignment("three", + Expression::Plus( + Box::new(Expression::Num(1.0)), + Box::new(Expression::Num(2.0)) + )), + Statement::Assignment("one", + Expression::Minus( + Box::new(Expression::Num(3.0)), + Box::new(Expression::Num(2.0)) + )), + Statement::Assignment("four", + Expression::Mult( + Box::new(Expression::Minus( + Box::new(Expression::Num(3.0)), + Box::new(Expression::Num(1.0)), + )), + Box::new(Expression::Num(2.0)), + )) + ]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); } }