bullet 0.1.2

Supersonic Math
Documentation
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?)),
};