From 2e04bcdfc1c906ff7d2b0b264c13f1abead7f52d Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Mon, 31 Jan 2022 17:16:32 -0600 Subject: [PATCH] One line functions --- rust/src/parser.rs | 71 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/rust/src/parser.rs b/rust/src/parser.rs index f0eb719..8589845 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -1,34 +1,29 @@ #[derive(Debug,PartialEq)] pub enum Stmt<'a> { Assignment(&'a str, Expr<'a>), - Funcall(Funcall<'a>), + Funcall(Expr<'a>), } #[derive(Debug,PartialEq)] pub enum Expr<'a> { Id(&'a str), Num(f64), - Funcall(Funcall<'a>), + Funcall(&'a str, Vec>), + Funcdef(Option<&'a str>, Vec>), Plus(Box>, Box>), Minus(Box>, Box>), Mult(Box>, Box>), Div(Box>, Box>), } -#[derive(Debug,PartialEq)] -pub struct Funcall<'a> { - id: &'a str, - args: Vec>, -} - peg::parser! { grammar deelang_parser() for str { pub rule program() -> Vec> - = __* s:stmt()* { s } + = __* s:stmt()* { s } pub rule stmt() -> Stmt<'input> = i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) } / f:funcall() stop() { Stmt::Funcall(f) } - rule expr() -> Expr<'input> = precedence!{ + rule expr() -> Expr<'input> = precedence! { e1:(@) "+" _ e2:@ { Expr::Plus(Box::new(e1), Box::new(e2)) } e1:(@) "-" _ e2:@ { Expr::Minus(Box::new(e1), Box::new(e2)) } -- @@ -36,7 +31,8 @@ peg::parser! { e1:(@) "/" _ e2:@ { Expr::Div(Box::new(e1), Box::new(e2)) } -- "(" _ e:expr() ")" _ { e } - f:funcall() _ { Expr::Funcall(f) } + f:funcall() _ { f } + i:id()? "->" _ s:stmt() { Expr::Funcdef(i, vec![s]) } i:id() _ { Expr::Id(i) } n:num() _ { Expr::Num(n) } } @@ -45,8 +41,8 @@ peg::parser! { = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i } rule num() -> f64 = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() } - rule funcall() -> Funcall<'input> - = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Funcall{id: i, args: e} } + rule funcall() -> Expr<'input> + = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } rule letter() = ['A'..='Z'] / ['a'..='z'] @@ -84,11 +80,10 @@ apple <- 1 ## This is too #[test] fn test_funcall() { let expected = vec![ - Stmt::Funcall(Funcall{id: "pear", args: vec![]}), - Stmt::Funcall(Funcall { - id: "pear", - args: vec![Expr::Id("x"), Expr::Id("y")], - }) + Stmt::Funcall(Expr::Funcall("pear", vec![])), + Stmt::Funcall(Expr::Funcall("pear", + vec![Expr::Id("x"), Expr::Id("y")], + )) ]; let prgm = r"pear() pear(x, y)"; @@ -103,12 +98,11 @@ apple <- pear(x, y)"; Stmt::Assignment("apple", Expr::Num(1.0)), Stmt::Assignment("apple", - Expr::Funcall(Funcall { - id: "pear", - args: vec![ + Expr::Funcall("pear", + vec![ Expr::Id("x"), Expr::Id("y"), - ]})), + ])), ]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); } @@ -140,4 +134,37 @@ four <- (3 - 1) * 2"; ]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); } + + #[test] + fn test_compound_expression() { + let prgm = "apple <- pear(x, y) + z"; + let expected = vec![ + Stmt::Assignment("apple", + Expr::Plus( + Box::new(Expr::Funcall( + "pear", + vec![Expr::Id("x"), Expr::Id("y")], + )), + Box::new(Expr::Id("z")) + ) + ), + ]; + assert_eq!(deelang_parser::program(prgm).unwrap(), expected); + } + + #[test] + fn test_funcdef() { + let prgm = r"foo <- -> bar()"; + let expected = vec![ + Stmt::Assignment("foo", + Expr::Funcdef( + None, + vec![ + Stmt::Funcall(Expr::Funcall("bar", vec![])), + ]) + ) + ]; + + assert_eq!(deelang_parser::program(prgm).unwrap(), expected); + } }