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