diff --git a/src/lexer.rs b/src/lexer.rs index 8474e8c..dae92c2 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 2e22968..18b721c 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 { @@ -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 1fbeb68..f6acf6d 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 @@ -98,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, }), } @@ -110,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 { @@ -134,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 { @@ -144,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()?; @@ -191,19 +213,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, body }.into()) } /// Parse loop @@ -256,23 +271,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(), @@ -289,7 +298,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 a8104ca..e64506f 100644 --- a/src/parser/ops.rs +++ b/src/parser/ops.rs @@ -20,34 +20,87 @@ 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); + // 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 { - 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)?, + 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()); } - _ => return Ok(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; @@ -94,33 +147,18 @@ 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 { - let next = self.lexer.peek().clone().ok_or(Error { - kind: ErrorKind::EndOfTokenStream, - position: self.lexer.span(), - })?; - - 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(), - }) - } + let peek = self.lexer.peek().clone(); + buf = match peek { Some(Token::RightParenthesis) => { self.lexer.next(); return Ok(buf); } - _ => return Ok(buf), + None => return Ok(buf), + Some(t) => self.parse_operation(Some(t), buf)?, }; } }