diff --git a/able-script-test/melo-hello.able b/able-script-test/melo-hello.able index 4970c9e..ac4d9f5 100644 --- a/able-script-test/melo-hello.able +++ b/able-script-test/melo-hello.able @@ -1,3 +1,3 @@ var hi = "wonk"; melo hi; -hi print; #Should error out +hi print; # Should error out diff --git a/src/main.rs b/src/main.rs index fb7e7b5..7add24f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ mod repl; mod variables; use clap::{App, Arg}; +use logos::Source; use parser::Parser; fn main() { // variables::test(); @@ -34,7 +35,17 @@ fn main() { // Parse let mut parser = Parser::new(&source); let ast = parser.init(); - println!("{:#?}", ast); + match ast { + Ok(ast) => println!("{:#?}", ast), + Err(e) => { + println!( + "Error `{:?}` occured at span: {:?} = `{:?}`", + e.kind, + e.position.clone(), + source.slice(e.position) + ); + } + } } None => { println!( diff --git a/src/parser/item.rs b/src/parser/item.rs index ea556a5..1d805fb 100644 --- a/src/parser/item.rs +++ b/src/parser/item.rs @@ -27,7 +27,6 @@ pub enum Expr { Subtract { left: Box, right: Box }, Multiply { left: Box, right: Box }, Divide { left: Box, right: Box }, - FunctionCall { iden: Iden, args: Vec }, Literal(Value), Identifier(Iden), } @@ -56,6 +55,10 @@ pub enum Stmt { cond: Box, body: Vec, }, - + FunctionCall { + iden: Iden, + args: Vec, + }, + Print(Expr), Melo(Iden), } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index e90a8d5..9084b01 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -35,9 +35,11 @@ impl<'a> Parser<'a> { if token.is_none() { return Ok(self.ast.clone()); }; - - let expr = self.parse_item(token)?; - self.ast.push(expr); + if matches!(token, Some(Token::Comment)) { + continue; + } + let item = self.parse_item(token)?; + self.ast.push(item); } } @@ -112,9 +114,15 @@ impl<'a> Parser<'a> { fn function_declaration(&mut self) -> ParseResult { let iden = self.require_iden()?; self.require(Token::LeftParenthesis)?; - let args = vec![]; - self.require(Token::RightParenthesis)?; - + let mut args = vec![]; + loop { + let next = self.lexer.next(); + match next { + Some(Token::RightParenthesis) => break, + Some(Token::Identifier(i)) => args.push(Iden(i)), + _ => return Err(self.unexpected_token(None)), + } + } self.require(Token::LeftBrace)?; // Parse function body let body = self.parse_body()?; diff --git a/src/parser/ops.rs b/src/parser/ops.rs index 024b137..69d82c1 100644 --- a/src/parser/ops.rs +++ b/src/parser/ops.rs @@ -2,12 +2,17 @@ use super::*; type ExprResult = Result; +/// Generate infix expression by pattern left right +/// +/// Credits: `@! ! Reiter#4543` #[macro_export] macro_rules! gen_infix { ($($fn_name: ident => $type: tt);*$(;)?) => {$( + /// Generated function for infix operator fn $fn_name(&mut self, left: Expr) -> ExprResult { + self.lexer.next(); let next = self.lexer.next(); - let right = self.ensure_expr(next)?; + let right = self.parse_expr(next)?; Ok(Expr::$type { left: Box::new(left), right: Box::new(right) }) })* }; @@ -15,14 +20,23 @@ macro_rules! gen_infix { impl<'a> Parser<'a> { pub(super) fn parse_ops(&mut self, token: Token) -> ParseResult { - let mut buf: Expr = self.ensure_expr(Some(token))?; + if matches!(self.lexer.peek(), Some(Token::LeftParenthesis)) { + return self.fn_call(token); + } + + let mut buf: Expr = self.parse_expr(Some(token))?; loop { - buf = match self.lexer.next() { + buf = match self.lexer.peek() { Some(Token::Addition) => self.addition(buf)?, Some(Token::Subtract) => self.subtract(buf)?, Some(Token::Multiply) => self.multiply(buf)?, Some(Token::Divide) => self.divide(buf)?, + Some(Token::Print) => { + self.lexer.next(); + self.require(Token::Semicolon)?; + return Ok(Stmt::Print(buf).into()); + } _ => return Ok(buf.into()), } } @@ -37,41 +51,84 @@ impl<'a> Parser<'a> { } /// Ensure that input token is an expression - fn ensure_expr(&mut self, token: Option) -> ExprResult { + fn parse_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))), + Token::LeftParenthesis => self.parse_paren(), 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(); + /// Parse parenthesieted expression + fn parse_paren(&mut self) -> ExprResult { + let next = self.lexer.next(); + let mut buf = self.parse_expr(next)?; + loop { + let next = self.lexer.peek().clone().ok_or(Error { + kind: ErrorKind::EndOfTokenStream, + position: self.lexer.span(), + })?; - while let Some(token) = self.lexer.peek() { - match token { - Token::Identifier(id) => { - args.push(Expr::Identifier(Iden(id.clone()))); + buf = match Some(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)?, + Some(Token::LeftParenthesis) => { + return Err(Error { + kind: ErrorKind::SyntaxError( + "Function call isn't an expression!".to_owned(), + ), + position: self.lexer.span(), + }) + } + Some(Token::RightParenthesis) => { self.lexer.next(); + return Ok(buf); } - Token::RightParenthesis => break, - _ => { - let next = self.lexer.next(); - } - } - self.require(Token::Comma)?; + _ => return Ok(buf.into()), + }; } - self.require(Token::RightParenthesis)?; - Ok(Expr::FunctionCall { iden, args }) + } + + /// Parse function call + fn fn_call(&mut self, token: Token) -> ParseResult { + let iden = if let Token::Identifier(i) = token { + Iden(i) + } else { + return Err(Error { + kind: ErrorKind::InvalidIdentifier, + position: self.lexer.span(), + }); + }; + + self.lexer.next(); + let mut args = Vec::new(); + loop { + let next = self.lexer.next(); + + // No argument function + if matches!(next, Some(Token::RightParenthesis)) { + break; + } + + args.push(self.parse_expr(next)?); + match self.lexer.next() { + Some(Token::RightParenthesis) => break, + Some(Token::Comma) => continue, + _ => return Err(self.unexpected_token(None)), + } + } + self.require(Token::Semicolon)?; + Ok(Stmt::FunctionCall { iden, args }.into()) } } diff --git a/src/repl.rs b/src/repl.rs index 64e2e8d..4aa3038 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,3 +1,4 @@ +use logos::Source; use rustyline::Editor; use crate::parser::Parser; @@ -14,7 +15,17 @@ pub fn repl() { } let mut parser = Parser::new(&line); let ast = parser.init(); - println!("{:#?}", ast); + match ast { + Ok(ast) => println!("{:?}", ast), + Err(e) => { + println!( + "Error `{:?}` occured at span: {:?} = `{:?}`", + e.kind, + e.position.clone(), + line.slice(e.position) + ); + } + } } Err(rustyline::error::ReadlineError::Eof) => { println!("bye");