From 30eedbc854d328221235fc5c136ab4ce4f579ce4 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 3 May 2021 21:35:43 +0200 Subject: [PATCH] Fixed some incompatible old code - Added assignment support - Reduced boilerplate - Removed `else` --- src/lexer.rs | 3 -- src/parser/item.rs | 4 +- src/parser/mod.rs | 65 ++++++++++++++------------- src/parser/ops.rs | 109 +++++++++++++++++++++++++++------------------ 4 files changed, 102 insertions(+), 79 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 8474e8cb..dae92c26 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -88,9 +88,6 @@ pub enum Token { #[token("if")] If, - #[token("else")] - Else, - #[token("loop")] Loop, diff --git a/src/parser/item.rs b/src/parser/item.rs index c6b7caf0..18b721c2 100644 --- a/src/parser/item.rs +++ b/src/parser/item.rs @@ -53,7 +53,7 @@ impl From for Expr { pub enum Stmt { VariableDeclaration { iden: Iden, - init: Option>, + init: Option, }, FunctionDeclaration { iden: Iden, @@ -65,7 +65,7 @@ pub enum Stmt { body: String, }, If { - cond: Box, + cond: Expr, body: Vec, }, FunctionCall { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5e8aa298..609e830c 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -111,13 +111,31 @@ impl<'a> Parser<'a> { fn variable_declaration(&mut self) -> ParseResult { let iden = self.require_iden()?; - let init = match self.lexer.next() { - Some(Token::Semicolon) => None, + let peek = self.lexer.peek().clone(); + let init = match peek { + Some(Token::Semicolon) => { + self.lexer.next(); + None + } Some(Token::Assignment) => { - let value = self.lexer.next(); - let value = self.parse_item(value)?; - self.require(Token::Semicolon)?; - Some(Box::new(value)) + 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 { @@ -192,19 +210,12 @@ impl<'a> Parser<'a> { /// Parse If-stmt pub fn if_cond(&mut self) -> ParseResult { self.require(Token::LeftParenthesis)?; - let cond = self.lexer.next(); - let cond = self.parse_item(cond)?; - self.require(Token::RightParenthesis)?; - + let cond = self.parse_paren()?; self.require(Token::LeftBrace)?; let body = self.parse_body()?; - Ok(Stmt::If { - cond: Box::new(cond), - body, - } - .into()) + Ok(Stmt::If { cond: cond, body }.into()) } /// Parse loop @@ -257,23 +268,17 @@ mod tests { body: vec![ VariableDeclaration { iden: Iden("a".to_owned()), - init: Some(Box::new( - Add { - left: Box::new(Literal(Value::Int(3))), - right: Box::new(Literal(Value::Int(2))), - } - .into(), - )), + init: Some(Add { + left: Box::new(Literal(Value::Int(3))), + right: Box::new(Literal(Value::Int(2))), + }), } .into(), If { - cond: Box::new( - Eq { - left: Box::new(Iden("a".to_owned()).into()), - right: Box::new(Literal(Value::Int(5)).into()), - } - .into(), - ), + cond: Eq { + left: Box::new(Iden("a".to_owned()).into()), + right: Box::new(Literal(Value::Int(5)).into()), + }, body: vec![Break.into()], } .into(), @@ -290,7 +295,7 @@ mod tests { let expected: &[Item] = &[ VariableDeclaration { iden: Iden("script".to_owned()), - init: Some(Box::new(Literal(Value::Nul).into())), + init: Some(Literal(Value::Nul)), } .into(), Print(Iden("script".to_owned()).into()).into(), diff --git a/src/parser/ops.rs b/src/parser/ops.rs index 84970765..42c01a9e 100644 --- a/src/parser/ops.rs +++ b/src/parser/ops.rs @@ -20,35 +20,79 @@ macro_rules! gen_infix { impl<'a> Parser<'a> { pub(super) fn parse_ops(&mut self, token: Token) -> ParseResult { - if matches!(self.lexer.peek(), Some(Token::LeftParenthesis)) { - return self.fn_call(token); + 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 { - 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::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::Assignment) => return self.set_variable(buf), + let peek = self.lexer.peek().clone(); + buf = match peek { Some(Token::Print) => { self.lexer.next(); self.require(Token::Semicolon)?; return Ok(Stmt::Print(buf).into()); } - _ => return Ok(buf.into()), + None => return Ok(buf.into()), + _ => 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(); + 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; @@ -63,22 +107,8 @@ impl<'a> Parser<'a> { logor => Or; } - fn set_variable(&mut self, iden: Expr) -> ParseResult { - self.lexer.next(); - if let Expr::Identifier(iden) = iden { - let next = self.lexer.next(); - let value = self.parse_expr(next)?; - self.require(Token::Semicolon)?; - Ok(Stmt::VarAssignment { iden, value }.into()) - } else { - Err(Error { - kind: ErrorKind::InvalidIdentifier, - position: self.lexer.span(), - }) - } - } /// Ensure that input token is an expression - fn parse_expr(&mut self, token: Option) -> ExprResult { + pub(super) fn parse_expr(&mut self, token: Option) -> ExprResult { let token = token.ok_or(Error { kind: ErrorKind::EndOfTokenStream, position: self.lexer.span(), @@ -109,7 +139,7 @@ impl<'a> Parser<'a> { } /// Parse parenthesieted expression - fn parse_paren(&mut self) -> ExprResult { + pub(super) fn parse_paren(&mut self) -> ExprResult { let next = self.lexer.next(); let mut buf = self.parse_expr(next)?; loop { @@ -119,23 +149,14 @@ impl<'a> Parser<'a> { })?; 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); } - _ => return Ok(buf), + None => return Ok(buf.into()), + Some(t) => { + self.parse_operation(Some(t), buf)? + } }; } }