From c0ecf5f2a3572a3529738deed339429d9d4138c7 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 3 May 2021 09:54:27 +0200 Subject: [PATCH 1/4] Variable assignment implemented --- src/parser/item.rs | 5 +++++ src/parser/mod.rs | 1 + src/parser/ops.rs | 17 ++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/parser/item.rs b/src/parser/item.rs index 2e229680..c6b7caf0 100644 --- a/src/parser/item.rs +++ b/src/parser/item.rs @@ -75,6 +75,11 @@ pub enum Stmt { Loop { body: Vec, }, + + VarAssignment { + iden: Iden, + value: Expr, + }, Break, HopBack, Print(Expr), diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1fbeb680..5e8aa298 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -69,6 +69,7 @@ impl<'a> Parser<'a> { | Token::String(_) | Token::Nul | Token::LeftParenthesis + | Token::Assignment | Token::LogNot => self.parse_ops(token), // Control flow diff --git a/src/parser/ops.rs b/src/parser/ops.rs index a8104ca6..84970765 100644 --- a/src/parser/ops.rs +++ b/src/parser/ops.rs @@ -38,6 +38,7 @@ impl<'a> Parser<'a> { 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), Some(Token::Print) => { self.lexer.next(); self.require(Token::Semicolon)?; @@ -62,8 +63,22 @@ 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 - pub(super) fn parse_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(), From 7057c3cfef6798f1922ec08d4d4e173128c6d477 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 3 May 2021 21:35:43 +0200 Subject: [PATCH 2/4] 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)? + } }; } } From 5bdbc2bbb002759eb99d6604a2593cfc38bd65b9 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 3 May 2021 21:36:32 +0200 Subject: [PATCH 3/4] Obeyed our paperclip overlord + fmt --- src/parser/mod.rs | 2 +- src/parser/ops.rs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 609e830c..7692d13a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -215,7 +215,7 @@ impl<'a> Parser<'a> { let body = self.parse_body()?; - Ok(Stmt::If { cond: cond, body }.into()) + Ok(Stmt::If { cond, body }.into()) } /// Parse loop diff --git a/src/parser/ops.rs b/src/parser/ops.rs index 42c01a9e..bfd0053c 100644 --- a/src/parser/ops.rs +++ b/src/parser/ops.rs @@ -153,10 +153,8 @@ impl<'a> Parser<'a> { self.lexer.next(); return Ok(buf); } - None => return Ok(buf.into()), - Some(t) => { - self.parse_operation(Some(t), buf)? - } + None => return Ok(buf), + Some(t) => self.parse_operation(Some(t), buf)?, }; } } From 16182629483198ab9726d63e9ae7387871130e68 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 3 May 2021 23:02:19 +0200 Subject: [PATCH 4/4] Tidy up --- src/parser/mod.rs | 5 ++++- src/parser/ops.rs | 16 ++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 7692d13a..f6acf6de 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -99,7 +99,7 @@ impl<'a> Parser<'a> { } _ => Err(Error { - kind: ErrorKind::SyntaxError("Unexpected identifier".to_owned()), + kind: ErrorKind::SyntaxError("Unexpected token".to_owned()), position: start..self.lexer.span().end, }), } @@ -153,6 +153,7 @@ impl<'a> Parser<'a> { /// `functio [iden] ([expr], [expr]) { ... } fn function_declaration(&mut self) -> ParseResult { let iden = self.require_iden()?; + self.require(Token::LeftParenthesis)?; let mut args = vec![]; loop { @@ -163,7 +164,9 @@ impl<'a> Parser<'a> { _ => 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 bfd0053c..e64506f7 100644 --- a/src/parser/ops.rs +++ b/src/parser/ops.rs @@ -20,6 +20,7 @@ macro_rules! gen_infix { 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), @@ -31,12 +32,15 @@ impl<'a> Parser<'a> { 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)?, } } @@ -65,6 +69,8 @@ impl<'a> Parser<'a> { fn parse_assignment(&mut self, token: Token) -> ParseResult { self.lexer.next(); + + // Extract identifier let iden = if let Token::Identifier(i) = token { Iden(i) } else { @@ -76,6 +82,7 @@ impl<'a> Parser<'a> { let next = self.lexer.next(); let mut value = self.parse_expr(next)?; + loop { let peek = self.lexer.peek().clone(); value = match peek { @@ -89,6 +96,7 @@ impl<'a> Parser<'a> { Some(t) => self.parse_operation(Some(t), value)?, }; } + self.lexer.next(); Ok(Stmt::VarAssignment { iden, value }.into()) @@ -143,12 +151,8 @@ impl<'a> Parser<'a> { 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(), - })?; - - buf = match Some(next) { + let peek = self.lexer.peek().clone(); + buf = match peek { Some(Token::RightParenthesis) => { self.lexer.next(); return Ok(buf);