use crate::ast::*;
grammar;
pub target: (Box<Expr>, Option<String>) = { // (1)
<var: Ident> "=" <e: expression> => (e, Some(var)),
<e: expression> => (e, None),
};
expression: Box<Expr> = {
#[precedence(level="0")]
term,
#[precedence(level="1")] #[assoc(side="left")]
<e: expression> "!" => Box::new(Expr::Fac(e)),
#[precedence(level="2")] #[assoc(side="left")]
<lhs: expression> "^" <rhs: expression> => Box::new(Expr::Op(lhs, Operation::Exp, rhs)),
#[precedence(level="3")] #[assoc(side="left")]
<lhs: expression> "*" <rhs: expression> => Box::new(Expr::Op(lhs, Operation::Mul, rhs)),
<lhs: expression> "/" <rhs: expression> => Box::new(Expr::Op(lhs, Operation::Div, rhs)),
<lhs: expression> "//" <rhs: expression> => Box::new(Expr::Op(lhs, Operation::FloorDiv, rhs)),
<lhs: expression> "%" <rhs: expression> => Box::new(Expr::Op(lhs, Operation::Mod, rhs)),
#[precedence(level="4")] #[assoc(side="left")]
<lhs: expression> "+" <rhs: expression> => Box::new(Expr::Op(lhs, Operation::Add, rhs)),
<lhs: expression> "-" <rhs: expression> => Box::new(Expr::Op(lhs, Operation::Sub, rhs)),
};
term: Box<Expr> = {
#[precedence(level="0")]
<name: Ident> "(" <args: arg_list> ")" => Box::new(Expr::Func(name, args)),
"(" <e: expression> ")" => e,
#[precedence(level="1")]
"-(" <e: expression> ")" => Box::new(Expr::Op(Box::new(Expr::Num(0.0)), Operation::Sub, e)),
<num: NumLiteral> => Box::new(Expr::Num(num)),
<name: Ident> => Box::new(Expr::Var(name)),
};
arg_list: Vec<Box<Expr>> = {
<args: arg_list> "," <new: expression> => {
let mut new_args = Vec::with_capacity(args.len() + 1);
for arg in args { new_args.push(arg); }
new_args.push(new);
new_args
},
<new: expression> => {
let mut args = Vec::new();
args.push(new);
args
}
}
Ident: String = <s:r"[a-zA-Z][a-zA-Z0-9_.]*"> => String::from(s);
NumLiteral: f64 = <s:r"[-]?[0-9]+(?:\.[0-9]+)?(?:e[-]?[0-9]+)?"> => s.parse::<f64>().expect("Failed to parse num literal");
// let ident_re = Regex::new(r"^[a-zA-Z][a-zA-Z0-9_.]*$").expect("Failed to generate ident regex");
// let num_re = Regex::new(r"^[0-9]+(?:\.[0-9]+)?(?:e[0-9]+)?$").expect("Failed to generate number regex");