Add if expressions
This commit is contained in:
parent
506b406146
commit
fd3ec9e12d
|
@ -1,6 +1,6 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use crate::{env::Env, function::FunctionMap, value::Value};
|
||||
use crate::{env::Env, function::FunctionMap, statement::Statement, value::Value};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BinaryOperation {
|
||||
|
@ -38,13 +38,17 @@ impl FromStr for BinaryOperation {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Expression {
|
||||
Constant(Value),
|
||||
Variable(String),
|
||||
Call(String, Vec<Expression>),
|
||||
CallMethod(Box<Expression>, String, Vec<Expression>),
|
||||
Binary(Box<Expression>, BinaryOperation, Box<Expression>),
|
||||
If(
|
||||
Vec<(Expression, Statement, Expression)>,
|
||||
(Box<Statement>, Box<Expression>),
|
||||
),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
|
@ -89,6 +93,19 @@ impl Expression {
|
|||
BinaryOperation::NotEqual => (lhs != rhs).into(),
|
||||
}
|
||||
}
|
||||
Expression::If(ifs, (else_statement, else_expr)) => {
|
||||
for (expr, statement, ret) in ifs {
|
||||
let e = Env::new_with_parent(e);
|
||||
if expr.eval(&e, f).is_truthy() {
|
||||
statement.eval(&e, f);
|
||||
return ret.eval(&e, f);
|
||||
}
|
||||
}
|
||||
|
||||
let e = Env::new_with_parent(e);
|
||||
else_statement.eval(&e, f);
|
||||
else_expr.eval(&e, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ value = { (const_value | call | identifier | parens) ~ method_call }
|
|||
|
||||
method_call = { (("." ~ identifier ~ call_params) ~ method_call)? }
|
||||
|
||||
expression = { equality }
|
||||
expression = { if_block_expr | equality }
|
||||
|
||||
equality = { inequality ~ ((equals | not_equals) ~ inequality)? }
|
||||
|
||||
|
@ -67,6 +67,10 @@ while_block = { "while" ~ expression ~ block }
|
|||
|
||||
if_block = { "if" ~ expression ~ block ~ ("else if" ~ expression ~ block)* ~ ("else" ~ block)? }
|
||||
|
||||
if_block_expr = { "if" ~ expression ~ if_block_expr_block ~ ("else if" ~ expression ~ if_block_expr_block)* ~ "else" ~ if_block_expr_block }
|
||||
|
||||
if_block_expr_block = { "{" ~ statement* ~ expression ~ "}" }
|
||||
|
||||
def_params = { "(" ~ (identifier ~ ","?)* ~ ")" }
|
||||
|
||||
def = { "def" ~ identifier ~ def_params ~ func_block }
|
||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -50,11 +50,11 @@ impl CustomValue for Foo {
|
|||
}
|
||||
}
|
||||
|
||||
fn functions(&self) -> Option<FunctionMap> {
|
||||
let mut map = FunctionMap::new();
|
||||
map.insert_native("edit_foo", Foo::edit);
|
||||
Some(map)
|
||||
}
|
||||
fn functions(&self) -> Option<FunctionMap> {
|
||||
let mut map = FunctionMap::new();
|
||||
map.insert_native("edit_foo", Foo::edit);
|
||||
Some(map)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -189,6 +189,36 @@ fn parse_expression(pair: Pair<Rule>) -> Expression {
|
|||
v
|
||||
}
|
||||
}
|
||||
Rule::if_block_expr => {
|
||||
let mut inner = pair.into_inner();
|
||||
let mut the_list = vec![];
|
||||
let mut the_else = None;
|
||||
while let Some(expr) = inner.next() {
|
||||
if let Some(if_block) = inner.next() {
|
||||
let expr = parse_expression(expr);
|
||||
let if_block_body = if_block.into_inner();
|
||||
let (a, b): (Vec<_>, Vec<_>) =
|
||||
if_block_body.partition(|a| a.as_rule() == Rule::statement);
|
||||
let (statements, _): (_, FuncHolder) =
|
||||
a.into_iter().map(parse_statement).unzip();
|
||||
let z = b.into_iter().map(parse_expression).collect::<Vec<_>>();
|
||||
the_list.push((expr, Statement::Body(statements), z[0].clone()));
|
||||
} else {
|
||||
let if_block_body = expr.into_inner();
|
||||
let (a, b): (Vec<_>, Vec<_>) =
|
||||
if_block_body.partition(|a| a.as_rule() == Rule::statement);
|
||||
let (statements, _): (_, FuncHolder) =
|
||||
a.into_iter().map(parse_statement).unzip();
|
||||
let z = b.into_iter().map(parse_expression).collect::<Vec<_>>();
|
||||
the_else = Some((
|
||||
Box::new(Statement::Body(statements)),
|
||||
Box::new(z[0].clone()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Expression::If(the_list, the_else.unwrap())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue