Implement range_expr
diff --git a/src/expr.rs b/src/expr.rs
index f74b652..c327a47 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1212,24 +1212,31 @@
// NOTE: The form of ranges which don't include a preceding expression are
// parsed by `atom_expr`, rather than by this function.
#[cfg(feature = "full")]
- named2!(range_expr(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, do_parse!(
- mut e: shim!(or_expr, allow_struct, allow_block) >>
- many0!(do_parse!(
- limits: syn!(RangeLimits) >>
- // We don't want to allow blocks here if we don't allow structs. See
- // the reasoning for `opt_ambiguous_expr!` above.
- hi: option!(shim!(or_expr, allow_struct, AllowBlock(allow_struct.0))) >>
- ({
- e = ExprRange {
- attrs: Vec::new(),
- from: Some(Box::new(e)),
- limits: limits,
- to: hi.map(|e| Box::new(e)),
- }.into();
- })
- )) >>
- (e)
- ));
+ fn range_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
+ let mut e = or_expr(input, allow_struct, allow_block)?;
+ while input.peek(Token![..]) {
+ e = Expr::Range(ExprRange {
+ attrs: Vec::new(),
+ from: Some(Box::new(e)),
+ limits: input.parse()?,
+ to: {
+ if input.is_empty()
+ || input.peek(Token![,])
+ || input.peek(Token![;])
+ || !allow_struct.0 && input.peek(token::Brace)
+ {
+ None
+ } else {
+ // We don't want to allow blocks here if we don't allow
+ // structs. See the reasoning for `opt_ambiguous_expr!`
+ // above.
+ Some(Box::new(or_expr(input, allow_struct, AllowBlock(allow_struct.0))?))
+ }
+ },
+ });
+ }
+ Ok(e)
+ }
// <and> || <and> ...
binop!(or_expr, and_expr, |input| {
@@ -2393,16 +2400,20 @@
));
#[cfg(feature = "full")]
- impl Synom for RangeLimits {
- named!(parse -> Self, alt!(
- // Must come before Dot2
- punct!(..=) => { RangeLimits::Closed }
- |
- // Must come before Dot2
- punct!(...) => { |dot3| RangeLimits::Closed(Token) }
- |
- punct!(..) => { RangeLimits::HalfOpen }
- ));
+ impl Parse for RangeLimits {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![..=]) {
+ input.parse().map(RangeLimits::Closed)
+ } else if lookahead.peek(Token![...]) {
+ let dot3: Token![...] = input.parse()?;
+ Ok(RangeLimits::Closed(Token))
+ } else if lookahead.peek(Token![..]) {
+ input.parse().map(RangeLimits::HalfOpen)
+ } else {
+ Err(lookahead.error())
+ }
+ }
}
impl Synom for ExprPath {