diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 0f41eeb..52b5ffd 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -9,13 +9,19 @@ pub enum Expr<'a> { Id(&'a str), Num(f64), Funcall(&'a str, Vec>), - Funcdef(Option<&'a str>, Vec>), + Funcdef(Option<&'a str>, Fun<'a>), Plus(Box>, Box>), Minus(Box>, Box>), Mult(Box>, Box>), Div(Box>, Box>), } +#[derive(Debug,PartialEq)] +pub enum Fun<'a> { + Oner(Box>), + Block(Vec>), +} + peg::parser! { grammar deelang_parser() for str { pub rule program() -> Vec> @@ -31,8 +37,8 @@ peg::parser! { e1:(@) "/" _ e2:@ { Expr::Div(Box::new(e1), Box::new(e2)) } -- "(" _ e:expr() ")" _ { e } - f:funcall() _ { f } - i:id()? "->" _ s:stmt() { Expr::Funcdef(i, vec![s]) } + f:funcall() { f } + f:funcdef() { f } i:id() _ { Expr::Id(i) } n:num() _ { Expr::Num(n) } } @@ -43,6 +49,9 @@ peg::parser! { = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() } rule funcall() -> Expr<'input> = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } + rule funcdef() -> Expr<'input> + = i:id()? "->" _ e:expr() { Expr::Funcdef(i, Fun::Oner(Box::new(e))) } / + i:id()? "->" _ stop() indent() __* s:stmt()+ dedent() { Expr::Funcdef(i, Fun::Block(s)) } rule letter() = ['A'..='Z'] / ['a'..='z'] @@ -50,6 +59,10 @@ peg::parser! { = ['0'..='9'] rule stop() = __+ / eof() + rule indent() + = ">>>" + rule dedent() + = "<<<" rule _ // Non-meaningful whitespace = ['\t'|' ']* rule __ // End Of Statement (comment, newline, eof, TODO semicolon) @@ -155,14 +168,52 @@ four <- (3 - 1) * 2"; #[test] fn test_funcdef() { let prgm = r"foo <- -> bar() -"; +foo <- -> +>>> +bar() +baz() +<<< +foo <- x -> y -> x * y"; let expected = vec![ - Stmt::Assignment("foo", - Expr::Funcdef( - None, - vec![ - Stmt::Funcall(Expr::Funcall("bar", vec![])), - ]) + Stmt::Assignment( + "foo", + Expr::Funcdef( + None, + Fun::Oner( + Box::new(Expr::Funcall("bar", vec![])), + ) + ) + ), + Stmt::Assignment( + "foo", + Expr::Funcdef( + None, + Fun::Block(vec![ + Stmt::Funcall(Expr::Funcall("bar", vec![])), + Stmt::Funcall(Expr::Funcall("baz", vec![])), + ]) + ) + ), + Stmt::Assignment( + "foo", + Expr::Funcdef( + Some("x"), + Fun::Oner( + Box::new( + Expr::Funcdef( + Some("y"), + Fun::Oner( + Box::new( + Expr::Mult( + Box::new(Expr::Id("x")), + Box::new(Expr::Id("y")), + ) + ) + ) + ) + ) + ) + ) ) ];