diff --git a/conditional.schala b/conditional.schala new file mode 100644 index 0000000..88ffbdf --- /dev/null +++ b/conditional.schala @@ -0,0 +1,2 @@ + +if true then 20 else 40 end diff --git a/src/compilation.rs b/src/compilation.rs index bbfa776..7f71889 100644 --- a/src/compilation.rs +++ b/src/compilation.rs @@ -119,6 +119,7 @@ impl CodeGen for Function { impl CodeGen for Expression { fn codegen(&self, data: &mut CompilationData) -> LLVMValueRef { + println!("Running codegen on: {:?}", self); use self::Expression::*; let int_type = LLVMWrap::Int64TypeInContext(data.context); diff --git a/src/parser.rs b/src/parser.rs index 8403fee..23de52d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -45,7 +45,7 @@ pub enum Expression { Variable(String), BinExp(String, Box, Box), Call(String, Vec), - Conditional(Box, Box, Option>), + Conditional(Box, Box>, Option>>), } impl fmt::Display for ASTNode { @@ -311,13 +311,53 @@ impl Parser { self.next(); Expression::StringLiteral(s) } + Some(Keyword(Kw::If)) => try!(self.conditional_expr()), Some(Identifier(_)) => try!(self.identifier_expr()), Some(Token::LParen) => try!(self.paren_expr()), - Some(_) => return ParseError::result_from_str("Expected primary expression"), + Some(e) => { + panic!(); + return ParseError::result_from_str("Expected primary expression"); + } None => return ParseError::result_from_str("Expected primary expression received EoI"), }) } + fn conditional_expr(&mut self) -> ParseResult { + use tokenizer::Token::*; + expect!(self, Keyword(Kw::If)); + let test = try!(self.expression()); + expect!(self, Keyword(Kw::Then)); + let mut then_block = Vec::new(); + loop { + match self.peek() { + None | Some(Keyword(Kw::Else)) | Some(Keyword(Kw::End)) => break, + _ => { + let exp = try!(self.expression()); + then_block.push(exp); + } + } + } + let else_block = if let Some(Keyword(Kw::Else)) = self.peek() { + self.next(); + let mut else_exprs = Vec::new(); + loop { + match self.peek() { + None | Some(Keyword(Kw::End)) => break, + _ => { + let exp = try!(self.expression()); + else_exprs.push(exp); + } + } + } + Some(Box::new(else_exprs)) + } else { + None + }; + + expect!(self, Keyword(Kw::End)); + Ok(Expression::Conditional(Box::new(test), Box::new(then_block), else_block)) + } + fn identifier_expr(&mut self) -> ParseResult { use tokenizer::Token::*; let name = expect_identifier!(self);