diff options
Diffstat (limited to 'src/parse')
| -rw-r--r-- | src/parse/ast/expression.rs | 15 | ||||
| -rw-r--r-- | src/parse/ast/mod.rs | 2 | ||||
| -rw-r--r-- | src/parse/ast/nodes.rs | 6 | ||||
| -rw-r--r-- | src/parse/ast/statement.rs | 13 | ||||
| -rw-r--r-- | src/parse/parser.rs | 218 |
5 files changed, 164 insertions, 90 deletions
diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs index 1749c40..c7f6d9b 100644 --- a/src/parse/ast/expression.rs +++ b/src/parse/ast/expression.rs @@ -1,6 +1,8 @@ use std::fmt::{self, Display, Formatter}; -use super::nodes::{BinaryOperator, BlockNode, FnNode, Identifier, IfNode, Literal, UnaryOperator}; +use super::nodes::{ + BinaryOperator, BlockNode, FnNode, Identifier, IfNode, Literal, LoopNode, UnaryOperator, +}; #[derive(Debug, Clone)] pub enum Expression { @@ -17,6 +19,7 @@ pub enum Expression { Block(Box<BlockNode>), Fn(Box<FnNode>), If(Box<IfNode>), + Loop(Box<LoopNode>), Literal(Literal), Identifier(Identifier), } @@ -97,6 +100,16 @@ impl Expression { Self::block_fmt(f, e, depth + 1)?; } } + Expression::Loop(node) => { + writeln!(f, "{}Loop:", pad)?; + if let Some(loop_condition) = &node.condition { + writeln!(f, "{}- Condition:", pad)?; + loop_condition.nested_fmt(f, depth + 1)?; + } + + writeln!(f, "{}- Body:", pad)?; + Self::block_fmt(f, &node.body, depth + 1)?; + } } Ok(()) diff --git a/src/parse/ast/mod.rs b/src/parse/ast/mod.rs index 93944b2..7d0b58b 100644 --- a/src/parse/ast/mod.rs +++ b/src/parse/ast/mod.rs @@ -3,8 +3,8 @@ use std::fmt::Display; use self::statement::Statement; pub mod expression; -pub mod statement; pub mod nodes; +pub mod statement; #[derive(Debug)] pub struct Program { diff --git a/src/parse/ast/nodes.rs b/src/parse/ast/nodes.rs index 822ffb6..2a4f7c0 100644 --- a/src/parse/ast/nodes.rs +++ b/src/parse/ast/nodes.rs @@ -107,6 +107,12 @@ pub struct IfNode { } #[derive(Debug, Clone)] +pub struct LoopNode { + pub condition: Option<Expression>, + pub body: BlockNode, +} + +#[derive(Debug, Clone)] pub struct BlockNode { pub statements: Vec<Statement>, pub tail_expression: Option<Expression>, diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs index b0e626d..99ee0e0 100644 --- a/src/parse/ast/statement.rs +++ b/src/parse/ast/statement.rs @@ -6,6 +6,8 @@ use super::expression::Expression; pub enum Statement { Expression(Expression), Print(Expression), + Break(Option<Expression>), + Continue, Return(Expression), } @@ -32,6 +34,17 @@ impl Statement { writeln!(f, "{}Return:", pad)?; expression.nested_fmt(f, depth + 1)?; } + Statement::Break(expression) => { + if let Some(returned_on_break) = expression { + writeln!(f, "{}Break:", pad)?; + returned_on_break.nested_fmt(f, depth + 1)?; + } else { + writeln!(f, "{}Break", pad)?; + } + } + Statement::Continue => { + writeln!(f, "{}Continue", pad)?; + } } Ok(()) 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 => { |
