Relops, strs

This commit is contained in:
Dane Johnson 2022-01-31 15:28:55 -06:00
parent 85d13bc26e
commit cf5d0aa525

View File

@ -1,38 +1,51 @@
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub enum Statement { pub enum Statement<'a> {
Assignment(String, Expression), Assignment(&'a str, Expression<'a>),
Funcall(Funcall), Funcall(Funcall<'a>),
} }
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub enum Expression { pub enum Expression<'a> {
Id(String), Id(&'a str),
Num(f64), Num(f64),
Funcall(Funcall) Funcall(Funcall<'a>),
Plus(Box<Expression<'a>>, Box<Expression<'a>>),
Minus(Box<Expression<'a>>, Box<Expression<'a>>),
Mult(Box<Expression<'a>>, Box<Expression<'a>>),
} }
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub struct Funcall { pub struct Funcall<'a> {
id: String, id: &'a str,
args: Vec<Expression>, args: Vec<Expression<'a>>,
} }
peg::parser! { peg::parser! {
grammar deelang_parser() for str { grammar deelang_parser() for str {
pub rule program() -> Vec<Statement> pub rule program() -> Vec<Statement<'input>>
= __* s:statement()* eof() { s } = __* s:statement()* eof() { s }
pub rule statement() -> Statement pub rule statement() -> Statement<'input>
= i:id() "<-" _ e:expr() __* { Statement::Assignment(i, e) } / = i:id() "<-" _ e:expr() __* { Statement::Assignment(i, e) } /
f:funcall() __* { Statement::Funcall(f)} f:funcall() __* { Statement::Funcall(f)}
rule expr() -> Expression rule expr() -> Expression<'input> = precedence!{
= f:funcall() _ { Expression::Funcall(f) } / e1:(@) "+" _ e2:@ { Expression::Plus(Box::new(e1), Box::new(e2)) }
i:id() _ { Expression::Id(i) } / e1:(@) "-" _ e2:@ { Expression::Minus(Box::new(e1), Box::new(e2)) }
n:num() _ { Expression::Num(n) } --
rule id() -> String e1:(@) "*" _ e2:@ { Expression::Mult(Box::new(e1), Box::new(e2)) }
= i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() } --
"(" _ e:expr() ")" _ { e }
f:funcall() _ { Expression::Funcall(f) }
i:id() _ { Expression::Id(i) }
n:num() _ { Expression::Num(n) }
}
rule id() -> &'input str
= i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i }
rule num() -> f64 rule num() -> f64
= n:$(digit()+ "."? digit()* / "." digit()+) _ { n.to_string().parse().unwrap() } = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() }
rule funcall() -> Funcall rule funcall() -> Funcall<'input>
= i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Funcall{id: i, args: e} } = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Funcall{id: i, args: e} }
rule letter() rule letter()
= ['A'..='Z'] / ['a'..='z'] = ['A'..='Z'] / ['a'..='z']
rule digit() rule digit()
@ -65,10 +78,10 @@ mod test {
#[test] #[test]
fn test_funcall() { fn test_funcall() {
let expected = vec![ let expected = vec![
Statement::Funcall(Funcall{id: "pear".to_string(), args: vec![]}), Statement::Funcall(Funcall{id: "pear", args: vec![]}),
Statement::Funcall(Funcall { Statement::Funcall(Funcall {
id: "pear".to_string(), id: "pear",
args: vec![Expression::Id("x".to_string()), Expression::Id("y".to_string())], args: vec![Expression::Id("x"), Expression::Id("y")],
}) })
]; ];
let prgm = r"pear() let prgm = r"pear()
@ -81,15 +94,44 @@ 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".to_string(), Statement::Assignment("apple",
Expression::Num(1.0)), Expression::Num(1.0)),
Statement::Assignment("apple".to_string(), Statement::Assignment("apple",
Expression::Funcall(Funcall { Expression::Funcall(Funcall {
id: "pear".to_string(), id: "pear",
args: vec![ args: vec![
Expression::Id("x".to_string()), Expression::Id("x"),
Expression::Id("y".to_string()) Expression::Id("y"),
]}))]; ]})),
];
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
}
#[test]
fn test_operators() {
let prgm = r"three <- 1 + 2
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))
)),
Statement::Assignment("one",
Expression::Minus(
Box::new(Expression::Num(3.0)),
Box::new(Expression::Num(2.0))
)),
Statement::Assignment("four",
Expression::Mult(
Box::new(Expression::Minus(
Box::new(Expression::Num(3.0)),
Box::new(Expression::Num(1.0)),
)),
Box::new(Expression::Num(2.0)),
))
];
assert_eq!(deelang_parser::program(prgm).unwrap(), expected); assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
} }
} }