diff --git a/examples/reid/easiest.reid b/examples/reid/easiest.reid index fa6f89b..0d57517 100644 --- a/examples/reid/easiest.reid +++ b/examples/reid/easiest.reid @@ -4,7 +4,7 @@ import std::print; fn main() { let hello = 32 + { - 2 + 2 + 2 + 3 }; let beep = hello + fibonacci(15); return beep; diff --git a/src/ast.rs b/src/ast.rs index 431bdad..4b56eb4 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -33,12 +33,6 @@ pub enum Literal { I32(i32), } -#[derive(Debug, Clone)] -pub enum BinaryOperator { - Add, - Mult, -} - #[derive(Debug, Clone)] pub enum Expression { VariableName(String), @@ -46,12 +40,13 @@ pub enum Expression { Binop(BinaryOperator, Box, Box), FunctionCall(Box), BlockExpr(Box), + IfExpr(Box), } impl Parse for Expression { fn parse(mut stream: TokenStream) -> Result { let lhs = parse_primary_expression(&mut stream)?; - parse_binop_rhs(&mut stream, lhs, 0) + parse_binop_rhs(&mut stream, lhs, None) } } @@ -60,6 +55,8 @@ fn parse_primary_expression(stream: &mut TokenStream) -> Result Expression::VariableName(v.clone()), @@ -84,40 +81,79 @@ fn parse_primary_expression(stream: &mut TokenStream) -> Result, ) -> Result { - while let Some(token) = stream.peek() { - let curr_token_prec = token.get_token_prec(); + let expr_prec = if let Some(op) = operator { + op.get_precedence() + 1 + } else { + 0 + }; + + while let Some(op) = operator.take().as_ref().or(stream.parse().as_ref().ok()) { + let curr_token_prec = op.get_precedence(); if curr_token_prec < expr_prec { break; // Just return lhs } else { - // token has to be an operator - stream.next(); // Eat token - let mut rhs = parse_primary_expression(stream)?; - if let Some(next_op) = stream.peek() { - let next_prec = next_op.get_token_prec(); + if let Ok(next_op) = stream.parse::() { + let next_prec = next_op.get_precedence(); if curr_token_prec < next_prec { // Operator on the right of rhs has more precedence, turn // rhs into lhs for new binop - rhs = parse_binop_rhs(stream, rhs, curr_token_prec + 1)?; + rhs = parse_binop_rhs(stream, rhs, Some(next_op))?; + } else { + let _ = operator.insert(next_op); } } - use BinaryOperator::*; - - lhs = match &token { - Token::Plus => Expression::Binop(Add, Box::new(lhs), Box::new(rhs)), - Token::Times => Expression::Binop(Mult, Box::new(lhs), Box::new(rhs)), - _ => Err(stream.expected_err("+ or *")?)?, - }; + lhs = Expression::Binop(*op, Box::new(lhs), Box::new(rhs)); } } Ok(lhs) } +#[derive(Debug, Clone, Copy)] +pub enum BinaryOperator { + Add, + Minus, + Mult, + + And, + LessThan, +} + +impl Parse for BinaryOperator { + fn parse(mut stream: TokenStream) -> Result { + Ok(match (stream.next(), stream.peek()) { + (Some(Token::Et), Some(Token::Et)) => { + stream.next(); + BinaryOperator::And + } + (Some(Token::LessThan), _) => BinaryOperator::LessThan, + + (Some(Token::Plus), _) => BinaryOperator::Add, + (Some(Token::Minus), _) => BinaryOperator::Minus, + (Some(Token::Times), _) => BinaryOperator::Mult, + (_, _) => Err(stream.expected_err("expected operator")?)?, + }) + } +} + +impl BinaryOperator { + pub fn get_precedence(&self) -> i8 { + use BinaryOperator::*; + match &self { + Add => 10, + Minus => 10, + Mult => 20, + And => 100, + LessThan => 100, + } + } +} + #[derive(Debug, Clone)] pub struct FunctionCallExpression(pub String, pub Vec); @@ -145,6 +181,16 @@ impl Parse for FunctionCallExpression { } } +#[derive(Debug, Clone)] +pub struct IfExpression(Expression, pub Block); + +impl Parse for IfExpression { + fn parse(mut stream: TokenStream) -> Result { + stream.expect(Token::If)?; + Ok(IfExpression(stream.parse()?, stream.parse()?)) + } +} + #[derive(Debug, Clone)] pub struct LetStatement(pub String, pub Expression); @@ -260,7 +306,8 @@ impl Parse for Block { while !matches!(stream.peek(), Some(Token::BraceClose)) { if let Some((r_type, e)) = return_stmt.take() { println!("Oh no, does this statement lack ;"); - dbg!(r_type, e); + dbg!(r_type, &e); + statements.push(BlockLevelStatement::Expression(e)); } let statement = stream.parse()?; if let BlockLevelStatement::Return((r_type, e)) = &statement { diff --git a/src/codegen.rs b/src/codegen.rs index b6f4727..83b1e12 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -173,6 +173,7 @@ impl Expression { let rhs = rhs.codegen(scope)?; Ok(scope.block.mul(lhs, rhs)?) } + _ => panic!("Other binary operators not supported yet!"), }, BlockExpr(block) => { let mut inner = scope.inner(); @@ -201,6 +202,7 @@ impl Expression { .cloned() .ok_or(Error::UndefinedVariable(name.clone())), Literal(lit) => Ok(scope.block.get_const(lit)), + IfExpr(_) => panic!("if expressions not yet supported"), } } } diff --git a/src/lexer.rs b/src/lexer.rs index 9624678..15bd28e 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -20,6 +20,8 @@ pub enum Token { FnKeyword, /// `->` Arrow, + /// `if` + If, // Symbols /// `;` @@ -34,10 +36,14 @@ pub enum Token { Times, /// `-` Minus, + /// `>` GreaterThan, /// `<` LessThan, + /// `&` + Et, + /// `(` ParenOpen, /// `)` @@ -153,6 +159,7 @@ pub fn tokenize>(to_tokenize: T) -> Result, Error "import" => Token::ImportKeyword, "return" => Token::ReturnKeyword, "fn" => Token::FnKeyword, + "if" => Token::If, _ => Token::Identifier(value), }; variant @@ -182,6 +189,7 @@ pub fn tokenize>(to_tokenize: T) -> Result, Error '-' => Token::Minus, '>' => Token::GreaterThan, '<' => Token::LessThan, + '&' => Token::Et, '(' => Token::ParenOpen, ')' => Token::ParenClose, '{' => Token::BraceOpen,