diff options
| author | Mel <einebeere@gmail.com> | 2021-10-23 22:01:52 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2021-10-23 22:01:52 +0200 |
| commit | 8a6eb35a900081967db16d313ab7ed470de6570f (patch) | |
| tree | d58dd702d8a742c7554545bc4e291480649e3663 /src/parse/parser.rs | |
| parent | da14afd74e1659af6ce4553360ac5dd0ce933db8 (diff) | |
| download | rabbithole-8a6eb35a900081967db16d313ab7ed470de6570f.tar.zst rabbithole-8a6eb35a900081967db16d313ab7ed470de6570f.zip | |
Loop expressions and concrete walker errors.
Diffstat (limited to 'src/parse/parser.rs')
| -rw-r--r-- | src/parse/parser.rs | 218 |
1 files changed, 130 insertions, 88 deletions
diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 9b72597..4a84101 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,4 +1,5 @@ use super::ast::expression::Expression; +use super::ast::nodes::LoopNode; use super::ast::nodes::UnaryOperator; use super::ast::statement::Statement; use super::ast::Program; @@ -46,6 +47,8 @@ impl<T: Iterator<Item = Token>> Parser<T> { match token.variant { KeywordPrint => self.print_statement(), KeywordReturn => self.return_statement(), + KeywordBreak => self.break_statement(), + KeywordContinue => self.continue_statement(), _ => self.expression_statement(), } } @@ -57,6 +60,24 @@ impl<T: Iterator<Item = Token>> Parser<T> { Ok(Statement::Return(expression)) } + fn break_statement(&mut self) -> Result<Statement> { + consume!(self, KeywordBreak)?; + let returned_on_break = if consume_if!(self, SemiColon).is_none() { + let expression = self.expression()?; + consume!(self, SemiColon)?; + Some(expression) + } else { + None + }; + Ok(Statement::Break(returned_on_break)) + } + + fn continue_statement(&mut self) -> Result<Statement> { + consume!(self, KeywordContinue)?; + consume!(self, SemiColon)?; + Ok(Statement::Continue) + } + fn print_statement(&mut self) -> Result<Statement> { consume!(self, KeywordPrint)?; let expression = self.expression()?; @@ -179,105 +200,126 @@ impl<T: Iterator<Item = Token>> Parser<T> { self.tokens.next().unwrap(), Ident ))), - GroupOpen => { - consume!(self, GroupOpen)?; - let expression = self.expression()?; - consume!(self, GroupClose)?; - Ok(Expression::Group(Box::new(expression))) - } - BlockOpen => Ok(Expression::Block(Box::new(self.block()?))), - KeywordFn => { - consume!(self, KeywordFn)?; - let token = self.tokens.next().expect("Expected function header."); - - let header = { - let has_self_receiver = if let KeywordSelf = token.variant { - consume_if!(self, Comma); - true - } else { - false - }; - - let mut parameters = Vec::new(); - while let Some(token) = consume_if!(self, Ident(_)) { - let parameter_name = inner!(token, Ident); - - let type_constraint = if consume_if!(self, Colon).is_some() { - Some(inner!(consume!(self, Ident(_))?, Ident)) - } else { - None - }; - - parameters.push(TypedIdentifier { - identifier: parameter_name, - type_constraint, - }); - - if consume_if!(self, Comma).is_none() { - break; - } - } - - let return_type = if consume_if!(self, Arrow).is_some() { - Some(inner!(consume!(self, Ident(_))?, Ident)) - } else { - None - }; - - FnHeader { - has_self_receiver, - parameters, - return_type, - } - }; - - let body = self.block()?; - - Ok(Expression::Fn(Box::new(FnNode { header, body }))) - } - KeywordIf => { - consume!(self, KeywordIf)?; + GroupOpen => Ok(Expression::Group(Box::new(self.group()?))), + BlockOpen => Ok(Expression::Block(Box::new(self.generic_block()?))), + KeywordFn => Ok(Expression::Fn(Box::new(self.function()?))), + KeywordIf => Ok(Expression::If(Box::new(self.conditional()?))), + KeywordLoop => Ok(Expression::Loop(Box::new(self.repeating()?))), + _ => Err(anyhow!("Unexpected token: {:?}", token.variant)), + } + } else { + Err(anyhow!("Expected expression.")) + } + } - let mut conditionals = Vec::new(); + fn group(&mut self) -> Result<Expression> { + consume!(self, GroupOpen)?; + let expression = self.expression()?; + consume!(self, GroupClose)?; + Ok(expression) + } - let if_condition = self.expression()?; - let if_block = self.block()?; + fn function(&mut self) -> Result<FnNode> { + consume!(self, KeywordFn)?; + let token = self.tokens.next().expect("Expected function header."); - conditionals.push(ConditionalBlock { - condition: if_condition, - block: if_block, - }); + let header = { + let has_self_receiver = if let KeywordSelf = token.variant { + consume_if!(self, Comma); + true + } else { + false + }; - // Elifs - while consume_if!(self, KeywordElif).is_some() { - let elif_condition = self.expression()?; - let elif_block = self.block()?; + let mut parameters = Vec::new(); + while let Some(token) = consume_if!(self, Ident(_)) { + let parameter_name = inner!(token, Ident); - conditionals.push(ConditionalBlock { - condition: elif_condition, - block: elif_block, - }); - } + let type_constraint = if consume_if!(self, Colon).is_some() { + Some(inner!(consume!(self, Ident(_))?, Ident)) + } else { + None + }; - let else_block = if consume_if!(self, KeywordElse).is_some() { - Some(self.block()?) - } else { - None - }; + parameters.push(TypedIdentifier { + identifier: parameter_name, + type_constraint, + }); - Ok(Expression::If(Box::new(IfNode { - conditionals, - else_block, - }))) + if consume_if!(self, Comma).is_none() { + break; } - _ => Err(anyhow!("Unexpected token: {:?}", token.variant)), } - } else { - Err(anyhow!("Expected expression.")) + + let return_type = if consume_if!(self, Arrow).is_some() { + Some(inner!(consume!(self, Ident(_))?, Ident)) + } else { + None + }; + + FnHeader { + has_self_receiver, + parameters, + return_type, + } + }; + + let body = self.generic_block()?; + + Ok(FnNode { header, body }) + } + + fn conditional(&mut self) -> Result<IfNode> { + consume!(self, KeywordIf)?; + + let mut conditionals = Vec::new(); + + let if_condition = self.expression()?; + let if_block = self.generic_block()?; + + conditionals.push(ConditionalBlock { + condition: if_condition, + block: if_block, + }); + + // Elifs + while consume_if!(self, KeywordElif).is_some() { + let elif_condition = self.expression()?; + let elif_block = self.generic_block()?; + + conditionals.push(ConditionalBlock { + condition: elif_condition, + block: elif_block, + }); } + + let else_block = if consume_if!(self, KeywordElse).is_some() { + Some(self.generic_block()?) + } else { + None + }; + + Ok(IfNode { + conditionals, + else_block, + }) + } + + fn repeating(&mut self) -> Result<LoopNode> { + consume!(self, KeywordLoop)?; + + let condition = if consume_if!(self, KeywordIf).is_some() { + let expression = self.expression()?; + Some(expression) + } else { + None + }; + + let body = self.generic_block()?; + Ok(LoopNode { body, condition }) } - fn block(&mut self) -> Result<BlockNode> { + fn generic_block(&mut self) -> Result<BlockNode> { consume!(self, BlockOpen)?; let mut statements = Vec::new(); @@ -286,7 +328,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { loop { let token = self.tokens.peek().expect("Unclosed block."); match token.variant { - KeywordReturn | KeywordPrint => { + KeywordReturn | KeywordPrint | KeywordContinue | KeywordBreak => { statements.push(self.statement()?); } BlockClose => { |
