More expression parsing
diff --git a/src/expr.rs b/src/expr.rs
index 1026654..312027f 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -4,8 +4,6 @@
pub enum Expr {
/// A `box x` expression.
Box(Box<Expr>),
- /// First expr is the place; second expr is the value.
- InPlace(Box<Expr>, Box<Expr>),
/// An array (`[a, b, c, d]`)
Vec(Vec<Expr>),
/// A function call
@@ -337,18 +335,137 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
+ use {Ident, Ty};
+ use ident::parsing::ident;
+ use lit::parsing::lit;
use nom::multispace;
+ use ty::parsing::ty;
- named!(pub expr -> Expr, alt!(
- box_expr
+ named!(pub expr -> Expr, do_parse!(
+ mut e: alt!(
+ boxed
+ |
+ vec
+ |
+ tup
+ |
+ unary
+ |
+ map!(lit, Expr::Lit)
+ ) >>
+ many0!(alt!(
+ tap!(c: call => {
+ e = Expr::Call(Box::new(e), c);
+ })
+ |
+ tap!(c: method_call => {
+ let (method, ascript, mut args) = c;
+ args.insert(0, e);
+ e = Expr::MethodCall(method, ascript, args);
+ })
+ |
+ tap!(b: binary => {
+ let (op, other) = b;
+ e = Expr::Binary(op, Box::new(e), Box::new(other));
+ })
+ )) >>
+ (e)
));
- named!(box_expr -> Expr, do_parse!(
+ named!(boxed -> Expr, do_parse!(
punct!("box") >>
multispace >>
inner: expr >>
(Expr::Box(Box::new(inner)))
));
+
+ named!(vec -> Expr, do_parse!(
+ punct!("[") >>
+ elems: separated_list!(punct!(","), expr) >>
+ punct!("]") >>
+ (Expr::Vec(elems))
+ ));
+
+ named!(call -> Vec<Expr>, do_parse!(
+ punct!("(") >>
+ args: separated_list!(punct!(","), expr) >>
+ punct!(")") >>
+ (args)
+ ));
+
+ named!(method_call -> (Ident, Vec<Ty>, Vec<Expr>), do_parse!(
+ punct!(".") >>
+ method: ident >>
+ ascript: opt_vec!(delimited!(
+ punct!("<"),
+ separated_list!(punct!(","), ty),
+ punct!(">")
+ )) >>
+ punct!("(") >>
+ args: separated_list!(punct!(","), expr) >>
+ punct!(")") >>
+ (method, ascript, args)
+ ));
+
+ named!(tup -> Expr, do_parse!(
+ punct!("(") >>
+ elems: separated_list!(punct!(","), expr) >>
+ punct!(")") >>
+ (Expr::Tup(elems))
+ ));
+
+ named!(binary -> (BinOp, Expr), tuple!(
+ alt!(
+ punct!("&&") => { |_| BinOp::And }
+ |
+ punct!("||") => { |_| BinOp::Or }
+ |
+ punct!("<<") => { |_| BinOp::Shl }
+ |
+ punct!(">>") => { |_| BinOp::Shr }
+ |
+ punct!("==") => { |_| BinOp::Eq }
+ |
+ punct!("<=") => { |_| BinOp::Le }
+ |
+ punct!("!=") => { |_| BinOp::Ne }
+ |
+ punct!(">=") => { |_| BinOp::Ge }
+ |
+ punct!("+") => { |_| BinOp::Add }
+ |
+ punct!("-") => { |_| BinOp::Sub }
+ |
+ punct!("*") => { |_| BinOp::Mul }
+ |
+ punct!("/") => { |_| BinOp::Div }
+ |
+ punct!("%") => { |_| BinOp::Rem }
+ |
+ punct!("^") => { |_| BinOp::BitXor }
+ |
+ punct!("&") => { |_| BinOp::BitAnd }
+ |
+ punct!("|") => { |_| BinOp::BitOr }
+ |
+ punct!("<") => { |_| BinOp::Lt }
+ |
+ punct!(">") => { |_| BinOp::Gt }
+ ),
+ expr
+ ));
+
+ named!(unary -> Expr, do_parse!(
+ operator: alt!(
+ punct!("*") => { |_| UnOp::Deref }
+ |
+ punct!("!") => { |_| UnOp::Not }
+ |
+ punct!("-") => { |_| UnOp::Neg }
+ ) >>
+ operand: expr >>
+ (Expr::Unary(operator, Box::new(operand)))
+ ));
}
#[cfg(feature = "printing")]
diff --git a/src/helper.rs b/src/helper.rs
index bccdd42..2a429e9 100644
--- a/src/helper.rs
+++ b/src/helper.rs
@@ -25,8 +25,8 @@
macro_rules! option {
($i:expr, $submac:ident!( $($args:tt)* )) => {
match $submac!($i, $($args)*) {
- ::nom::IResult::Done(i, o) => ::nom::IResult::Done(i, Some(o)),
- ::nom::IResult::Error => ::nom::IResult::Done($i, None),
+ $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, Some(o)),
+ $crate::nom::IResult::Error => $crate::nom::IResult::Done($i, None),
}
};
@@ -38,14 +38,31 @@
macro_rules! opt_vec {
($i:expr, $submac:ident!( $($args:tt)* )) => {
match $submac!($i, $($args)*) {
- ::nom::IResult::Done(i, o) => ::nom::IResult::Done(i, o),
- ::nom::IResult::Error => ::nom::IResult::Done($i, Vec::new()),
+ $crate::nom::IResult::Done(i, o) => $crate::nom::IResult::Done(i, o),
+ $crate::nom::IResult::Error => $crate::nom::IResult::Done($i, Vec::new()),
}
};
}
macro_rules! epsilon {
($i:expr,) => {
- value!($i, ())
+ $crate::nom::IResult::Done($i, ())
+ };
+}
+
+macro_rules! tap {
+ ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
+ match $submac!($i, $($args)*) {
+ $crate::nom::IResult::Done(i, o) => {
+ let $name = o;
+ $e;
+ $crate::nom::IResult::Done(i, ())
+ }
+ $crate::nom::IResult::Error => $crate::nom::IResult::Error,
+ }
+ };
+
+ ($i:expr, $name:ident : $f:expr => $e:expr) => {
+ tap!($i, $name: call!($f) => $e);
};
}
diff --git a/src/lit.rs b/src/lit.rs
index 92d5339..7dcc8bc 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -118,16 +118,14 @@
bytes.next();
len += 1;
}
- _ => {
- return if len > 0 {
- IResult::Done(&input[len..], value)
- } else {
- IResult::Error
- };
- },
+ _ => break,
}
}
- IResult::Error
+ if len > 0 {
+ IResult::Done(&input[len..], value)
+ } else {
+ IResult::Error
+ }
}
}
diff --git a/src/nom.rs b/src/nom.rs
index a899a20..5d9d00c 100644
--- a/src/nom.rs
+++ b/src/nom.rs
@@ -549,6 +549,20 @@
}
};
+ ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
+ do_parse!($i, $field: call!($e) >> $($rest)*);
+ };
+
+ ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
+ match $submac!($i, $($args)*) {
+ $crate::nom::IResult::Error => $crate::nom::IResult::Error,
+ $crate::nom::IResult::Done(i,o) => {
+ let mut $field = o;
+ do_parse!(i, $($rest)*)
+ },
+ }
+ };
+
// ending the chain
($i:expr, $e:ident >> ( $($rest:tt)* )) => {
do_parse!($i, call!($e) >> ( $($rest)* ));