Renames, eof and comment fixes

This commit is contained in:
Dane Johnson 2022-01-31 15:56:08 -06:00
parent cf5d0aa525
commit 3b3501cb57

View File

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