Conditionals
This commit is contained in:
parent
96d446dde3
commit
51531b806f
@ -1,10 +1,11 @@
|
||||
#[derive(Debug,PartialEq)]
|
||||
#[derive(Debug,PartialEq,Clone)]
|
||||
pub enum Stmt {
|
||||
Assignment(String, Expr),
|
||||
Funcall(Expr),
|
||||
Conditional(Vec<Expr>, Option<Expr>),
|
||||
}
|
||||
|
||||
#[derive(Debug,PartialEq)]
|
||||
#[derive(Debug,PartialEq,Clone)]
|
||||
pub enum Expr {
|
||||
Id(String),
|
||||
Num(f64),
|
||||
@ -15,6 +16,13 @@ pub enum Expr {
|
||||
Mult(Box<Expr>, Box<Expr>),
|
||||
Div(Box<Expr>, Box<Expr>),
|
||||
Block(Vec<Stmt>),
|
||||
GuardedBlock(Box<GuardedBlock>),
|
||||
}
|
||||
|
||||
#[derive(Debug,PartialEq,Clone)]
|
||||
pub struct GuardedBlock {
|
||||
pub guard: Expr,
|
||||
pub block: Vec<Stmt>,
|
||||
}
|
||||
|
||||
peg::parser! {
|
||||
@ -23,7 +31,8 @@ peg::parser! {
|
||||
= __* s:stmt()* { s }
|
||||
pub rule stmt() -> Stmt
|
||||
= i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) } /
|
||||
f:funcall() stop() { Stmt::Funcall(f) }
|
||||
f:funcall() stop() { Stmt::Funcall(f) } /
|
||||
c:conditional() { c }
|
||||
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,8 +46,6 @@ peg::parser! {
|
||||
i:id() _ { Expr::Id(i) }
|
||||
n:num() _ { Expr::Num(n) }
|
||||
}
|
||||
rule block() -> Expr
|
||||
= stop() indent() __* s:stmt()+ dedent() { Expr::Block(s) }
|
||||
|
||||
rule id() -> String
|
||||
= i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() }
|
||||
@ -48,6 +55,28 @@ peg::parser! {
|
||||
= i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) }
|
||||
rule funcdef() -> Expr
|
||||
= i:id()? "->" _ e:(expr() / block()) { Expr::Funcdef(i, Box::new(e)) }
|
||||
rule conditional() -> Stmt
|
||||
= i:_if() __* ei:elif()* __* e:_else()? __* { Stmt::Conditional([vec![i], ei].concat(), e) }
|
||||
rule _if() -> Expr
|
||||
= "if" _ g:expr() b:indented_block() {
|
||||
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||
guard: g,
|
||||
block: b,
|
||||
}))
|
||||
}
|
||||
rule elif() -> Expr
|
||||
= "elif" _ g:expr() b:indented_block() {
|
||||
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||
guard: g,
|
||||
block: b
|
||||
}))
|
||||
}
|
||||
rule _else() -> Expr
|
||||
= "else" _ b:block() { b }
|
||||
rule block() -> Expr
|
||||
= i:indented_block() { Expr::Block(i) }
|
||||
rule indented_block() -> Vec<Stmt>
|
||||
= stop() indent() __* s:stmt()+ dedent() { s }
|
||||
|
||||
rule letter()
|
||||
= ['A'..='Z'] / ['a'..='z']
|
||||
@ -250,6 +279,32 @@ foo <- x -> y -> x * y";
|
||||
];
|
||||
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
|
||||
}
|
||||
#[test]
|
||||
fn test_conditional() {
|
||||
let prgm = r"if foo
|
||||
>>>bar()
|
||||
<<<
|
||||
elif baz
|
||||
>>>foobar()
|
||||
<<<
|
||||
else
|
||||
>>>quux()
|
||||
<<<";
|
||||
let expected = vec![Stmt::Conditional(
|
||||
vec![
|
||||
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||
guard: Expr::Id("foo".to_string()),
|
||||
block: vec![Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![]))]
|
||||
})),
|
||||
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||
guard: Expr::Id("baz".to_string()),
|
||||
block: vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))]
|
||||
})),
|
||||
],
|
||||
Some(Expr::Block(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))])),
|
||||
)];
|
||||
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_preprocess() {
|
||||
|
Loading…
Reference in New Issue
Block a user