pub fn parse_assoc_expr_with(&mut self,
                                 min_prec: usize,
                                 lhs: LhsExpr)
                                 -> PResult<'a, P<Expr>> {
        let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
            expr
        } else {
            let attrs = match lhs {
                LhsExpr::AttributesParsed(attrs) => Some(attrs),
                _ => None,
            };
            if self.token == token::DotDot {
                return self.parse_prefix_range_expr(attrs);
            } else {
                try!(self.parse_prefix_expr(attrs))
            }
        };


        if self.expr_is_complete(&lhs) {
            // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
            return Ok(lhs);
        }
        self.expected_tokens.push(TokenType::Operator);
        while let Some(op) = AssocOp::from_token(&self.token) {

            let lhs_span = if self.last_token_interpolated {
                self.last_span
            } else {
                lhs.span
            };

            let cur_op_span = self.span;
            let restrictions = if op.is_assign_like() {
                self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
            } else {
                self.restrictions
            };
            if op.precedence() < min_prec {
                break;
            }
            self.bump();
            if op.is_comparison() {
                self.check_no_chained_comparison(&lhs, &op);
            }
            // Special cases:
            if op == AssocOp::As {
                let rhs = try!(self.parse_ty());
                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
                                   ExprKind::Cast(lhs, rhs), None);
                continue
            } else if op == AssocOp::Colon {
                let rhs = try!(self.parse_ty());
                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
                                   ExprKind::Type(lhs, rhs), None);
                continue
            } else if op == AssocOp::DotDot {
                    // If we didn’t have to handle `x..`, it would be pretty easy to generalise
                    // it to the Fixity::None code.
                    //
                    // We have 2 alternatives here: `x..y` and `x..` The other two variants are
                    // handled with `parse_prefix_range_expr` call above.
                    let rhs = if self.is_at_start_of_range_notation_rhs() {
                        let rhs = self.parse_assoc_expr_with(op.precedence() + 1,
                                                             LhsExpr::NotYetParsed);
                        match rhs {
                            Ok(e) => Some(e),
                            Err(mut e) => {
                                e.cancel();
                                None
                            }
                        }
                    } else {
                        None
                    };
                    let (lhs_span, rhs_span) = (lhs_span, if let Some(ref x) = rhs {
                        x.span
                    } else {
                        cur_op_span
                    });
                    let r = self.mk_range(Some(lhs), rhs);
                    lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, None);
                    break
            }

            let rhs = try!(match op.fixity() {
                Fixity::Right => self.with_res(
                    restrictions - Restrictions::RESTRICTION_STMT_EXPR,
                    |this| {
                        this.parse_assoc_expr_with(op.precedence(),
                            LhsExpr::NotYetParsed)
                }),
                Fixity::Left => self.with_res(
                    restrictions - Restrictions::RESTRICTION_STMT_EXPR,
                    |this| {
                        this.parse_assoc_expr_with(op.precedence() + 1,
                            LhsExpr::NotYetParsed)
                }),
                // We currently have no non-associative operators that are not handled above by
                // the special cases. The code is here only for future convenience.
                Fixity::None => self.with_res(
                    restrictions - Restrictions::RESTRICTION_STMT_EXPR,
                    |this| {
                        this.parse_assoc_expr_with(op.precedence() + 1,
                            LhsExpr::NotYetParsed)
                }),
            });

            lhs = match op {
                AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide |
                AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor |
                AssocOp::BitAnd | AssocOp::BitOr | AssocOp::ShiftLeft | AssocOp::ShiftRight |
                AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
                AssocOp::Greater | AssocOp::GreaterEqual => {
                    let ast_op = op.to_ast_binop().unwrap();
                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                    let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
                    self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
                }
                AssocOp::Assign =>
                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::Assign(lhs, rhs), None),
                AssocOp::Inplace =>
                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::InPlace(lhs, rhs), None),
                AssocOp::AssignOp(k) => {
                    let aop = match k {
                        token::Plus =>    BinOpKind::Add,
                        token::Minus =>   BinOpKind::Sub,
                        token::Star =>    BinOpKind::Mul,
                        token::Slash =>   BinOpKind::Div,
                        token::Percent => BinOpKind::Rem,
                        token::Caret =>   BinOpKind::BitXor,
                        token::And =>     BinOpKind::BitAnd,
                        token::Or =>      BinOpKind::BitOr,
                        token::Shl =>     BinOpKind::Shl,
                        token::Shr =>     BinOpKind::Shr,
                    };
                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                    let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
                    self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
                }
                AssocOp::As | AssocOp::Colon | AssocOp::DotDot => {
                    self.bug("As, Colon or DotDot branch reached")
                }
            };

            if op.fixity() == Fixity::None { break }
        }
        Ok(lhs)
    }
/// Parse an associative expression with operators of at least `min_prec` precedence
Parse an associative expression with operators of at least `min_prec` precedence
Parse an associative expression with operators of at least ` min_prec ` precedence
pub fn parse_assoc_expr_with(&mut self,
                                 min_prec: usize,
                                 lhs: LhsExpr)
                                 -> PResult<'a, P<Expr>> {
        let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
            expr
        } else {
            let attrs = match lhs {
                LhsExpr::AttributesParsed(attrs) => Some(attrs),
                _ => None,
            };
            if self.token == token::DotDot {
                return self.parse_prefix_range_expr(attrs);
            } else {
                try!(self.parse_prefix_expr(attrs))
            }
        };
        if self.expr_is_complete(&lhs) {
            // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
            return Ok(lhs);
        }
        self.expected_tokens.push(TokenType::Operator);
        while let Some(op) = AssocOp::from_token(&self.token) {
            let lhs_span = if self.last_token_interpolated {
                self.last_span
            } else {
                lhs.span
            };
            let cur_op_span = self.span;
            let restrictions = if op.is_assign_like() {
                self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL
            } else {
                self.restrictions
            };
            if op.precedence() < min_prec {
                break;
            }
            self.bump();
            if op.is_comparison() {
                self.check_no_chained_comparison(&lhs, &op);
            }
            // Special cases:
            if op == AssocOp::As {
                let rhs = try!(self.parse_ty());
                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
                                   ExprKind::Cast(lhs, rhs), None);
                continue
            } else if op == AssocOp::Colon {
                let rhs = try!(self.parse_ty());
                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
                                   ExprKind::Type(lhs, rhs), None);
                continue
            } else if op == AssocOp::DotDot {
                    // If we didn’t have to handle `x..`, it would be pretty easy to generalise
                    // it to the Fixity::None code.
                    //
                    // We have 2 alternatives here: `x..y` and `x..` The other two variants are
                    // handled with `parse_prefix_range_expr` call above.
                    let rhs = if self.is_at_start_of_range_notation_rhs() {
                        let rhs = self.parse_assoc_expr_with(op.precedence() + 1,
                                                             LhsExpr::NotYetParsed);
                        match rhs {
                            Ok(e) => Some(e),
                            Err(mut e) => {
                                e.cancel();
                                None
                            }
                        }
                    } else {
                        None
                    };
                    let (lhs_span, rhs_span) = (lhs_span, if let Some(ref x) = rhs {
                        x.span
                    } else {
                        cur_op_span
                    });
                    let r = self.mk_range(Some(lhs), rhs);
                    lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, None);
                    break
            }
            let rhs = try!(match op.fixity() {
                Fixity::Right => self.with_res(
                    restrictions - Restrictions::RESTRICTION_STMT_EXPR,
                    |this| {
                        this.parse_assoc_expr_with(op.precedence(),
                            LhsExpr::NotYetParsed)
                }),
                Fixity::Left => self.with_res(
                    restrictions - Restrictions::RESTRICTION_STMT_EXPR,
                    |this| {
                        this.parse_assoc_expr_with(op.precedence() + 1,
                            LhsExpr::NotYetParsed)
                }),
                // We currently have no non-associative operators that are not handled above by
                // the special cases. The code is here only for future convenience.
                Fixity::None => self.with_res(
                    restrictions - Restrictions::RESTRICTION_STMT_EXPR,
                    |this| {
                        this.parse_assoc_expr_with(op.precedence() + 1,
                            LhsExpr::NotYetParsed)
                }),
            });
            lhs = match op {
                AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide |
                AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor |
                AssocOp::BitAnd | AssocOp::BitOr | AssocOp::ShiftLeft | AssocOp::ShiftRight |
                AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
                AssocOp::Greater | AssocOp::GreaterEqual => {
                    let ast_op = op.to_ast_binop().unwrap();
                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                    let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
                    self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
                }
                AssocOp::Assign =>
                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::Assign(lhs, rhs), None),
                AssocOp::Inplace =>
                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::InPlace(lhs, rhs), None),
                AssocOp::AssignOp(k) => {
                    let aop = match k {
                        token::Plus =>    BinOpKind::Add,
                        token::Minus =>   BinOpKind::Sub,
                        token::Star =>    BinOpKind::Mul,
                        token::Slash =>   BinOpKind::Div,
                        token::Percent => BinOpKind::Rem,
                        token::Caret =>   BinOpKind::BitXor,
                        token::And =>     BinOpKind::BitAnd,
                        token::Or =>      BinOpKind::BitOr,
                        token::Shl =>     BinOpKind::Shl,
                        token::Shr =>     BinOpKind::Shr,
                    };
                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                    let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
                    self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
                }
                AssocOp::As | AssocOp::Colon | AssocOp::DotDot => {
                    self.bug("As, Colon or DotDot branch reached")
                }
            };
            if op.fixity() == Fixity::None { break }
        }
        Ok(lhs)
    }
pub fn parse_assoc_expr_with ( & mut self , min_prec : usize , lhs : LhsExpr ) -> PResult < ' a , P < Expr > > { let mut lhs = if let LhsExpr :: AlreadyParsed ( expr ) = lhs { expr } else { let attrs = match lhs { LhsExpr :: AttributesParsed ( attrs ) => Some ( attrs ) , _ => None , } ; if self . token == token :: DotDot { return self . parse_prefix_range_expr ( attrs ) ; } else { try ! ( self parse_prefix_expr ( attrs ) ) } } ; if self . expr_is_complete ( & lhs ) { // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok ( lhs ) ; } self . expected_tokens . push ( TokenType :: Operator ) ; while let Some ( op ) = AssocOp :: from_token ( & self . token ) { let lhs_span = if self . last_token_interpolated { self . last_span } else { lhs . span } ; let cur_op_span = self . span ; let restrictions = if op . is_assign_like ( ) { self . restrictions & Restrictions :: RESTRICTION_NO_STRUCT_LITERAL } else { self . restrictions } ; if op . precedence ( ) < min_prec { break ; } self . bump ( ) ; if op . is_comparison ( ) { self . check_no_chained_comparison ( & lhs , & op ) ; } // Special cases: if op == AssocOp :: As { let rhs = try ! ( self parse_ty ( ) ) ; lhs = self . mk_expr ( lhs_span . lo , rhs . span . hi , ExprKind :: Cast ( lhs , rhs ) , None ) ; continue } else if op == AssocOp :: Colon { let rhs = try ! ( self parse_ty ( ) ) ; lhs = self . mk_expr ( lhs_span . lo , rhs . span . hi , ExprKind :: Type ( lhs , rhs ) , None ) ; continue } else if op == AssocOp :: DotDot { // If we didn’t have to handle `x..`, it would be pretty easy to generalise // it to the Fixity::None code. // // We have 2 alternatives here: `x..y` and `x..` The other two variants are // handled with `parse_prefix_range_expr` call above. let rhs = if self . is_at_start_of_range_notation_rhs ( ) { let rhs = self . parse_assoc_expr_with ( op . precedence ( ) + 1 , LhsExpr :: NotYetParsed ) ; match rhs { Ok ( e ) => Some ( e ) , Err ( mut e ) => { e . cancel ( ) ; None } } } else { None } ; let ( lhs_span , rhs_span ) = ( lhs_span , if let Some ( ref x ) = rhs { x . span } else { cur_op_span } ) ; let r = self . mk_range ( Some ( lhs ) , rhs ) ; lhs = self . mk_expr ( lhs_span . lo , rhs_span . hi , r , None ) ; break } let rhs = try ! ( match op fixity ( ) { Fixity Right self with_res ( restrictions Restrictions RESTRICTION_STMT_EXPR this { this parse_assoc_expr_with ( op precedence ( ) LhsExpr NotYetParsed ) } ) Fixity Left self with_res ( restrictions Restrictions RESTRICTION_STMT_EXPR this { this parse_assoc_expr_with ( op precedence ( ) 1 LhsExpr NotYetParsed ) } ) // We currently have no non-associative operators that are not handled above by // the special cases. The code is here only for future convenience. Fixity None self with_res ( restrictions Restrictions RESTRICTION_STMT_EXPR this { this parse_assoc_expr_with ( op precedence ( ) 1 LhsExpr NotYetParsed ) } ) } ) ; lhs = match op { AssocOp :: Add | AssocOp :: Subtract | AssocOp :: Multiply | AssocOp :: Divide | AssocOp :: Modulus | AssocOp :: LAnd | AssocOp :: LOr | AssocOp :: BitXor | AssocOp :: BitAnd | AssocOp :: BitOr | AssocOp :: ShiftLeft | AssocOp :: ShiftRight | AssocOp :: Equal | AssocOp :: Less | AssocOp :: LessEqual | AssocOp :: NotEqual | AssocOp :: Greater | AssocOp :: GreaterEqual => { let ast_op = op . to_ast_binop ( ) . unwrap ( ) ; let ( lhs_span , rhs_span ) = ( lhs_span , rhs . span ) ; let binary = self . mk_binary ( codemap :: respan ( cur_op_span , ast_op ) , lhs , rhs ) ; self . mk_expr ( lhs_span . lo , rhs_span . hi , binary , None ) } AssocOp :: Assign => self . mk_expr ( lhs_span . lo , rhs . span . hi , ExprKind :: Assign ( lhs , rhs ) , None ) , AssocOp :: Inplace => self . mk_expr ( lhs_span . lo , rhs . span . hi , ExprKind :: InPlace ( lhs , rhs ) , None ) , AssocOp :: AssignOp ( k ) => { let aop = match k { token :: Plus => BinOpKind :: Add , token :: Minus => BinOpKind :: Sub , token :: Star => BinOpKind :: Mul , token :: Slash => BinOpKind :: Div , token :: Percent => BinOpKind :: Rem , token :: Caret => BinOpKind :: BitXor , token :: And => BinOpKind :: BitAnd , token :: Or => BinOpKind :: BitOr , token :: Shl => BinOpKind :: Shl , token :: Shr => BinOpKind :: Shr , } ; let ( lhs_span , rhs_span ) = ( lhs_span , rhs . span ) ; let aopexpr = self . mk_assign_op ( codemap :: respan ( cur_op_span , aop ) , lhs , rhs ) ; self . mk_expr ( lhs_span . lo , rhs_span . hi , aopexpr , None ) } AssocOp :: As | AssocOp :: Colon | AssocOp :: DotDot => { self . bug ( " " ) } } ; if op . fixity ( ) == Fixity :: None { break } } Ok ( lhs ) }
Parse an associative expression with operators of at least `min_prec` precedence
Parse an associative expression with operators of at least ` min_prec ` precedence
&mut self
min_prec
usize
lhs
LhsExpr
&mut self
min_prec
usize
lhs
LhsExpr