diff --git a/src/main.rs b/src/main.rs index eb43c6b5..fb7e7b55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,10 @@ fn main() { println!("{:#?}", ast); } None => { - println!("Hi [AbleScript {}] - AST Printer", env!("CARGO_PKG_VERSION")); + println!( + "Hi [AbleScript {}] - AST Printer", + env!("CARGO_PKG_VERSION") + ); repl::repl(); } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 4c416913..e90a8d58 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -53,7 +53,11 @@ impl<'a> Parser<'a> { let start = self.lexer.span().start; match token { - Token::Identifier(_) => self.parse_ops(token).map(|x| x.into()), + Token::Identifier(_) + | Token::Aboolean(_) + | Token::Boolean(_) + | Token::Integer(_) + | Token::String(_) => self.parse_ops(token), // Control flow Token::If => self.if_cond(), @@ -62,12 +66,6 @@ impl<'a> Parser<'a> { Token::Function => self.function_declaration(), Token::BfFunction => self.bff_declaration(), - // Literals - Token::String(x) => Ok(Expr::Literal(Value::Str(x)).into()), - Token::Integer(x) => Ok(Expr::Literal(Value::Int(x)).into()), - Token::Boolean(x) => Ok(Expr::Literal(Value::Bool(x)).into()), - Token::Aboolean(x) => Ok(Expr::Literal(Value::Abool(x)).into()), - // Prefix keywords // Melo - ban variable from next usage (runtime error) Token::Melo => { diff --git a/src/parser/ops.rs b/src/parser/ops.rs index c9591531..024b1376 100644 --- a/src/parser/ops.rs +++ b/src/parser/ops.rs @@ -2,14 +2,59 @@ use super::*; type ExprResult = Result; +#[macro_export] +macro_rules! gen_infix { + ($($fn_name: ident => $type: tt);*$(;)?) => {$( + fn $fn_name(&mut self, left: Expr) -> ExprResult { + let next = self.lexer.next(); + let right = self.ensure_expr(next)?; + Ok(Expr::$type { left: Box::new(left), right: Box::new(right) }) + })* + }; +} + impl<'a> Parser<'a> { - /// Parse operations (got identifier/value) - pub(super) fn parse_ops(&mut self, token: Token) -> ExprResult { - todo!() + pub(super) fn parse_ops(&mut self, token: Token) -> ParseResult { + let mut buf: Expr = self.ensure_expr(Some(token))?; + + loop { + buf = match self.lexer.next() { + Some(Token::Addition) => self.addition(buf)?, + Some(Token::Subtract) => self.subtract(buf)?, + Some(Token::Multiply) => self.multiply(buf)?, + Some(Token::Divide) => self.divide(buf)?, + _ => return Ok(buf.into()), + } + } + } + + // Generate infix + gen_infix! { + addition => Add; + subtract => Subtract; + multiply => Multiply; + divide => Divide; + } + + /// Ensure that input token is an expression + fn ensure_expr(&mut self, token: Option) -> ExprResult { + let token = token.ok_or(Error { + kind: ErrorKind::EndOfTokenStream, + position: self.lexer.span(), + })?; + match token { + Token::Boolean(b) => Ok(Expr::Literal(Value::Bool(b))), + Token::Integer(i) => Ok(Expr::Literal(Value::Int(i))), + Token::String(s) => Ok(Expr::Literal(Value::Str(s))), + Token::Aboolean(a) => Ok(Expr::Literal(Value::Abool(a))), + Token::Identifier(i) => Ok(Expr::Identifier(Iden(i))), + t => Err(self.unexpected_token(Some(t))), + } } /// Parse function call fn fn_call(&mut self, iden: Iden) -> ExprResult { + return todo!(); self.lexer.next(); let mut args: Vec = Vec::new(); diff --git a/src/parser/utils.rs b/src/parser/utils.rs index 8ccfce80..1706fbea 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -2,7 +2,10 @@ use crate::error::{Error, ErrorKind}; use crate::lexer::Token; use crate::variables::Abool; -use super::{Parser, item::{Iden, Item}}; +use super::{ + item::{Iden, Item}, + Parser, +}; pub fn abool2num(abool: Abool) -> i32 { match abool { @@ -37,7 +40,7 @@ impl<'a> Parser<'a> { } else { Err(Error { kind: ErrorKind::InvalidIdentifier, - position: self.lexer.span(), + position: self.lexer.span(), }) } } @@ -50,7 +53,7 @@ impl<'a> Parser<'a> { self.lexer.slice(), s ), - None => format!("Unexpected token: `{}`)", self.lexer.slice(),), + None => format!("Unexpected token: `{}`", self.lexer.slice(),), }; Error { kind: ErrorKind::SyntaxError(error_msg),