diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 79c5857..8e2fa46 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -1,30 +1,30 @@ #[derive(Debug,PartialEq)] -pub enum Stmt<'a> { - Assignment(&'a str, Expr<'a>), - Funcall(Expr<'a>), +pub enum Stmt { + Assignment(String, Expr), + Funcall(Expr), } #[derive(Debug,PartialEq)] -pub enum Expr<'a> { - Id(&'a str), +pub enum Expr { + Id(String), Num(f64), - Funcall(&'a str, Vec>), - Funcdef(Option<&'a str>, Box>), - Plus(Box>, Box>), - Minus(Box>, Box>), - Mult(Box>, Box>), - Div(Box>, Box>), - Block(Vec>), + Funcall(String, Vec), + Funcdef(Option, Box), + Plus(Box, Box), + Minus(Box, Box), + Mult(Box, Box), + Div(Box, Box), + Block(Vec), } peg::parser! { grammar deelang_parser() for str { - pub rule program() -> Vec> + pub rule program() -> Vec = __* s:stmt()* { s } - pub rule stmt() -> Stmt<'input> + pub rule stmt() -> Stmt = i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) } / - f:funcall() stop() { Stmt::Funcall(f) } - rule expr() -> Expr<'input> = precedence! { + f:funcall() stop() { Stmt::Funcall(f) } + rule expr() -> Expr = precedence! { e1:(@) "+" _ e2:@ { Expr::Plus(Box::new(e1), Box::new(e2)) } e1:(@) "-" _ e2:@ { Expr::Minus(Box::new(e1), Box::new(e2)) } -- @@ -37,16 +37,16 @@ peg::parser! { i:id() _ { Expr::Id(i) } n:num() _ { Expr::Num(n) } } - rule block() -> Expr<'input> + rule block() -> Expr = stop() indent() __* s:stmt()+ dedent() { Expr::Block(s) } - rule id() -> &'input str - = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i } + rule id() -> String + = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() } rule num() -> f64 = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() } - rule funcall() -> Expr<'input> + rule funcall() -> Expr = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } - rule funcdef() -> Expr<'input> + rule funcdef() -> Expr = i:id()? "->" _ e:(expr() / block()) { Expr::Funcdef(i, Box::new(e)) } rule letter() @@ -104,18 +104,14 @@ fn preprocess(input: &str) -> String { output } -pub fn parse<'a>(prgm: &'a str) -> Vec> { - let prgm = preprocess(prgm); - let prgm = Box::new(prgm); - let prgm = Box::leak(prgm); - deelang_parser::program(prgm).unwrap() +pub fn parse(prgm: &str) -> Vec { + let prgm = preprocess(&prgm); + deelang_parser::program(&prgm).unwrap() } -pub fn parse_stmt<'a>(stmt: &'a str) -> Stmt<'a> { - let stmt = preprocess(stmt); - let stmt = Box::new(stmt); - let stmt = Box::leak(stmt); - deelang_parser::stmt(stmt).unwrap() +pub fn parse_stmt(stmt: &str) -> Stmt { + let stmt = preprocess(&stmt); + deelang_parser::stmt(&stmt).unwrap() } @@ -128,16 +124,16 @@ mod test { let prgm = r"## This is a comment apple <- 1 ## This is too ## This comment ends the file"; - let expected = vec![Stmt::Assignment("apple", Expr::Num(1.0))]; + let expected = vec![Stmt::Assignment("apple".to_string(), Expr::Num(1.0))]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); } #[test] fn test_funcall() { let expected = vec![ - Stmt::Funcall(Expr::Funcall("pear", vec![])), - Stmt::Funcall(Expr::Funcall("pear", - vec![Expr::Id("x"), Expr::Id("y")], + Stmt::Funcall(Expr::Funcall("pear".to_string(), vec![])), + Stmt::Funcall(Expr::Funcall("pear".to_string(), + vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())], )) ]; let prgm = r"pear() @@ -150,13 +146,13 @@ pear(x, y)"; let prgm = r"apple <- 1 apple <- pear(x, y)"; let expected = vec![ - Stmt::Assignment("apple", + Stmt::Assignment("apple".to_string(), Expr::Num(1.0)), - Stmt::Assignment("apple", - Expr::Funcall("pear", + Stmt::Assignment("apple".to_string(), + Expr::Funcall("pear".to_string(), vec![ - Expr::Id("x"), - Expr::Id("y"), + Expr::Id("x".to_string()), + Expr::Id("y".to_string()), ])), ]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); @@ -168,17 +164,17 @@ apple <- pear(x, y)"; one <- 3 - 2 four <- (3 - 1) * 2"; let expected = vec![ - Stmt::Assignment("three", + Stmt::Assignment("three".to_string(), Expr::Plus( Box::new(Expr::Num(1.0)), Box::new(Expr::Num(2.0)) )), - Stmt::Assignment("one", + Stmt::Assignment("one".to_string(), Expr::Minus( Box::new(Expr::Num(3.0)), Box::new(Expr::Num(2.0)) )), - Stmt::Assignment("four", + Stmt::Assignment("four".to_string(), Expr::Mult( Box::new(Expr::Minus( Box::new(Expr::Num(3.0)), @@ -194,13 +190,13 @@ four <- (3 - 1) * 2"; fn test_compound_expression() { let prgm = "apple <- pear(x, y) + z"; let expected = vec![ - Stmt::Assignment("apple", + Stmt::Assignment("apple".to_string(), Expr::Plus( Box::new(Expr::Funcall( - "pear", - vec![Expr::Id("x"), Expr::Id("y")], + "pear".to_string(), + vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())], )), - Box::new(Expr::Id("z")) + Box::new(Expr::Id("z".to_string())) ) ), ]; @@ -218,33 +214,33 @@ baz() foo <- x -> y -> x * y"; let expected = vec![ Stmt::Assignment( - "foo", + "foo".to_string(), Expr::Funcdef( None, - Box::new(Expr::Funcall("bar", vec![])), + Box::new(Expr::Funcall("bar".to_string(), vec![])), ) ), Stmt::Assignment( - "foo", + "foo".to_string(), Expr::Funcdef( None, Box::new(Expr::Block(vec![ - Stmt::Funcall(Expr::Funcall("bar", vec![])), - Stmt::Funcall(Expr::Funcall("baz", vec![])), + Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])), + Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])), ])) ) ), Stmt::Assignment( - "foo", + "foo".to_string(), Expr::Funcdef( - Some("x"), + Some("x".to_string()), Box::new( Expr::Funcdef( - Some("y"), + Some("y".to_string()), Box::new( Expr::Mult( - Box::new(Expr::Id("x")), - Box::new(Expr::Id("y")), + Box::new(Expr::Id("x".to_string())), + Box::new(Expr::Id("y".to_string())), ) ) )