diff --git a/src/parser/item.rs b/src/parser/item.rs deleted file mode 100644 index 18b721c2..00000000 --- a/src/parser/item.rs +++ /dev/null @@ -1,87 +0,0 @@ -use crate::variables::Value; - -#[derive(Debug, Clone, Hash, PartialEq, Eq)] -pub struct Iden(pub String); - -#[derive(Debug, Clone, PartialEq)] -pub enum Item { - Expr(Expr), - Stmt(Stmt), -} - -impl From for Item { - fn from(e: Expr) -> Self { - Item::Expr(e) - } -} - -impl From for Item { - fn from(i: Iden) -> Self { - Item::Expr(Expr::Identifier(i)) - } -} - -impl From for Item { - fn from(s: Stmt) -> Self { - Item::Stmt(s) - } -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Expr { - Add { left: Box, right: Box }, - Subtract { left: Box, right: Box }, - Multiply { left: Box, right: Box }, - Divide { left: Box, right: Box }, - Lt { left: Box, right: Box }, - Gt { left: Box, right: Box }, - Eq { left: Box, right: Box }, - Neq { left: Box, right: Box }, - And { left: Box, right: Box }, - Or { left: Box, right: Box }, - Not(Box), - Literal(Value), - Identifier(Iden), -} -impl From for Expr { - fn from(i: Iden) -> Self { - Self::Identifier(i) - } -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Stmt { - VariableDeclaration { - iden: Iden, - init: Option, - }, - FunctionDeclaration { - iden: Iden, - args: Vec, - body: Vec, - }, - BfFDeclaration { - iden: Iden, - body: String, - }, - If { - cond: Expr, - body: Vec, - }, - FunctionCall { - iden: Iden, - args: Vec, - }, - Loop { - body: Vec, - }, - - VarAssignment { - iden: Iden, - value: Expr, - }, - Break, - HopBack, - Print(Expr), - Melo(Iden), -} diff --git a/src/parser/mod.rs b/src/parser/mod.rs deleted file mode 100644 index aea7710a..00000000 --- a/src/parser/mod.rs +++ /dev/null @@ -1,311 +0,0 @@ -pub mod item; -mod ops; -mod utils; - -use item::Item; - -use crate::{ - error::{Error, ErrorKind}, - lexer::PeekableLexer, - parser::item::{Expr, Stmt}, - variables::Value, -}; -use crate::{lexer::Token, parser::item::Iden}; - -pub type ParseResult = Result; - -/// Parser structure / state machine -pub struct Parser<'a> { - lexer: PeekableLexer<'a>, - ast: Vec, - tdark: bool, -} - -impl<'a> Parser<'a> { - /// Create a new parser object - pub fn new(source: &'a str) -> Self { - Self { - lexer: PeekableLexer::lexer(source), - ast: Vec::new(), - tdark: false, - } - } - - pub fn init(&mut self) -> Result, Error> { - loop { - let token = self.lexer.next(); - - match token { - Some(Token::Comment) => continue, - Some(Token::TDark) => { - let mut block = self.tdark_block()?; - self.ast.append(&mut block); - } - None => return Ok(self.ast.clone()), - _ => { - let item = self.parse_item(token)?; - self.ast.push(item); - } - } - } - } - - fn parse_item(&mut self, token: Option) -> ParseResult { - if matches!(token, None) { - return Err(Error { - kind: ErrorKind::EndOfTokenStream, - position: self.lexer.span(), - }); - } - - let token = token.unwrap(); - let start = self.lexer.span().start; - - match token { - Token::Identifier(_) - | Token::Aboolean(_) - | Token::Boolean(_) - | Token::Integer(_) - | Token::String(_) - | Token::Nul - | Token::LeftParenthesis - | Token::Assignment - | Token::LogNot => self.parse_ops(token), - - // Control flow - Token::If => self.if_cond(), - Token::Loop => self.loop_block(), - - Token::HopBack => { - self.require(Token::Semicolon)?; - Ok(Stmt::HopBack.into()) - } - Token::Break => { - self.require(Token::Semicolon)?; - Ok(Stmt::Break.into()) - } - - // Declarations - Token::Variable => self.variable_declaration(), - Token::Function => self.function_declaration(), - Token::BfFunction => self.bff_declaration(), - - // Prefix keywords - // Melo - ban variable from next usage (runtime error) - Token::Melo => { - let e = self.require_iden()?; - self.require(Token::Semicolon)?; - Ok(Stmt::Melo(e).into()) - } - - _ => Err(Error { - kind: ErrorKind::SyntaxError("Unexpected token".to_owned()), - position: start..self.lexer.span().end, - }), - } - } - - /// Parse variable declaration - /// - /// `var [iden] = [literal];` - fn variable_declaration(&mut self) -> ParseResult { - let iden = self.require_iden()?; - - let peek = self.lexer.peek().clone(); - let init = match peek { - Some(Token::Semicolon) => { - self.lexer.next(); - None - } - Some(Token::Assignment) => { - self.lexer.next(); - let next = self.lexer.next(); - let mut value = self.parse_expr(next)?; - loop { - let peek = self.lexer.peek().clone(); - value = match peek { - Some(Token::Semicolon) => break, - None => { - return Err(Error { - kind: ErrorKind::EndOfTokenStream, - position: self.lexer.span(), - }) - } - Some(t) => self.parse_operation(Some(t), value)?, - }; - } - self.lexer.next(); - Some(value) - } - _ => { - return Err(Error { - kind: ErrorKind::SyntaxError("Unexpected token".to_owned()), - position: self.lexer.span(), - }) - } - }; - - Ok(Stmt::VariableDeclaration { iden, init }.into()) - } - - /// Declare function - /// - /// `functio [iden] ([expr], [expr]) { ... } - fn function_declaration(&mut self) -> ParseResult { - let iden = self.require_iden()?; - - self.require(Token::LeftParenthesis)?; - 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()?; - - Ok(Stmt::FunctionDeclaration { iden, args, body }.into()) - } - - /// Declare BF FFI Function - /// - /// `bff [iden] { ... }` - fn bff_declaration(&mut self) -> ParseResult { - let iden = self.require_iden()?; - self.require(Token::LeftBrace)?; - - let mut body = String::new(); - loop { - let token = { - match self.lexer.next() { - Some(t) => t, - None => { - return Err(Error { - kind: ErrorKind::EndOfTokenStream, - position: self.lexer.span(), - }) - } - } - }; - - body.push_str(match token { - Token::OpGt - | Token::OpLt - | Token::Addition - | Token::Subtract - | Token::FullStop - | Token::Comma - | Token::LeftBracket - | Token::RightBracket => self.lexer.slice(), - Token::RightBrace => break, - _ => return Err(self.unexpected_token(None)), - }); - } - Ok(Stmt::BfFDeclaration { iden, body }.into()) - } - - /// Parse If-stmt - pub fn if_cond(&mut self) -> ParseResult { - self.require(Token::LeftParenthesis)?; - let cond = self.parse_paren()?; - self.require(Token::LeftBrace)?; - - let body = self.parse_body()?; - - Ok(Stmt::If { cond, body }.into()) - } - - /// Parse loop - pub fn loop_block(&mut self) -> ParseResult { - self.require(Token::LeftBrace)?; - let body = self.parse_body()?; - - Ok(Stmt::Loop { body }.into()) - } - - /// T-Dark block parsing - pub fn tdark_block(&mut self) -> Result, Error> { - self.require(Token::LeftBrace)?; - self.tdark = true; - let mut body = Vec::new(); - loop { - let token = { - match self.lexer.next() { - Some(t) => t, - None => { - return Err(Error { - kind: ErrorKind::EndOfTokenStream, - position: self.lexer.span(), - }) - } - } - }; - - if token == Token::RightBrace { - break; - } - body.push(self.parse_item(Some(token))?); - } - self.tdark = false; - Ok(body) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use Expr::*; - use Stmt::*; - - #[test] - fn control_flow() { - let code = r#"loop { var a = 3 + 2; if (a == 5) { break; } }"#; - - let expected: &[Item] = &[Item::Stmt(Loop { - body: vec![ - VariableDeclaration { - iden: Iden("a".to_owned()), - init: Some(Add { - left: Box::new(Literal(Value::Int(3))), - right: Box::new(Literal(Value::Int(2))), - }), - } - .into(), - If { - cond: Eq { - left: Box::new(Iden("a".to_owned()).into()), - right: Box::new(Literal(Value::Int(5)).into()), - }, - body: vec![Break.into()], - } - .into(), - ], - })]; - let ast = Parser::new(code).init().unwrap(); - - assert_eq!(ast, expected) - } - - #[test] - fn tdark() { - let code = r#"T-Dark { var lang = nul; lang print; }"#; - let expected: &[Item] = &[ - VariableDeclaration { - iden: Iden("script".to_owned()), - init: Some(Literal(Value::Nul)), - } - .into(), - Print(Iden("script".to_owned()).into()).into(), - ]; - - let ast = Parser::new(code).init().unwrap(); - - assert_eq!(ast, expected) - } -} diff --git a/src/parser/ops.rs b/src/parser/ops.rs deleted file mode 100644 index e64506f7..00000000 --- a/src/parser/ops.rs +++ /dev/null @@ -1,197 +0,0 @@ -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.parse_expr(next)?; - Ok(Expr::$type { left: Box::new(left), right: Box::new(right) }) - })* - }; -} - -impl<'a> Parser<'a> { - pub(super) fn parse_ops(&mut self, token: Token) -> ParseResult { - // Statements - match self.lexer.peek() { - Some(Token::LeftParenthesis) => return self.fn_call(token), - Some(Token::Assignment) => return self.parse_assignment(token), - _ => (), - } - - let mut buf: Expr = self.parse_expr(Some(token))?; - - loop { - let peek = self.lexer.peek().clone(); - buf = match peek { - // Print statement - Some(Token::Print) => { - self.lexer.next(); - self.require(Token::Semicolon)?; - return Ok(Stmt::Print(buf).into()); - } - None => return Ok(buf.into()), - - // An expression - _ => self.parse_operation(peek, buf)?, - } - } - } - - /// Match and perform - pub(super) fn parse_operation(&mut self, token: Option, buf: Expr) -> ExprResult { - match token { - 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::OpLt) => self.cmplt(buf), - Some(Token::OpGt) => self.cmpgt(buf), - Some(Token::OpEq) => self.cmpeq(buf), - Some(Token::OpNeq) => self.cmpneq(buf), - Some(Token::LogAnd) => self.logand(buf), - Some(Token::LogOr) => self.logor(buf), - Some(Token::LeftParenthesis) => Err(Error { - kind: ErrorKind::SyntaxError("Function call isn't an expression!".to_owned()), - position: self.lexer.span(), - }), - Some(_) | None => Err(self.unexpected_token(None)), - } - } - - fn parse_assignment(&mut self, token: Token) -> ParseResult { - self.lexer.next(); - - // Extract identifier - let iden = if let Token::Identifier(i) = token { - Iden(i) - } else { - return Err(Error { - kind: ErrorKind::InvalidIdentifier, - position: self.lexer.span(), - }); - }; - - let next = self.lexer.next(); - let mut value = self.parse_expr(next)?; - - loop { - let peek = self.lexer.peek().clone(); - value = match peek { - Some(Token::Semicolon) => break, - None => { - return Err(Error { - kind: ErrorKind::EndOfTokenStream, - position: self.lexer.span(), - }) - } - Some(t) => self.parse_operation(Some(t), value)?, - }; - } - - self.lexer.next(); - - Ok(Stmt::VarAssignment { iden, value }.into()) - } - // Generate infix - gen_infix! { - addition => Add; - subtract => Subtract; - multiply => Multiply; - divide => Divide; - cmplt => Lt; - cmpgt => Gt; - cmpeq => Eq; - cmpneq => Neq; - logand => And; - logor => Or; - } - - /// Ensure that input token is an expression - pub(super) 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(if self.tdark { - s.replace("lang", "script") - } else { - s - }))), - Token::Aboolean(a) => Ok(Expr::Literal(Value::Abool(a))), - Token::Identifier(i) => Ok(Expr::Identifier(Iden(if self.tdark { - i.replace("lang", "script") - } else { - i - }))), - Token::Nul => Ok(Expr::Literal(Value::Nul)), - Token::LogNot => { - let next = self.lexer.next(); - Ok(Expr::Not(Box::new(self.parse_expr(next)?))) - } - Token::LeftParenthesis => self.parse_paren(), - t => Err(self.unexpected_token(Some(t))), - } - } - - /// Parse parenthesieted expression - pub(super) fn parse_paren(&mut self) -> ExprResult { - let next = self.lexer.next(); - let mut buf = self.parse_expr(next)?; - loop { - let peek = self.lexer.peek().clone(); - buf = match peek { - Some(Token::RightParenthesis) => { - self.lexer.next(); - return Ok(buf); - } - None => return Ok(buf), - Some(t) => self.parse_operation(Some(t), buf)?, - }; - } - } - - /// 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/parser/utils.rs b/src/parser/utils.rs deleted file mode 100644 index 8146ebcd..00000000 --- a/src/parser/utils.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::{ - error::{Error, ErrorKind}, - lexer::Token, - variables::Abool, -}; - -use super::{ - item::{Iden, Item}, - Parser, -}; - -pub fn abool2num(abool: Abool) -> i32 { - match abool { - Abool::Never => -1, - Abool::Sometimes => 0, - Abool::Always => 1, - } -} -pub fn num2abool(number: i32) -> Abool { - match number { - -1 => Abool::Never, - 0 => Abool::Sometimes, - 1 => Abool::Always, - _ => Abool::Sometimes, - } -} - -impl<'a> Parser<'a> { - /// Require type of token as next and return it's value (sometimes irrelevant) - pub(super) fn require(&mut self, with: Token) -> Result { - if self.lexer.next() == Some(with.clone()) { - Ok(self.lexer.slice().to_owned()) - } else { - Err(self.unexpected_token(Some(with))) - } - } - - /// Require an identifier on next and return it - pub(super) fn require_iden(&mut self) -> Result { - if let Some(Token::Identifier(id)) = self.lexer.next() { - if self.tdark { - Ok(Iden(id.replace("lang", "script"))) - } else { - Ok(Iden(id)) - } - } else { - Err(Error { - kind: ErrorKind::InvalidIdentifier, - position: self.lexer.span(), - }) - } - } - - /// Throw unexpected token error (optionally what was expected) - pub(super) fn unexpected_token(&mut self, expected: Option) -> Error { - let error_msg = match expected { - Some(s) => format!( - "Unexpected token: `{}` (required: `{:?}`)", - self.lexer.slice(), - s - ), - None => format!("Unexpected token: `{}`", self.lexer.slice(),), - }; - Error { - kind: ErrorKind::SyntaxError(error_msg), - position: self.lexer.span(), - } - } - - pub(super) fn parse_body(&mut self) -> Result, Error> { - let mut body = Vec::new(); - loop { - let token = { - match self.lexer.next() { - Some(t) => t, - None => { - return Err(Error { - kind: ErrorKind::EndOfTokenStream, - position: self.lexer.span(), - }) - } - } - }; - - if token == Token::RightBrace { - break; - } - body.push(self.parse_item(Some(token))?); - } - Ok(body) - } -}