Skip to content

Commit

Permalink
move some expression parsing into standalone functions
Browse files Browse the repository at this point in the history
  • Loading branch information
andogq committed Aug 23, 2024
1 parent 9ca5e9b commit 0454488
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 112 deletions.
10 changes: 5 additions & 5 deletions src/stage/parse/block.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

pub fn parse_block(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<Block, ParseError> {
let span_start = match tokens.next_spanned().unwrap() {
pub fn parse_block(compiler: &mut Compiler, lexer: &mut Lexer<'_>) -> Result<Block, ParseError> {
let span_start = match lexer.next_spanned().unwrap() {
(Token::LeftBrace, span) => span.start,
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand All @@ -12,14 +12,14 @@ pub fn parse_block(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<Bl
}
};

let statements = std::iter::from_fn(|| match tokens.peek_token().unwrap() {
let statements = std::iter::from_fn(|| match lexer.peek_token().unwrap() {
Token::RightBrace => None,
_ => Some(parse_statement(compiler, tokens)),
_ => Some(parse_statement(compiler, lexer)),
})
.collect::<Result<Vec<_>, _>>()?;

// Consume the right brace that just stopped us
let span_end = match tokens.next_spanned().unwrap() {
let span_end = match lexer.next_spanned().unwrap() {
(Token::RightBrace, span) => span.end,
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand Down
16 changes: 8 additions & 8 deletions src/stage/parse/expression/e_assign.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub use super::*;

pub fn parse_assign(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<Assign, ParseError> {
let (binding, span_start) = match tokens.next_spanned().unwrap() {
pub fn parse_assign(compiler: &mut Compiler, lexer: &mut Lexer<'_>) -> Result<Assign, ParseError> {
let (binding, span_start) = match lexer.next_spanned().unwrap() {
(Token::Ident(ident), span) => (ident, span),
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand All @@ -14,7 +14,7 @@ pub fn parse_assign(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<A

let binding = compiler.symbols.get_or_intern(binding);

match tokens.next_token().unwrap() {
match lexer.next_token().unwrap() {
Token::Eq => (),
token => {
return Err(ParseError::ExpectedToken {
Expand All @@ -25,7 +25,7 @@ pub fn parse_assign(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<A
}
}

let value = parse_expression(compiler, tokens, Precedence::Lowest)?;
let value = parse_expression(compiler, lexer, Precedence::Lowest)?;

Ok(Assign {
span: span_start.start..value.span().end,
Expand All @@ -37,9 +37,9 @@ pub fn parse_assign(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<A

pub fn parse_op_assign(
compiler: &mut Compiler,
tokens: &mut Lexer<'_>,
lexer: &mut Lexer<'_>,
) -> Result<Assign, ParseError> {
let (binding, binding_span) = match tokens.next_spanned().unwrap() {
let (binding, binding_span) = match lexer.next_spanned().unwrap() {
(Token::Ident(ident), span) => (ident, span),
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand All @@ -52,7 +52,7 @@ pub fn parse_op_assign(

let binding = compiler.symbols.get_or_intern(binding);

let operation = match tokens.next_token().unwrap() {
let operation = match lexer.next_token().unwrap() {
Token::AddAssign => InfixOperation::Plus,
Token::MinusAssign => InfixOperation::Minus,
Token::MulAssign => InfixOperation::Multiply,
Expand All @@ -62,7 +62,7 @@ pub fn parse_op_assign(
}
};

let right = parse_expression(compiler, tokens, Precedence::Lowest)?;
let right = parse_expression(compiler, lexer, Precedence::Lowest)?;

Ok(Assign {
span: binding_span.start..right.span().end,
Expand Down
4 changes: 2 additions & 2 deletions src/stage/parse/expression/e_boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use super::*;

pub fn parse_boolean(
_compiler: &mut Compiler,
tokens: &mut Lexer<'_>,
lexer: &mut Lexer<'_>,
) -> Result<Boolean, ParseError> {
match tokens.next_spanned().unwrap() {
match lexer.next_spanned().unwrap() {
(Token::True, span) => Ok(Boolean::new(true, span, Default::default())),
(Token::False, span) => Ok(Boolean::new(false, span, Default::default())),
(token, _) => {
Expand Down
4 changes: 2 additions & 2 deletions src/stage/parse/expression/e_ident.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

pub fn parse_ident(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<Ident, ParseError> {
match tokens.next_spanned().unwrap() {
pub fn parse_ident(compiler: &mut Compiler, lexer: &mut Lexer<'_>) -> Result<Ident, ParseError> {
match lexer.next_spanned().unwrap() {
(Token::Ident(ident), span) => Ok(Ident::new(
compiler.symbols.get_or_intern(ident),
span,
Expand Down
14 changes: 7 additions & 7 deletions src/stage/parse/expression/e_if.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

pub fn parse_if(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<If, ParseError> {
let span_start = match tokens.next_spanned().unwrap() {
pub fn parse_if(compiler: &mut Compiler, lexer: &mut Lexer<'_>) -> Result<If, ParseError> {
let span_start = match lexer.next_spanned().unwrap() {
(Token::If, span) => span.start,
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand All @@ -12,14 +12,14 @@ pub fn parse_if(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<If, P
}
};

let condition = parse_expression(compiler, tokens, Precedence::Lowest)?;
let condition = parse_expression(compiler, lexer, Precedence::Lowest)?;

let success = parse_block(compiler, tokens)?;
let success = parse_block(compiler, lexer)?;

let otherwise = if matches!(tokens.peek_token(), Some(Token::Else)) {
tokens.next_token().unwrap();
let otherwise = if matches!(lexer.peek_token(), Some(Token::Else)) {
lexer.next_token().unwrap();

let otherwise = parse_block(compiler, tokens)?;
let otherwise = parse_block(compiler, lexer)?;

Some(otherwise)
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/stage/parse/expression/e_integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use super::*;

pub fn parse_integer(
_compiler: &mut Compiler,
tokens: &mut Lexer<'_>,
lexer: &mut Lexer<'_>,
) -> Result<Integer, ParseError> {
match tokens.next_spanned().unwrap() {
match lexer.next_spanned().unwrap() {
(Token::Integer(value), span) => Ok(Integer::new(value, span, Default::default())),
(token, _) => Err(ParseError::ExpectedToken {
expected: Box::new(Token::Integer(0)),
Expand Down
6 changes: 3 additions & 3 deletions src/stage/parse/expression/e_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::{

use super::{Compiler, Lexer, ParseError};

pub fn parse_loop(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<Loop, ParseError> {
let span_start = match tokens.next_spanned().unwrap() {
pub fn parse_loop(compiler: &mut Compiler, lexer: &mut Lexer<'_>) -> Result<Loop, ParseError> {
let span_start = match lexer.next_spanned().unwrap() {
(Token::Loop, span) => span.start,
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand All @@ -17,7 +17,7 @@ pub fn parse_loop(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<Loo
}
};

let body = parse_block(compiler, tokens)?;
let body = parse_block(compiler, lexer)?;

Ok(Loop {
span: span_start..body.span.end,
Expand Down
187 changes: 104 additions & 83 deletions src/stage/parse/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,108 +44,129 @@ impl Precedence {
}
}

fn parse_prefix(compiler: &mut Compiler, tokens: &mut Lexer<'_>) -> Result<Expression, ParseError> {
match tokens.peek_token().unwrap().clone() {
Token::Integer(_) => Ok(Expression::Integer(parse_integer(compiler, tokens)?)),
Token::Ident(_) => match tokens.double_peek_token() {
Some(Token::Eq) => Ok(Expression::Assign(parse_assign(compiler, tokens)?)),
fn parse_prefix(compiler: &mut Compiler, lexer: &mut Lexer<'_>) -> Result<Expression, ParseError> {
match lexer.peek_token().unwrap().clone() {
Token::Integer(_) => Ok(Expression::Integer(parse_integer(compiler, lexer)?)),
Token::Ident(_) => match lexer.double_peek_token() {
Some(Token::Eq) => Ok(Expression::Assign(parse_assign(compiler, lexer)?)),
Some(Token::AddAssign | Token::MinusAssign) => {
Ok(Expression::Assign(parse_op_assign(compiler, tokens)?))
Ok(Expression::Assign(parse_op_assign(compiler, lexer)?))
}
_ => Ok(Expression::Ident(parse_ident(compiler, tokens)?)),
_ => Ok(Expression::Ident(parse_ident(compiler, lexer)?)),
},
Token::True => Ok(Expression::Boolean(parse_boolean(compiler, tokens)?)),
Token::False => Ok(Expression::Boolean(parse_boolean(compiler, tokens)?)),
Token::LeftBrace => Ok(Expression::Block(parse_block(compiler, tokens)?)),
Token::LeftParen => parse_grouped(compiler, tokens),
Token::If => Ok(Expression::If(parse_if(compiler, tokens)?)),
Token::Loop => Ok(Expression::Loop(parse_loop(compiler, tokens)?)),
Token::True => Ok(Expression::Boolean(parse_boolean(compiler, lexer)?)),
Token::False => Ok(Expression::Boolean(parse_boolean(compiler, lexer)?)),
Token::LeftBrace => Ok(Expression::Block(parse_block(compiler, lexer)?)),
Token::LeftParen => parse_grouped(compiler, lexer),
Token::If => Ok(Expression::If(parse_if(compiler, lexer)?)),
Token::Loop => Ok(Expression::Loop(parse_loop(compiler, lexer)?)),
token => Err(ParseError::UnexpectedToken(token.clone())),
}
}

pub fn parse_expression(
compiler: &mut Compiler,
tokens: &mut Lexer<'_>,
lexer: &mut Lexer<'_>,
precedence: Precedence,
) -> Result<Expression, ParseError> {
let mut left = parse_prefix(compiler, tokens)?;
let mut left = parse_prefix(compiler, lexer)?;

while tokens.peek_token().is_some() && precedence < Precedence::of(tokens.peek_token().unwrap())
{
left = match (left, tokens.peek_token().unwrap()) {
while lexer.peek_token().is_some() && precedence < Precedence::of(lexer.peek_token().unwrap()) {
left = match (left, lexer.peek_token().unwrap()) {
// Function call
(Expression::Ident(name), Token::LeftParen) => {
// Consume the args
let args = iter::from_fn(|| {
match tokens.peek_token().unwrap() {
Token::RightParen => None,
Token::LeftParen | Token::Comma => {
// Consume the opening paren or comma
tokens.next_token();

// If the closing parenthesis is encountered, stop parsing arguments
if matches!(tokens.peek_token().unwrap(), Token::RightParen) {
return None;
}

// Parse the next argument
Some(parse_expression(compiler, tokens, Precedence::Lowest))
}
token => Some(Err(ParseError::ExpectedToken {
expected: Box::new(Token::Comma),
found: Box::new(token.clone()),
reason: "function arguments must be separated by a comma".to_string(),
})),
}
})
.collect::<Result<Vec<_>, _>>()?;

// Consume the closing paren
let end_span = match tokens.next_spanned().unwrap() {
(Token::RightParen, span) => span,
(token, _) => {
return Err(ParseError::ExpectedToken {
expected: Box::new(Token::RightParen),
found: Box::new(token),
reason: "argument list must end with right paren".to_string(),
})
}
};

let span = name.span.start..end_span.end;
Expression::Call(Call::new(name.binding, args, span, Default::default()))
(Expression::Ident(ident), Token::LeftParen) => {
parse_function_call(compiler, lexer, ident)?
}

// Regular infix operation
(left, token) => {
if let Ok(operation) = InfixOperation::try_from(token.clone()) {
let token = tokens.next_token().unwrap();
let precedence = Precedence::of(&token);

let right = parse_expression(compiler, tokens, precedence)?;

let span = left.span().start..right.span().end;

Expression::Infix(Infix::new(
Box::new(left),
operation,
Box::new(right),
span,
Default::default(),
))
} else {
// Probably aren't in the expression any more
return Ok(left);
}
}
(left, _) => parse_infix(compiler, lexer, left)?,
};
}

Ok(left)
}

fn parse_grouped(compiler: &mut Compiler, tokens: &mut Lexer) -> Result<Expression, ParseError> {
let span_start = match tokens.next_spanned().unwrap() {
fn parse_function_call(
compiler: &mut Compiler,
lexer: &mut Lexer,
ident: Ident,
) -> Result<Expression, ParseError> {
// Consume the args
let args = iter::from_fn(|| {
match lexer.peek_token().unwrap() {
Token::RightParen => None,
Token::LeftParen | Token::Comma => {
// Consume the opening paren or comma
lexer.next_token();

// If the closing parenthesis is encountered, stop parsing arguments
if matches!(lexer.peek_token().unwrap(), Token::RightParen) {
return None;
}

// Parse the next argument
Some(parse_expression(compiler, lexer, Precedence::Lowest))
}
token => Some(Err(ParseError::ExpectedToken {
expected: Box::new(Token::Comma),
found: Box::new(token.clone()),
reason: "function arguments must be separated by a comma".to_string(),
})),
}
})
.collect::<Result<Vec<_>, _>>()?;

// Consume the closing paren
let end_span = match lexer.next_spanned().unwrap() {
(Token::RightParen, span) => span,
(token, _) => {
return Err(ParseError::ExpectedToken {
expected: Box::new(Token::RightParen),
found: Box::new(token),
reason: "argument list must end with right paren".to_string(),
})
}
};

let span = ident.span.start..end_span.end;
Ok(Expression::Call(Call::new(
ident.binding,
args,
span,
Default::default(),
)))
}

fn parse_infix(
compiler: &mut Compiler,
lexer: &mut Lexer,
left: Expression,
) -> Result<Expression, ParseError> {
let token = lexer.next_token().unwrap();

Ok(
if let Ok(operation) = InfixOperation::try_from(token.clone()) {
let precedence = Precedence::of(&token);

let right = parse_expression(compiler, lexer, precedence)?;

let span = left.span().start..right.span().end;

Expression::Infix(Infix::new(
Box::new(left),
operation,
Box::new(right),
span,
Default::default(),
))
} else {
left
},
)
}

fn parse_grouped(compiler: &mut Compiler, lexer: &mut Lexer) -> Result<Expression, ParseError> {
let span_start = match lexer.next_spanned().unwrap() {
(Token::LeftParen, span) => span.start,
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand All @@ -156,9 +177,9 @@ fn parse_grouped(compiler: &mut Compiler, tokens: &mut Lexer) -> Result<Expressi
}
};

let e = parse_expression(compiler, tokens, Precedence::Lowest)?;
let e = parse_expression(compiler, lexer, Precedence::Lowest)?;

let span_end = match tokens.next_spanned().unwrap() {
let span_end = match lexer.next_spanned().unwrap() {
(Token::RightParen, span) => span.end,
(token, _) => {
return Err(ParseError::ExpectedToken {
Expand Down

0 comments on commit 0454488

Please sign in to comment.