use std::str::FromStr; use ast::{self, WithLocation}; grammar; pub Program: ast::Program = { Expression => ast::Program(<>), }; Expression: Box<ast::WithLocation<ast::Expression>> = { <e1:Expression> "&&" <e2:ExpressionEq> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::And, Box::new(v1), Box::new(v2)) })), <e1:Expression> "||" <e2:ExpressionEq> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Or, Box::new(v1), Box::new(v2)) })), <l: @L> "!" <e: ExpressionEq> <r: @R> => Box::new(WithLocation::new( ast::Expression::UnaryOp(ast::UnaryOp::Not, e), l, r )), <ExpressionEq> => <>, }; ExpressionEq: Box<ast::WithLocation<ast::Expression>> = { <e1:ExpressionEq> "=" <e2:ExpressionCmp> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Eq, Box::new(v1), Box::new(v2)) })), <e1:ExpressionEq> "!=" <e2:ExpressionCmp> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Neq, Box::new(v1), Box::new(v2)) })), <ExpressionCmp> => <>, }; ExpressionCmp: Box<ast::WithLocation<ast::Expression>> = { <e1:ExpressionCmp> ">" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Gt, Box::new(v1), Box::new(v2)) })), <e1:ExpressionCmp> "<" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Lt, Box::new(v1), Box::new(v2)) })), <e1:ExpressionCmp> ">=" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Ge, Box::new(v1), Box::new(v2)) })), <e1:ExpressionCmp> "<=" <e2:ExpressionAdd> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Le, Box::new(v1), Box::new(v2)) })), <ExpressionAdd> => <>, }; ExpressionAdd: Box<ast::WithLocation<ast::Expression>> = { <e1:ExpressionAdd> "+" <e2:ExpressionMul> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Add, Box::new(v1), Box::new(v2)) })), <e1:ExpressionAdd> "-" <e2:ExpressionMul> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Sub, Box::new(v1), Box::new(v2)) })), <ExpressionMul> => <>, }; ExpressionMul: Box<ast::WithLocation<ast::Expression>> = { <e1:ExpressionMul> "*" <e2:ExpressionSign> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Mul, Box::new(v1), Box::new(v2)) })), <e1:ExpressionMul> "/" <e2:ExpressionSign> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::Div, Box::new(v1), Box::new(v2)) })), <e1:ExpressionMul> "//" <e2:ExpressionSign> => Box::new(e1.join_map(*e2, |v1, v2| { ast::Expression::BinOp(ast::BinOp::FloorDiv, Box::new(v1), Box::new(v2)) })), <ExpressionSign> => <>, }; ExpressionSign: Box<ast::WithLocation<ast::Expression>> = { <l: @L> "+" <e: ExpressionBase> <r: @R> => Box::new(WithLocation::new( ast::Expression::UnaryOp(ast::UnaryOp::Pos, e), l, r )), <l: @L> "-" <e: ExpressionBase> <r: @R> => Box::new(WithLocation::new( ast::Expression::UnaryOp(ast::UnaryOp::Neg, e), l, r )), <ExpressionBase> => <>, }; ExpressionBase: Box<ast::WithLocation<ast::Expression>> = { Num => Box::new(<>.map(|v| ast::Expression::Number(v))), Spanned<r"nil"> => Box::new(<>.map(|v| ast::Expression::Nil)), "(" <Expression> ")" => <>, }; Num: WithLocation<u64> = <e: Spanned<r"[0-9]+">> => e.map(|v| u64::from_str(v).unwrap()); Spanned<T>: WithLocation<T> = { <l: @L> <v: T> <r: @R> => WithLocation::new(v, l, r) };