diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 9dad759..f0eb719 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -1,42 +1,44 @@ #[derive(Debug,PartialEq)] -pub enum Statement<'a> { - Assignment(&'a str, Expression<'a>), +pub enum Stmt<'a> { + Assignment(&'a str, Expr<'a>), Funcall(Funcall<'a>), } #[derive(Debug,PartialEq)] -pub enum Expression<'a> { +pub enum Expr<'a> { Id(&'a str), Num(f64), Funcall(Funcall<'a>), - Plus(Box>, Box>), - Minus(Box>, Box>), - Mult(Box>, Box>), + Plus(Box>, Box>), + Minus(Box>, Box>), + Mult(Box>, Box>), + Div(Box>, Box>), } #[derive(Debug,PartialEq)] pub struct Funcall<'a> { id: &'a str, - args: Vec>, + args: Vec>, } peg::parser! { grammar deelang_parser() for str { - pub rule program() -> Vec> - = __* s:statement()* eof() { s } - pub rule statement() -> Statement<'input> - = i:id() "<-" _ e:expr() __* { Statement::Assignment(i, e) } / - f:funcall() __* { Statement::Funcall(f)} - 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)) } + pub rule program() -> Vec> + = __* 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!{ + e1:(@) "+" _ e2:@ { Expr::Plus(Box::new(e1), Box::new(e2)) } + e1:(@) "-" _ e2:@ { Expr::Minus(Box::new(e1), Box::new(e2)) } -- - e1:(@) "*" _ e2:@ { Expression::Mult(Box::new(e1), Box::new(e2)) } + e1:(@) "*" _ e2:@ { Expr::Mult(Box::new(e1), Box::new(e2)) } + e1:(@) "/" _ e2:@ { Expr::Div(Box::new(e1), Box::new(e2)) } -- "(" _ e:expr() ")" _ { e } - f:funcall() _ { Expression::Funcall(f) } - i:id() _ { Expression::Id(i) } - n:num() _ { Expression::Num(n) } + f:funcall() _ { Expr::Funcall(f) } + i:id() _ { Expr::Id(i) } + n:num() _ { Expr::Num(n) } } rule id() -> &'input str @@ -50,10 +52,12 @@ peg::parser! { = ['A'..='Z'] / ['a'..='z'] rule digit() = ['0'..='9'] + rule stop() + = __+ / eof() rule _ // Non-meaningful whitespace = ['\t'|' ']* - rule __ // Blank lines and lines containing only comments - = comment() &eof() / comment() newline() / newline() + rule __ // End Of Statement (comment, newline, eof, TODO semicolon) + = comment()? newline() / comment() &eof() rule comment() = "#" (!newline() [_])* &(newline() / eof()) rule newline() @@ -70,18 +74,20 @@ mod test { #[test] fn test_comments() { - let expected = vec![]; - let prgm = "## This is a comment"; + let prgm = "## This is a comment +apple <- 1 ## This is too +## This comment ends the file"; + let expected = vec![Stmt::Assignment("apple", Expr::Num(1.0))]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); } #[test] fn test_funcall() { let expected = vec![ - Statement::Funcall(Funcall{id: "pear", args: vec![]}), - Statement::Funcall(Funcall { + Stmt::Funcall(Funcall{id: "pear", args: vec![]}), + Stmt::Funcall(Funcall { id: "pear", - args: vec![Expression::Id("x"), Expression::Id("y")], + args: vec![Expr::Id("x"), Expr::Id("y")], }) ]; let prgm = r"pear() @@ -94,14 +100,14 @@ pear(x, y)"; let prgm = r"apple <- 1 apple <- pear(x, y)"; let expected = vec![ - Statement::Assignment("apple", - Expression::Num(1.0)), - Statement::Assignment("apple", - Expression::Funcall(Funcall { + Stmt::Assignment("apple", + Expr::Num(1.0)), + Stmt::Assignment("apple", + Expr::Funcall(Funcall { id: "pear", args: vec![ - Expression::Id("x"), - Expression::Id("y"), + Expr::Id("x"), + Expr::Id("y"), ]})), ]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); @@ -113,23 +119,23 @@ apple <- pear(x, y)"; 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)) + Stmt::Assignment("three", + Expr::Plus( + Box::new(Expr::Num(1.0)), + Box::new(Expr::Num(2.0)) )), - Statement::Assignment("one", - Expression::Minus( - Box::new(Expression::Num(3.0)), - Box::new(Expression::Num(2.0)) + Stmt::Assignment("one", + Expr::Minus( + Box::new(Expr::Num(3.0)), + Box::new(Expr::Num(2.0)) )), - Statement::Assignment("four", - Expression::Mult( - Box::new(Expression::Minus( - Box::new(Expression::Num(3.0)), - Box::new(Expression::Num(1.0)), + Stmt::Assignment("four", + Expr::Mult( + Box::new(Expr::Minus( + Box::new(Expr::Num(3.0)), + Box::new(Expr::Num(1.0)), )), - Box::new(Expression::Num(2.0)), + Box::new(Expr::Num(2.0)), )) ]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected);