about summary refs log tree commit diff
path: root/src/parse/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse/parser.rs')
-rw-r--r--src/parse/parser.rs218
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 => {