aboutsummaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/ast/expression.rs15
-rw-r--r--src/parse/ast/mod.rs2
-rw-r--r--src/parse/ast/nodes.rs6
-rw-r--r--src/parse/ast/statement.rs13
-rw-r--r--src/parse/parser.rs204
5 files changed, 157 insertions, 83 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.");
+ 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."))
+ }
+ }
+
+ fn group(&mut self) -> Result<Expression> {
+ consume!(self, GroupOpen)?;
+ let expression = self.expression()?;
+ consume!(self, GroupClose)?;
+ Ok(expression)
+ }
+
+ fn function(&mut self) -> Result<FnNode> {
+ 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 header = {
- let has_self_receiver = if let KeywordSelf = token.variant {
- consume_if!(self, Comma);
- true
- } else {
- false
- };
+ let type_constraint = if consume_if!(self, Colon).is_some() {
+ Some(inner!(consume!(self, Ident(_))?, Ident))
+ } else {
+ None
+ };
- let mut parameters = Vec::new();
- while let Some(token) = consume_if!(self, Ident(_)) {
- let parameter_name = inner!(token, Ident);
+ parameters.push(TypedIdentifier {
+ identifier: parameter_name,
+ type_constraint,
+ });
- let type_constraint = if consume_if!(self, Colon).is_some() {
- Some(inner!(consume!(self, Ident(_))?, Ident))
- } else {
- None
- };
+ if consume_if!(self, Comma).is_none() {
+ break;
+ }
+ }
- parameters.push(TypedIdentifier {
- identifier: parameter_name,
- type_constraint,
- });
+ let return_type = if consume_if!(self, Arrow).is_some() {
+ Some(inner!(consume!(self, Ident(_))?, Ident))
+ } else {
+ None
+ };
- if consume_if!(self, Comma).is_none() {
- break;
- }
- }
+ FnHeader {
+ has_self_receiver,
+ parameters,
+ return_type,
+ }
+ };
- let return_type = if consume_if!(self, Arrow).is_some() {
- Some(inner!(consume!(self, Ident(_))?, Ident))
- } else {
- None
- };
+ let body = self.generic_block()?;
- FnHeader {
- has_self_receiver,
- parameters,
- return_type,
- }
- };
+ Ok(FnNode { header, body })
+ }
- let body = self.block()?;
+ fn conditional(&mut self) -> Result<IfNode> {
+ consume!(self, KeywordIf)?;
- Ok(Expression::Fn(Box::new(FnNode { header, body })))
- }
- KeywordIf => {
- consume!(self, KeywordIf)?;
+ let mut conditionals = Vec::new();
- let mut conditionals = Vec::new();
+ let if_condition = self.expression()?;
+ let if_block = self.generic_block()?;
- let if_condition = self.expression()?;
- let if_block = self.block()?;
+ conditionals.push(ConditionalBlock {
+ condition: if_condition,
+ block: if_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()?;
- // Elifs
- while consume_if!(self, KeywordElif).is_some() {
- let elif_condition = self.expression()?;
- let elif_block = self.block()?;
+ conditionals.push(ConditionalBlock {
+ condition: elif_condition,
+ block: elif_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
+ };
- let else_block = if consume_if!(self, KeywordElse).is_some() {
- Some(self.block()?)
- } else {
- None
- };
+ Ok(IfNode {
+ conditionals,
+ else_block,
+ })
+ }
- Ok(Expression::If(Box::new(IfNode {
- conditionals,
- else_block,
- })))
- }
- _ => Err(anyhow!("Unexpected token: {:?}", token.variant)),
- }
+ 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 {
- Err(anyhow!("Expected expression."))
- }
+ 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 => {