fn leaf_expr(&mut self) -> WeldResult<Box<Expr>> {
        let mut annotations = Annotations::new();
        self.parse_annotations(&mut annotations)?;

        match *self.next() {
            TI16Literal(v) => Ok(expr_box(Literal(I16Literal(v)), Annotations::new())),
            TI8Literal(v) => Ok(expr_box(Literal(I8Literal(v)), Annotations::new())),
            TI32Literal(v) => Ok(expr_box(Literal(I32Literal(v)), Annotations::new())),
            TI64Literal(v) => Ok(expr_box(Literal(I64Literal(v)), Annotations::new())),
            TF32Literal(v) => Ok(expr_box(
                Literal(F32Literal(v.to_bits())),
                Annotations::new(),
            )),
            TF64Literal(v) => Ok(expr_box(
                Literal(F64Literal(v.to_bits())),
                Annotations::new(),
            )),
            TBoolLiteral(v) => Ok(expr_box(Literal(BoolLiteral(v)), Annotations::new())),
            TStringLiteral(ref v) => Ok(expr_box(
                Literal(StringLiteral(v.clone())),
                Annotations::new(),
            )),

            TI8 => Ok(self.parse_cast(ScalarKind::I8)?),
            TI16 => Ok(self.parse_cast(ScalarKind::I16)?),
            TI32 => Ok(self.parse_cast(ScalarKind::I32)?),
            TI64 => Ok(self.parse_cast(ScalarKind::I64)?),
            TU8 => Ok(self.parse_cast(ScalarKind::U8)?),
            TU16 => Ok(self.parse_cast(ScalarKind::U16)?),
            TU32 => Ok(self.parse_cast(ScalarKind::U32)?),
            TU64 => Ok(self.parse_cast(ScalarKind::U64)?),
            TF32 => Ok(self.parse_cast(ScalarKind::F32)?),
            TF64 => Ok(self.parse_cast(ScalarKind::F64)?),
            TBool => Ok(self.parse_cast(ScalarKind::Bool)?),

            TToVec => {
                self.consume(TOpenParen)?;
                let child_expr = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(ToVec { child_expr }, Annotations::new()))
            }

            TIdent(ref name) => Ok(expr_box(
                Ident(Symbol::new(name.as_str(), 0)),
                Annotations::new(),
            )),

            TOpenParen => {
                let expr = self.expr()?;
                if *self.next() != TCloseParen {
                    return compile_err!("Expected ')' after {:?}", expr);
                }
                Ok(expr)
            }

            TOpenBracket => {
                let mut exprs: Vec<Expr> = Vec::new();
                while *self.peek() != TCloseBracket {
                    let expr = self.expr()?;
                    exprs.push(*expr);
                    if *self.peek() == TComma {
                        self.next();
                    } else if *self.peek() != TCloseBracket {
                        return compile_err!("Expected ',' or ']'");
                    }
                }
                self.consume(TCloseBracket)?;
                Ok(expr_box(MakeVector { elems: exprs }, Annotations::new()))
            }

            TOpenBrace => {
                let mut exprs: Vec<Expr> = Vec::new();
                while *self.peek() != TCloseBrace {
                    let expr = self.expr()?;
                    exprs.push(*expr);
                    if *self.peek() == TComma {
                        self.next();
                    } else if *self.peek() != TCloseBrace {
                        return compile_err!("Expected ',' or '}}'");
                    }
                }
                self.consume(TCloseBrace)?;
                Ok(expr_box(MakeStruct { elems: exprs }, Annotations::new()))
            }

            TIf => {
                self.consume(TOpenParen)?;
                let cond = self.expr()?;
                self.consume(TComma)?;
                let on_true = self.expr()?;
                self.consume(TComma)?;
                let on_false = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(
                    If {
                        cond,
                        on_true,
                        on_false,
                    },
                    annotations,
                ))
            }

            TIterate => {
                self.consume(TOpenParen)?;
                let initial = self.expr()?;
                self.consume(TComma)?;
                let update_func = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(
                    Iterate {
                        initial,
                        update_func,
                    },
                    Annotations::new(),
                ))
            }

            TSelect => {
                self.consume(TOpenParen)?;
                let cond = self.expr()?;
                self.consume(TComma)?;
                let on_true = self.expr()?;
                self.consume(TComma)?;
                let on_false = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(
                    Select {
                        cond,
                        on_true,
                        on_false,
                    },
                    Annotations::new(),
                ))
            }

            TBroadcast => {
                self.consume(TOpenParen)?;
                let expr = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Broadcast(expr), Annotations::new()))
            }

            TSerialize => {
                self.consume(TOpenParen)?;
                let expr = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Serialize(expr), Annotations::new()))
            }

            TDeserialize => {
                self.consume(TOpenBracket)?;
                let value_ty = self.type_()?;
                self.consume(TCloseBracket)?;
                self.consume(TOpenParen)?;
                let value = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(
                    Deserialize {
                        value_ty: Box::new(value_ty),
                        value,
                    },
                    annotations,
                ))
            }

            TCUDF => {
                let mut args = vec![];
                self.consume(TOpenBracket)?;
                let sym_name = self.symbol()?;
                self.consume(TComma)?;
                let return_ty = self.type_()?;
                self.consume(TCloseBracket)?;
                self.consume(TOpenParen)?;
                while *self.peek() != TCloseParen {
                    let arg = self.expr()?;
                    args.push(*arg);
                    if *self.peek() == TComma {
                        self.consume(TComma)?;
                    }
                }
                self.consume(TCloseParen)?;
                Ok(expr_box(
                    CUDF {
                        sym_name: sym_name.name(),
                        return_ty: Box::new(return_ty),
                        args,
                    },
                    annotations,
                ))
            }

            TZip => {
                self.consume(TOpenParen)?;
                let mut vectors = vec![];
                while *self.peek() != TCloseParen {
                    let vector = self.expr()?;
                    vectors.push(*vector);
                    if *self.peek() == TComma {
                        self.next();
                    } else if *self.peek() != TCloseParen {
                        return compile_err!("Expected ',' or ')'");
                    }
                }
                self.consume(TCloseParen)?;
                if vectors.len() < 2 {
                    return compile_err!("Expected two or more arguments in Zip");
                }
                Ok(expr_box(Zip { vectors }, Annotations::new()))
            }

            TFor => {
                self.consume(TOpenParen)?;
                let mut iters = vec![];
                // Zips only appear as syntactic sugar in the context of Fors (they don't
                // become Zip expressions).
                if *self.peek() == TZip {
                    self.consume(TZip)?;
                    self.consume(TOpenParen)?;
                    iters.push(self.parse_iter()?);
                    while *self.peek() == TComma {
                        self.consume(TComma)?;
                        iters.push(self.parse_iter()?);
                    }
                    self.consume(TCloseParen)?;
                } else {
                    // Single unzipped vector.
                    iters.push(self.parse_iter()?);
                }
                self.consume(TComma)?;
                let builder = self.expr()?;
                self.consume(TComma)?;
                let body = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(
                    For {
                        iters,
                        builder,
                        func: body,
                    },
                    annotations,
                ))
            }

            TLen => {
                self.consume(TOpenParen)?;
                let data = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Length { data }, Annotations::new()))
            }

            TLookup => {
                self.consume(TOpenParen)?;
                let data = self.expr()?;
                self.consume(TComma)?;
                let index = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Lookup { data, index }, Annotations::new()))
            }

            TOptLookup => {
                self.consume(TOpenParen)?;
                let data = self.expr()?;
                self.consume(TComma)?;
                let index = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(OptLookup { data, index }, Annotations::new()))
            }

            TKeyExists => {
                self.consume(TOpenParen)?;
                let data = self.expr()?;
                self.consume(TComma)?;
                let key = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(KeyExists { data, key }, Annotations::new()))
            }

            TSlice => {
                self.consume(TOpenParen)?;
                let data = self.expr()?;
                self.consume(TComma)?;
                let index = self.expr()?;
                self.consume(TComma)?;
                let size = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Slice { data, index, size }, Annotations::new()))
            }

            TSort => {
                self.consume(TOpenParen)?;
                let data = self.expr()?;
                self.consume(TComma)?;
                let cmpfunc = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Sort { data, cmpfunc }, Annotations::new()))
            }
            TExp => self.unary_leaf_expr(TExp),
            TLog => self.unary_leaf_expr(TLog),
            TErf => self.unary_leaf_expr(TErf),
            TSqrt => self.unary_leaf_expr(TSqrt),
            TSin => self.unary_leaf_expr(TSin),
            TCos => self.unary_leaf_expr(TCos),
            TTan => self.unary_leaf_expr(TTan),
            TASin => self.unary_leaf_expr(TASin),
            TACos => self.unary_leaf_expr(TACos),
            TATan => self.unary_leaf_expr(TATan),
            TSinh => self.unary_leaf_expr(TSinh),
            TCosh => self.unary_leaf_expr(TCosh),
            TTanh => self.unary_leaf_expr(TTanh),

            TMerge => {
                self.consume(TOpenParen)?;
                let builder = self.expr()?;
                self.consume(TComma)?;
                let value = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Merge { builder, value }, Annotations::new()))
            }

            TResult => {
                self.consume(TOpenParen)?;
                let value = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Res { builder: value }, Annotations::new()))
            }

            TAppender => {
                let mut elem_type = Unknown;
                if *self.peek() == TOpenBracket {
                    self.consume(TOpenBracket)?;
                    elem_type = self.type_()?;
                    self.consume(TCloseBracket)?;
                }

                let arg = if *self.peek() == TOpenParen {
                    self.consume(TOpenParen)?;
                    let arg = self.expr()?;
                    self.consume(TCloseParen)?;
                    Some(arg)
                } else {
                    None
                };

                let mut expr = expr_box(NewBuilder(arg), Annotations::new());
                expr.ty = Builder(Appender(Box::new(elem_type)), annotations);
                Ok(expr)
            }

            TMerger => {
                let elem_type: Type;
                self.consume(TOpenBracket)?;
                elem_type = self.type_()?;
                self.consume(TComma)?;
                let bin_op = self.commutative_binop_()?;
                self.consume(TCloseBracket)?;

                let mut value = None;
                if *self.peek() == TOpenParen {
                    self.consume(TOpenParen)?;
                    value = Some(self.expr()?);
                    self.consume(TCloseParen)?;
                }

                let mut expr = expr_box(NewBuilder(value), Annotations::new());
                expr.ty = Builder(Merger(Box::new(elem_type), bin_op), annotations);
                Ok(expr)
            }

            TDictMerger => {
                let key_type: Type;
                let value_type: Type;
                self.consume(TOpenBracket)?;
                key_type = self.type_()?;
                self.consume(TComma)?;
                value_type = self.type_()?;
                self.consume(TComma)?;
                let bin_op = self.commutative_binop_()?;
                self.consume(TCloseBracket)?;

                let arg = if *self.peek() == TOpenParen {
                    self.consume(TOpenParen)?;
                    let arg = self.expr()?;
                    self.consume(TCloseParen)?;
                    Some(arg)
                } else {
                    None
                };

                let mut expr = expr_box(NewBuilder(arg), Annotations::new());
                expr.ty = Builder(
                    DictMerger(Box::new(key_type), Box::new(value_type), bin_op),
                    annotations,
                );
                Ok(expr)
            }

            TGroupMerger => {
                let key_type: Type;
                let value_type: Type;
                self.consume(TOpenBracket)?;
                key_type = self.type_()?;
                self.consume(TComma)?;
                value_type = self.type_()?;
                self.consume(TCloseBracket)?;
                let mut expr = expr_box(NewBuilder(None), Annotations::new());
                expr.ty = Builder(
                    GroupMerger(Box::new(key_type), Box::new(value_type)),
                    annotations,
                );
                Ok(expr)
            }

            TVecMerger => {
                let elem_type: Type;
                self.consume(TOpenBracket)?;
                elem_type = self.type_()?;
                self.consume(TComma)?;
                let bin_op = self.commutative_binop_()?;
                self.consume(TCloseBracket)?;
                self.consume(TOpenParen)?;
                let expr = self.expr()?;
                self.consume(TCloseParen)?;

                let mut expr = expr_box(NewBuilder(Some(expr)), Annotations::new());
                expr.ty = Builder(VecMerger(Box::new(elem_type), bin_op), annotations);
                Ok(expr)
            }

            TMinus => Ok(expr_box(Negate(self.leaf_expr()?), Annotations::new())),
            TBang => Ok(expr_box(Not(self.leaf_expr()?), Annotations::new())),

            TAssert => {
                self.consume(TOpenParen)?;
                let cond = self.expr()?;
                self.consume(TCloseParen)?;
                Ok(expr_box(Assert(cond), Annotations::new()))
            }

            TMin => {
                self.consume(TOpenParen)?;
                let left = self.expr()?;
                self.consume(TComma)?;
                let right = self.expr()?;
                self.consume(TCloseParen)?;

                let res = expr_box(
                    BinOp {
                        kind: Min,
                        left,
                        right,
                    },
                    Annotations::new(),
                );

                Ok(res)
            }

            TMax => {
                self.consume(TOpenParen)?;
                let left = self.expr()?;
                self.consume(TComma)?;
                let right = self.expr()?;
                self.consume(TCloseParen)?;

                let res = expr_box(
                    BinOp {
                        kind: Max,
                        left,
                        right,
                    },
                    Annotations::new(),
                );

                Ok(res)
            }

            TPow => {
                self.consume(TOpenParen)?;
                let left = self.expr()?;
                self.consume(TComma)?;
                let right = self.expr()?;
                self.consume(TCloseParen)?;

                let res = expr_box(
                    BinOp {
                        kind: Pow,
                        left,
                        right,
                    },
                    Annotations::new(),
                );
                Ok(res)
            }

            ref other => compile_err!("Expected expression but got '{}'", other),
        }
    }
Parse a terminal expression at the bottom of the precedence chain.
weld/src/syntax/parser.rs