use builder::{Builder, NodeResult};
use func::Func;
use eval::Command;
use error::Error;
grammar<'b>(builder: &'b Builder);
pub Expr: NodeResult = {
<l:Expr> "+" <r:Factor> => builder.add(l?, r?),
<l:Expr> "-" <r:Factor> => builder.sub(l?, r?),
"-" <f:Factor> => builder.neg(f?),
Factor,
};
pub Factor: NodeResult = {
<l:Factor> "*" <r:Pow> => builder.mul(l?, r?),
<l:Factor> "ยท" <r:Pow> => builder.mul(l?, r?),
<l:Factor> "/" <r:Pow> => builder.div(l?, r?),
Pow,
};
pub Op: NodeResult = {
<v:r"d/d(\pL+)"> => builder.op(Func::Diff(v[3..].into())),
};
pub Pow: NodeResult = {
<b:Term> "^" <e:Pow> => builder.pow(b?, e?),
<l:Term> <r:Pow> => builder.apply(l?, r?),
Term
};
Comma<T>: Vec<T> = {
<v:(<T> ",")*> <e:T> => {
let mut v = v;
v.push(e );
v
},
};
pub CommaE = Comma<Expr>;
pub Tuple: NodeResult = {
"(" <t:CommaE> ")" => {
let mut t = t;
match t.len() {
1 => t.pop().unwrap(),
_ => builder.tuple(t)
}
},
};
pub Array: NodeResult = {
"[" <t:CommaE> "]" => builder.array(t),
};
pub Term: NodeResult = {
Num,
NumFloat,
Var,
Tuple,
Array,
Op,
};
Num: NodeResult = <s:r"[0-9]+"> => builder.decimal(s);
NumFloat: NodeResult = <s:r"[0-9]+\.[0-9]+"> => builder.decimal_float(s);
Var: NodeResult = <s:Name> => Ok(builder.named(s));
Name: &'input str = r"\pL+";
pub CommaS = Comma<Name>;
pub Command: Result<Command<'input>, Error> = {
"def" <f:r"\pL+"> "(" <a:CommaS> ")" ":=" <e:Expr> => Ok(Command::Define(f, a, e?)),
"def" <f:r"\pL+"> ":=" <e:Expr> => Ok(Command::Define(f, vec![], e?)),
"eval" <e:Expr> => Ok(Command::Eval(e?)),
"bench" <e:Expr> => Ok(Command::Bench(e?)),
<e:Expr> => Ok(Command::Expr(e?)),
};