diff options
-rw-r--r-- | src/ast.rs | 19 | ||||
-rw-r--r-- | src/taiga.lalrpop | 19 |
2 files changed, 38 insertions, 0 deletions
@@ -60,6 +60,7 @@ pub enum BinOp { #[derive(Debug)] pub enum Expression { + Let(Vec<WithLocation<VarDec>>, Box<WithLocation<Expression>>), UnaryOp(UnaryOp, Box<WithLocation<Expression>>), BinOp(BinOp, Box<WithLocation<Expression>>, Box<WithLocation<Expression>>), Number(u64), @@ -67,3 +68,21 @@ pub enum Expression { Name(String), Nil, } + +#[derive(Debug)] +pub struct VarDec { + name: WithLocation<String>, + type_: Option<String>, + value: Box<WithLocation<Expression>>, +} + +impl VarDec { + pub fn new(name: WithLocation<String>, type_: Option<String>, + value: Box<WithLocation<Expression>>) -> VarDec { + VarDec { + name: name, + type_: type_, + value: value, + } + } +} diff --git a/src/taiga.lalrpop b/src/taiga.lalrpop index be47147..851cb24 100644 --- a/src/taiga.lalrpop +++ b/src/taiga.lalrpop @@ -7,6 +7,19 @@ pub Program: ast::Program = { Expression => ast::Program(<>), }; +VarDec: Box<WithLocation<ast::VarDec>> = + <l: @L> "var" <name: Name> "=" <exp: Expression> <r: @R> => + Box::new(WithLocation::new(ast::VarDec::new(name, None, exp), l, r)); + +DeclarationsList: Vec<WithLocation<ast::VarDec>> = { + <h: DeclarationsList> <t: VarDec> => { + let mut h = h; + h.push(*t); + h + }, + <VarDec> => vec![*<>], +}; + 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)) @@ -87,6 +100,8 @@ ExpressionBase: Box<ast::WithLocation<ast::Expression>> = { String => Box::new(<>.map(|v| ast::Expression::String(v))), Name => Box::new(<>.map(|v| ast::Expression::Name(v))), Spanned<r"nil"> => Box::new(<>.map(|v| ast::Expression::Nil)), + <l: @L> "let" <d: DeclarationsList> "in" <e: Expression> "end" <r: @R> => + Box::new(WithLocation::new(ast::Expression::Let(d, e), l, r)), "(" <Expression> ")" => <>, }; @@ -102,6 +117,10 @@ Spanned<T>: WithLocation<T> = { match { "nil", + "var", + "let", + "in", + "end", } else { r"[[:alpha:]_][[:alpha:]_0-9]*", |