diff options
-rw-r--r-- | src/ast.rs | 22 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/taiga.lalrpop | 25 |
3 files changed, 48 insertions, 1 deletions
@@ -18,12 +18,34 @@ impl<T> WithLocation<T> { location: self.location, } } + + pub fn join_map<U, V, F>(self, other: WithLocation<U>, f: F) -> WithLocation<V> + where F: FnOnce(WithLocation<T>, WithLocation<U>) -> V + { + let loc1 = self.location; + let loc2 = other.location; + WithLocation { + value: f(self, other), + location: (loc1.0, loc2.1), + } + } } #[derive(Debug)] pub struct Program(pub Box<WithLocation<Expression>>); #[derive(Debug)] +pub enum BinOp { + Add, + Sub, + Mul, + Div, + FloorDiv, +} + +#[derive(Debug)] pub enum Expression { + BinOp(BinOp, Box<WithLocation<Expression>>, Box<WithLocation<Expression>>), Number(u64), + Nil, } diff --git a/src/main.rs b/src/main.rs index 5b343ec..bd4659b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,5 +2,5 @@ pub mod ast; pub mod taiga; fn main() { - println!("{:?}", taiga::parse_Program("5")); + println!("{:?}", taiga::parse_Program("(3 + 5) * 7")); } diff --git a/src/taiga.lalrpop b/src/taiga.lalrpop index 08c3cd3..0182a04 100644 --- a/src/taiga.lalrpop +++ b/src/taiga.lalrpop @@ -8,7 +8,32 @@ pub Program: ast::Program = { }; Expression: Box<ast::WithLocation<ast::Expression>> = { + <e1:Expression> "+" <e2:ExpressionMul> => Box::new(e1.join_map(*e2, |v1, v2| { + ast::Expression::BinOp(ast::BinOp::Add, Box::new(v1), Box::new(v2)) + })), + <e1:Expression> "-" <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:ExpressionBase> => Box::new(e1.join_map(*e2, |v1, v2| { + ast::Expression::BinOp(ast::BinOp::Mul, Box::new(v1), Box::new(v2)) + })), + <e1:ExpressionMul> "/" <e2:ExpressionBase> => Box::new(e1.join_map(*e2, |v1, v2| { + ast::Expression::BinOp(ast::BinOp::Div, Box::new(v1), Box::new(v2)) + })), + <e1:ExpressionMul> "//" <e2:ExpressionBase> => Box::new(e1.join_map(*e2, |v1, v2| { + ast::Expression::BinOp(ast::BinOp::FloorDiv, Box::new(v1), Box::new(v2)) + })), + <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()); |