ConstExpr type for discriminant and array len
diff --git a/src/constant.rs b/src/constant.rs
new file mode 100644
index 0000000..2834539
--- /dev/null
+++ b/src/constant.rs
@@ -0,0 +1,113 @@
+use super::*;
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub enum ConstExpr {
+ /// A function call
+ ///
+ /// The first field resolves to the function itself,
+ /// and the second field is the list of arguments
+ Call(Box<ConstExpr>, Vec<ConstExpr>),
+ /// A binary operation (For example: `a + b`, `a * b`)
+ Binary(BinOp, Box<ConstExpr>, Box<ConstExpr>),
+ /// A unary operation (For example: `!x`, `*x`)
+ Unary(UnOp, Box<ConstExpr>),
+ /// A literal (For example: `1`, `"foo"`)
+ Lit(Lit),
+ /// A cast (`foo as f64`)
+ Cast(Box<ConstExpr>, Box<Ty>),
+ /// Variable reference, possibly containing `::` and/or type
+ /// parameters, e.g. foo::bar::<baz>.
+ Path(Path),
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+ use super::*;
+ use {BinOp, Ty};
+ use lit::parsing::lit;
+ use op::parsing::{binop, unop};
+ use ty::parsing::{path, ty};
+
+ named!(pub const_expr -> ConstExpr, do_parse!(
+ mut e: alt!(
+ expr_lit
+ |
+ expr_unary
+ |
+ path => { ConstExpr::Path }
+ ) >>
+ many0!(alt!(
+ tap!(args: and_call => {
+ e = ConstExpr::Call(Box::new(e), args);
+ })
+ |
+ tap!(more: and_binary => {
+ let (op, other) = more;
+ e = ConstExpr::Binary(op, Box::new(e), Box::new(other));
+ })
+ |
+ tap!(ty: and_cast => {
+ e = ConstExpr::Cast(Box::new(e), Box::new(ty));
+ })
+ )) >>
+ (e)
+ ));
+
+ named!(and_call -> Vec<ConstExpr>, do_parse!(
+ punct!("(") >>
+ args: separated_list!(punct!(","), const_expr) >>
+ punct!(")") >>
+ (args)
+ ));
+
+ named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
+
+ named!(expr_unary -> ConstExpr, do_parse!(
+ operator: unop >>
+ operand: const_expr >>
+ (ConstExpr::Unary(operator, Box::new(operand)))
+ ));
+
+ named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
+
+ named!(and_cast -> Ty, do_parse!(
+ keyword!("as") >>
+ ty: ty >>
+ (ty)
+ ));
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use super::*;
+ use quote::{Tokens, ToTokens};
+
+ impl ToTokens for ConstExpr {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ ConstExpr::Call(ref func, ref args) => {
+ func.to_tokens(tokens);
+ tokens.append("(");
+ tokens.append_separated(args, ",");
+ tokens.append(")");
+ }
+ ConstExpr::Binary(op, ref left, ref right) => {
+ left.to_tokens(tokens);
+ op.to_tokens(tokens);
+ right.to_tokens(tokens);
+ }
+ ConstExpr::Unary(op, ref expr) => {
+ op.to_tokens(tokens);
+ expr.to_tokens(tokens);
+ }
+ ConstExpr::Lit(ref lit) => lit.to_tokens(tokens),
+ ConstExpr::Cast(ref expr, ref ty) => {
+ expr.to_tokens(tokens);
+ tokens.append("as");
+ ty.to_tokens(tokens);
+ }
+ ConstExpr::Path(ref path) => path.to_tokens(tokens),
+ }
+ }
+ }
+}
diff --git a/src/data.rs b/src/data.rs
index 1565794..71d6754 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -6,7 +6,7 @@
pub attrs: Vec<Attribute>,
pub data: VariantData,
/// Explicit discriminant, e.g. `Foo = 1`
- pub discriminant: Option<Discriminant>,
+ pub discriminant: Option<ConstExpr>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -48,18 +48,12 @@
Inherited,
}
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub struct Discriminant {
- pub value: u64,
- pub ty: IntTy,
-}
-
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
use attr::parsing::outer_attr;
+ use constant::parsing::const_expr;
use ident::parsing::ident;
- use lit::parsing::int;
use ty::parsing::ty;
named!(pub struct_body -> VariantData, alt!(
@@ -88,7 +82,7 @@
|
epsilon!() => { |_| VariantData::Unit }
) >>
- disr: option!(preceded!(punct!("="), discriminant)) >>
+ disr: option!(preceded!(punct!("="), const_expr)) >>
(Variant {
ident: id,
attrs: attrs,
@@ -144,20 +138,11 @@
|
epsilon!() => { |_| Visibility::Inherited }
));
-
- named!(discriminant -> Discriminant, map!(
- int,
- |(value, ty)| Discriminant {
- value: value,
- ty: ty,
- }
- ));
}
#[cfg(feature = "printing")]
mod printing {
use super::*;
- use lit::Lit;
use quote::{Tokens, ToTokens};
impl ToTokens for Variant {
@@ -213,10 +198,4 @@
}
}
}
-
- impl ToTokens for Discriminant {
- fn to_tokens(&self, tokens: &mut Tokens) {
- Lit::Int(self.value, self.ty).to_tokens(tokens);
- }
- }
}
diff --git a/src/expr.rs b/src/expr.rs
index f2f96d0..fa7cdf7 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -188,56 +188,6 @@
pub attrs: Vec<Attribute>,
}
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum BinOp {
- /// The `+` operator (addition)
- Add,
- /// The `-` operator (subtraction)
- Sub,
- /// The `*` operator (multiplication)
- Mul,
- /// The `/` operator (division)
- Div,
- /// The `%` operator (modulus)
- Rem,
- /// The `&&` operator (logical and)
- And,
- /// The `||` operator (logical or)
- Or,
- /// The `^` operator (bitwise xor)
- BitXor,
- /// The `&` operator (bitwise and)
- BitAnd,
- /// The `|` operator (bitwise or)
- BitOr,
- /// The `<<` operator (shift left)
- Shl,
- /// The `>>` operator (shift right)
- Shr,
- /// The `==` operator (equality)
- Eq,
- /// The `<` operator (less than)
- Lt,
- /// The `<=` operator (less than or equal to)
- Le,
- /// The `!=` operator (not equal to)
- Ne,
- /// The `>=` operator (greater than or equal to)
- Ge,
- /// The `>` operator (greater than)
- Gt,
-}
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum UnOp {
- /// The `*` operator for dereferencing
- Deref,
- /// The `!` operator for logical inversion
- Not,
- /// The `-` operator for negation
- Neg,
-}
-
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Pat {
/// Represents a wildcard pattern (`_`)
@@ -340,7 +290,7 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
- use {Delimited, DelimToken, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, TokenTree, Ty};
+ use {BinOp, Delimited, DelimToken, FnArg, FnDecl, FunctionRetTy, Ident, Lifetime, TokenTree, Ty};
use attr::parsing::outer_attr;
use generics::parsing::lifetime;
use ident::parsing::ident;
@@ -348,6 +298,7 @@
use lit::parsing::lit;
use mac::parsing::mac;
use nom::IResult::Error;
+ use op::parsing::{binop, unop};
use ty::parsing::{mutability, path, qpath, ty};
named!(pub expr -> Expr, do_parse!(
@@ -482,55 +433,10 @@
(Expr::Tup(elems))
));
- named!(and_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!(and_binary -> (BinOp, Expr), tuple!(binop, expr));
named!(expr_unary -> Expr, do_parse!(
- operator: alt!(
- punct!("*") => { |_| UnOp::Deref }
- |
- punct!("!") => { |_| UnOp::Not }
- |
- punct!("-") => { |_| UnOp::Neg }
- ) >>
+ operator: unop >>
operand: expr >>
(Expr::Unary(operator, Box::new(operand)))
));
@@ -1206,7 +1112,7 @@
}
Expr::AssignOp(op, ref var, ref expr) => {
var.to_tokens(tokens);
- tokens.append(op.assign_op());
+ tokens.append(op.assign_op().unwrap());
expr.to_tokens(tokens);
}
Expr::Field(ref expr, ref field) => {
@@ -1306,69 +1212,6 @@
}
}
- impl BinOp {
- fn op(&self) -> &'static str {
- match *self {
- BinOp::Add => "+",
- BinOp::Sub => "-",
- BinOp::Mul => "*",
- BinOp::Div => "/",
- BinOp::Rem => "%",
- BinOp::And => "&&",
- BinOp::Or => "||",
- BinOp::BitXor => "^",
- BinOp::BitAnd => "&",
- BinOp::BitOr => "|",
- BinOp::Shl => "<<",
- BinOp::Shr => ">>",
- BinOp::Eq => "==",
- BinOp::Lt => "<",
- BinOp::Le => "<=",
- BinOp::Ne => "!=",
- BinOp::Ge => ">=",
- BinOp::Gt => ">",
- }
- }
-
- fn assign_op(&self) -> &'static str {
- match *self {
- BinOp::Add => "+=",
- BinOp::Sub => "-=",
- BinOp::Mul => "*=",
- BinOp::Div => "/=",
- BinOp::Rem => "%=",
- BinOp::BitXor => "^=",
- BinOp::BitAnd => "&=",
- BinOp::BitOr => "|=",
- BinOp::Shl => "<<=",
- BinOp::Shr => ">>=",
- _ => panic!("bad assignment operator"),
- }
- }
- }
-
- impl ToTokens for BinOp {
- fn to_tokens(&self, tokens: &mut Tokens) {
- tokens.append(self.op());
- }
- }
-
- impl UnOp {
- fn op(&self) -> &'static str {
- match *self {
- UnOp::Deref => "*",
- UnOp::Not => "!",
- UnOp::Neg => "-",
- }
- }
- }
-
- impl ToTokens for UnOp {
- fn to_tokens(&self, tokens: &mut Tokens) {
- tokens.append(self.op());
- }
- }
-
impl ToTokens for FieldValue {
fn to_tokens(&self, tokens: &mut Tokens) {
self.ident.to_tokens(tokens);
diff --git a/src/lib.rs b/src/lib.rs
index 9e9ffd0..76ca608 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,14 +21,17 @@
mod attr;
pub use attr::{Attribute, AttrStyle, MetaItem};
+mod constant;
+pub use constant::ConstExpr;
+
mod data;
-pub use data::{Discriminant, Field, Variant, VariantData, Visibility};
+pub use data::{Field, Variant, VariantData, Visibility};
#[cfg(feature = "full")]
mod expr;
#[cfg(feature = "full")]
-pub use expr::{Arm, BinOp, BindingMode, Block, BlockCheckMode, CaptureBy, Expr, FieldPat, Local,
- MacStmtStyle, Pat, RangeLimits, Stmt, UnOp};
+pub use expr::{Arm, BindingMode, Block, BlockCheckMode, CaptureBy, Expr, FieldPat, Local,
+ MacStmtStyle, Pat, RangeLimits, Stmt};
mod generics;
pub use generics::{Generics, Lifetime, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound,
@@ -60,11 +63,14 @@
mod macro_input;
pub use macro_input::{Body, MacroInput};
+mod op;
+pub use op::{BinOp, UnOp};
+
#[cfg(feature = "parsing")]
mod space;
mod ty;
-pub use ty::{AngleBracketedParameterData, ArrayLen, BareFnArg, BareFnTy, FunctionRetTy, MutTy,
+pub use ty::{AngleBracketedParameterData, BareFnArg, BareFnTy, FunctionRetTy, MutTy,
Mutability, ParenthesizedParameterData, Path, PathParameters, PathSegment,
PolyTraitRef, QSelf, Ty, TypeBinding};
diff --git a/src/op.rs b/src/op.rs
new file mode 100644
index 0000000..a27f6a2
--- /dev/null
+++ b/src/op.rs
@@ -0,0 +1,169 @@
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum BinOp {
+ /// The `+` operator (addition)
+ Add,
+ /// The `-` operator (subtraction)
+ Sub,
+ /// The `*` operator (multiplication)
+ Mul,
+ /// The `/` operator (division)
+ Div,
+ /// The `%` operator (modulus)
+ Rem,
+ /// The `&&` operator (logical and)
+ And,
+ /// The `||` operator (logical or)
+ Or,
+ /// The `^` operator (bitwise xor)
+ BitXor,
+ /// The `&` operator (bitwise and)
+ BitAnd,
+ /// The `|` operator (bitwise or)
+ BitOr,
+ /// The `<<` operator (shift left)
+ Shl,
+ /// The `>>` operator (shift right)
+ Shr,
+ /// The `==` operator (equality)
+ Eq,
+ /// The `<` operator (less than)
+ Lt,
+ /// The `<=` operator (less than or equal to)
+ Le,
+ /// The `!=` operator (not equal to)
+ Ne,
+ /// The `>=` operator (greater than or equal to)
+ Ge,
+ /// The `>` operator (greater than)
+ Gt,
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum UnOp {
+ /// The `*` operator for dereferencing
+ Deref,
+ /// The `!` operator for logical inversion
+ Not,
+ /// The `-` operator for negation
+ Neg,
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+ use super::*;
+
+ named!(pub binop -> BinOp, 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 }
+ ));
+
+ named!(pub unop -> UnOp, alt!(
+ punct!("*") => { |_| UnOp::Deref }
+ |
+ punct!("!") => { |_| UnOp::Not }
+ |
+ punct!("-") => { |_| UnOp::Neg }
+ ));
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use super::*;
+ use quote::{Tokens, ToTokens};
+
+ impl BinOp {
+ pub fn op(&self) -> &'static str {
+ match *self {
+ BinOp::Add => "+",
+ BinOp::Sub => "-",
+ BinOp::Mul => "*",
+ BinOp::Div => "/",
+ BinOp::Rem => "%",
+ BinOp::And => "&&",
+ BinOp::Or => "||",
+ BinOp::BitXor => "^",
+ BinOp::BitAnd => "&",
+ BinOp::BitOr => "|",
+ BinOp::Shl => "<<",
+ BinOp::Shr => ">>",
+ BinOp::Eq => "==",
+ BinOp::Lt => "<",
+ BinOp::Le => "<=",
+ BinOp::Ne => "!=",
+ BinOp::Ge => ">=",
+ BinOp::Gt => ">",
+ }
+ }
+
+ pub fn assign_op(&self) -> Option<&'static str> {
+ match *self {
+ BinOp::Add => Some("+="),
+ BinOp::Sub => Some("-="),
+ BinOp::Mul => Some("*="),
+ BinOp::Div => Some("/="),
+ BinOp::Rem => Some("%="),
+ BinOp::BitXor => Some("^="),
+ BinOp::BitAnd => Some("&="),
+ BinOp::BitOr => Some("|="),
+ BinOp::Shl => Some("<<="),
+ BinOp::Shr => Some(">>="),
+ _ => None,
+ }
+ }
+ }
+
+ impl ToTokens for BinOp {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ tokens.append(self.op());
+ }
+ }
+
+ impl UnOp {
+ pub fn op(&self) -> &'static str {
+ match *self {
+ UnOp::Deref => "*",
+ UnOp::Not => "!",
+ UnOp::Neg => "-",
+ }
+ }
+ }
+
+ impl ToTokens for UnOp {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ tokens.append(self.op());
+ }
+ }
+}
diff --git a/src/ty.rs b/src/ty.rs
index b8aee5a..fb34280 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -6,7 +6,7 @@
/// A variable-length array (`[T]`)
Slice(Box<Ty>),
/// A fixed length array (`[T; n]`)
- Array(Box<Ty>, ArrayLen),
+ Array(Box<Ty>, ConstExpr),
/// A raw pointer (`*const T` or `*mut T`)
Ptr(Box<MutTy>),
/// A reference (`&'a T` or `&'a mut T`)
@@ -36,15 +36,6 @@
}
#[derive(Debug, Clone, Eq, PartialEq)]
-pub enum ArrayLen {
- /// As in `[T; 0]`.
- Usize(usize),
- /// As in `[T; LEN]` or `[T; helper::LEN as usize]`. The boolean indicates
- /// whether the path is followed by `as usize`.
- Path(Path, bool),
-}
-
-#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MutTy {
pub ty: Ty,
pub mutability: Mutability,
@@ -204,9 +195,9 @@
#[cfg(feature = "parsing")]
pub mod parsing {
use super::*;
+ use constant::parsing::const_expr;
use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
use ident::parsing::ident;
- use lit::parsing::int;
use std::str;
named!(pub ty -> Ty, alt!(
@@ -242,21 +233,11 @@
punct!("[") >>
elem: ty >>
punct!(";") >>
- len: array_len >>
+ len: const_expr >>
punct!("]") >>
(Ty::Array(Box::new(elem), len))
));
- named!(array_len -> ArrayLen, alt!(
- map!(int, |(i, _)| ArrayLen::Usize(i as usize))
- |
- do_parse!(
- path: path >>
- as_usize: option!(tuple!(keyword!("as"), keyword!("usize"))) >>
- (ArrayLen::Path(path, as_usize.is_some()))
- )
- ));
-
named!(ty_ptr -> Ty, do_parse!(
punct!("*") >>
mutability: alt!(
@@ -527,21 +508,6 @@
}
}
- impl ToTokens for ArrayLen {
- fn to_tokens(&self, tokens: &mut Tokens) {
- match *self {
- ArrayLen::Usize(len) => tokens.append(&len.to_string()),
- ArrayLen::Path(ref path, as_usize) => {
- path.to_tokens(tokens);
- if as_usize {
- tokens.append("as");
- tokens.append("usize");
- }
- }
- }
- }
- }
-
impl ToTokens for Mutability {
fn to_tokens(&self, tokens: &mut Tokens) {
if let Mutability::Mutable = *self {