1
0

Refactor parsing for better jumping and returns

This commit is contained in:
Jeff 2024-10-20 18:51:04 -04:00
parent 1da61f0873
commit 648bbdbc4d
2 changed files with 144 additions and 90 deletions

View File

@ -25,6 +25,7 @@ pub fn parse(source: &str) -> Result<Chunk, DustError> {
implicit_return: true, implicit_return: true,
}) })
.map_err(|error| DustError::Parse { error, source })?; .map_err(|error| DustError::Parse { error, source })?;
parser.commit_current_statement();
} }
Ok(parser.finish()) Ok(parser.finish())
@ -36,6 +37,7 @@ pub struct Parser<'src> {
chunk: Chunk, chunk: Chunk,
current_statement: Vec<(Instruction, Span)>, current_statement: Vec<(Instruction, Span)>,
current_is_expression: bool,
minimum_register: u8, minimum_register: u8,
current_token: Token<'src>, current_token: Token<'src>,
@ -61,6 +63,7 @@ impl<'src> Parser<'src> {
lexer, lexer,
chunk: Chunk::new(None), chunk: Chunk::new(None),
current_statement: Vec::new(), current_statement: Vec::new(),
current_is_expression: false,
minimum_register: 0, minimum_register: 0,
current_token, current_token,
current_position, current_position,
@ -145,7 +148,9 @@ impl<'src> Parser<'src> {
self.current_statement.push((instruction, position)); self.current_statement.push((instruction, position));
} }
fn commit_current_statement(&mut self) { fn commit_current_statement(&mut self) -> Result<(), ParseError> {
self.parse_implicit_return()?;
let next_register = self.next_register(); let next_register = self.next_register();
for (instruction, position) in self.current_statement.drain(..) { for (instruction, position) in self.current_statement.drain(..) {
@ -153,6 +158,9 @@ impl<'src> Parser<'src> {
} }
self.minimum_register = next_register; self.minimum_register = next_register;
self.current_is_expression = false;
Ok(())
} }
fn get_statement_operations<const COUNT: usize>(&self) -> Option<[(Operation, Span); COUNT]> { fn get_statement_operations<const COUNT: usize>(&self) -> Option<[(Operation, Span); COUNT]> {
@ -234,6 +242,8 @@ impl<'src> Parser<'src> {
position, position,
); );
self.current_is_expression = true;
Ok(()) Ok(())
} else { } else {
Err(ParseError::ExpectedToken { Err(ParseError::ExpectedToken {
@ -256,6 +266,8 @@ impl<'src> Parser<'src> {
self.emit_constant(value, position)?; self.emit_constant(value, position)?;
self.current_is_expression = true;
Ok(()) Ok(())
} else { } else {
Err(ParseError::ExpectedToken { Err(ParseError::ExpectedToken {
@ -276,6 +288,8 @@ impl<'src> Parser<'src> {
self.emit_constant(value, position)?; self.emit_constant(value, position)?;
self.current_is_expression = true;
Ok(()) Ok(())
} else { } else {
Err(ParseError::ExpectedToken { Err(ParseError::ExpectedToken {
@ -302,6 +316,8 @@ impl<'src> Parser<'src> {
self.emit_constant(value, position)?; self.emit_constant(value, position)?;
self.current_is_expression = true;
Ok(()) Ok(())
} else { } else {
Err(ParseError::ExpectedToken { Err(ParseError::ExpectedToken {
@ -328,6 +344,8 @@ impl<'src> Parser<'src> {
self.emit_constant(value, position)?; self.emit_constant(value, position)?;
self.current_is_expression = true;
Ok(()) Ok(())
} else { } else {
Err(ParseError::ExpectedToken { Err(ParseError::ExpectedToken {
@ -348,6 +366,8 @@ impl<'src> Parser<'src> {
self.emit_constant(value, position)?; self.emit_constant(value, position)?;
self.current_is_expression = true;
Ok(()) Ok(())
} else { } else {
Err(ParseError::ExpectedToken { Err(ParseError::ExpectedToken {
@ -363,6 +383,8 @@ impl<'src> Parser<'src> {
self.parse_expression()?; self.parse_expression()?;
self.expect(Token::RightParenthesis)?; self.expect(Token::RightParenthesis)?;
self.current_is_expression = true;
Ok(()) Ok(())
} }
@ -419,6 +441,8 @@ impl<'src> Parser<'src> {
self.emit_instruction(instruction, operator_position); self.emit_instruction(instruction, operator_position);
self.current_is_expression = true;
Ok(()) Ok(())
} }
@ -559,7 +583,9 @@ impl<'src> Parser<'src> {
| Token::SlashEqual | Token::SlashEqual
| Token::PercentEqual = operator | Token::PercentEqual = operator
{ {
self.commit_current_statement(); self.current_is_expression = false;
} else {
self.current_is_expression = true;
} }
Ok(()) Ok(())
@ -658,6 +684,8 @@ impl<'src> Parser<'src> {
operator_position, operator_position,
); );
self.current_is_expression = true;
Ok(()) Ok(())
} }
@ -695,6 +723,8 @@ impl<'src> Parser<'src> {
self.emit_instruction(Instruction::jump(jump_to), operator_position); self.emit_instruction(Instruction::jump(jump_to), operator_position);
self.parse_sub_expression(&rule.precedence)?; self.parse_sub_expression(&rule.precedence)?;
self.current_is_expression = true;
Ok(()) Ok(())
} }
@ -721,6 +751,8 @@ impl<'src> Parser<'src> {
start_position, start_position,
)?; )?;
self.current_is_expression = true;
return Ok(()); return Ok(());
} else { } else {
return Err(ParseError::UndeclaredVariable { return Err(ParseError::UndeclaredVariable {
@ -792,6 +824,8 @@ impl<'src> Parser<'src> {
Instruction::set_local(register, local_index), Instruction::set_local(register, local_index),
start_position, start_position,
); );
self.current_is_expression = false;
} else { } else {
let register = self.next_register(); let register = self.next_register();
@ -799,6 +833,8 @@ impl<'src> Parser<'src> {
Instruction::get_local(register, local_index), Instruction::get_local(register, local_index),
self.previous_position, self.previous_position,
); );
self.current_is_expression = true;
} }
Ok(()) Ok(())
@ -869,6 +905,8 @@ impl<'src> Parser<'src> {
Span(start, end), Span(start, end),
); );
self.current_is_expression = true;
Ok(()) Ok(())
} }
@ -892,33 +930,18 @@ impl<'src> Parser<'src> {
if let Token::LeftCurlyBrace = self.current_token { if let Token::LeftCurlyBrace = self.current_token {
self.parse_block(block_allowed)?; self.parse_block(block_allowed)?;
} else {
return Err(ParseError::ExpectedToken {
expected: TokenKind::LeftCurlyBrace,
found: self.current_token.to_owned(),
position: self.current_position,
});
} }
let if_end = self.chunk.len() + self.current_statement.len(); let if_block_end = self.current_statement.len();
if let Some(if_jump) = self.get_last_jump_mut() { if let Some(if_jump) = self.get_last_jump_mut() {
if_jump.set_b(if_end as u8); if_jump.set_b(if_block_end as u8);
}
let last_operation = self
.current_statement
.last()
.map(|(instruction, _)| instruction.operation());
if let (Some(Operation::LoadConstant) | Some(Operation::LoadBoolean), Token::Else) =
(last_operation, self.current_token)
{
let (mut load_constant, load_constant_position) = self
.current_statement
.pop()
.ok_or_else(|| ParseError::ExpectedExpression {
found: self.previous_token.to_owned(),
position: self.previous_position,
})?;
load_constant.set_c_to_boolean(true);
self.emit_instruction(load_constant, load_constant_position);
} }
if self.allow(Token::Else)? { if self.allow(Token::Else)? {
@ -928,23 +951,38 @@ impl<'src> Parser<'src> {
if let Token::LeftCurlyBrace = self.current_token { if let Token::LeftCurlyBrace = self.current_token {
self.parse_block(block_allowed)?; self.parse_block(block_allowed)?;
self.commit_current_statement();
let else_end = (self.chunk.len() + self.current_statement.len()) as u8; let else_end = self.current_statement.len();
if let Operation::LoadBoolean | Operation::LoadConstant = self if else_end - if_block_end > 1 {
.chunk self.current_statement.insert(
.get_instruction(if_end, self.current_position) if_block_end,
.map(|(instruction, _)| instruction.operation())? (
{ Instruction::jump((else_end + 1) as u8),
self.current_position,
),
);
} else { } else {
self.chunk.insert_instruction( self.current_statement
if_end, .iter_mut()
Instruction::jump(else_end + 1), .rev()
self.current_position, .filter(|(instruction, _)| {
)?; matches!(
instruction.operation(),
Operation::LoadBoolean | Operation::LoadConstant
)
})
.nth(1)
.map(|(instruction, _)| instruction.set_c_to_boolean(true));
} }
self.current_is_expression = self
.current_statement
.last()
.map_or(false, |(instruction, _)| instruction.yields_value());
self.commit_current_statement()?;
return Ok(()); return Ok(());
} }
@ -955,7 +993,10 @@ impl<'src> Parser<'src> {
}); });
} }
self.commit_current_statement(); self.current_is_expression = false;
self.commit_current_statement()?;
Ok(()) Ok(())
} }
@ -989,47 +1030,15 @@ impl<'src> Parser<'src> {
let jump_back = Instruction::jump(jump_start); let jump_back = Instruction::jump(jump_start);
self.emit_instruction(jump_back, self.current_position); self.emit_instruction(jump_back, self.current_position);
self.commit_current_statement(); self.commit_current_statement()?;
self.current_is_expression = false;
Ok(()) Ok(())
} }
fn parse_statement(&mut self, allowed: Allowed) -> Result<(), ParseError> { fn parse_statement(&mut self, allowed: Allowed) -> Result<(), ParseError> {
self.parse( self.parse(Precedence::None, allowed)?;
Precedence::None,
Allowed {
assignment: true,
explicit_return: true,
implicit_return: true,
},
)?;
let parsed_expression = self
.current_statement
.last()
.or_else(|| self.chunk.instructions().last())
.map(|(instruction, _)| instruction.yields_value())
.unwrap_or(false);
let end_of_statement = matches!(
self.current_token,
Token::Eof | Token::RightCurlyBrace | Token::Semicolon
);
let has_semicolon = self.allow(Token::Semicolon)?;
let returned = self
.current_statement
.last()
.map(|(instruction, _)| matches!(instruction.operation(), Operation::Return))
.unwrap_or(false);
if allowed.implicit_return
&& parsed_expression
&& end_of_statement
&& !has_semicolon
&& !returned
{
self.emit_instruction(Instruction::r#return(true), self.current_position);
self.commit_current_statement();
}
Ok(()) Ok(())
} }
@ -1080,7 +1089,33 @@ impl<'src> Parser<'src> {
let end = self.current_position.1; let end = self.current_position.1;
self.emit_instruction(Instruction::r#return(has_return_value), Span(start, end)); self.emit_instruction(Instruction::r#return(has_return_value), Span(start, end));
self.commit_current_statement();
self.current_is_expression = false;
self.commit_current_statement()?;
Ok(())
}
fn parse_implicit_return(&mut self) -> Result<(), ParseError> {
if !self.current_is_expression {
return Ok(());
}
let end_of_statement = matches!(
self.current_token,
Token::Eof | Token::RightCurlyBrace | Token::Semicolon
);
let has_semicolon = self.allow(Token::Semicolon)?;
let returned = self
.current_statement
.last()
.map(|(instruction, _)| matches!(instruction.operation(), Operation::Return))
.unwrap_or(false);
if end_of_statement && !has_semicolon && !returned {
self.emit_instruction(Instruction::r#return(true), self.current_position);
}
Ok(()) Ok(())
} }
@ -1131,7 +1166,10 @@ impl<'src> Parser<'src> {
Instruction::define_local(register, local_index, is_mutable), Instruction::define_local(register, local_index, is_mutable),
position, position,
); );
self.commit_current_statement();
self.current_is_expression = false;
self.commit_current_statement()?;
Ok(()) Ok(())
} }
@ -1230,6 +1268,7 @@ impl<'src> Parser<'src> {
explicit_return: true, explicit_return: true,
implicit_return: true, implicit_return: true,
})?; })?;
function_parser.commit_current_statement()?;
} }
function_parser.advance()?; function_parser.advance()?;
@ -1264,9 +1303,14 @@ impl<'src> Parser<'src> {
Instruction::define_local(register, local_index, false), Instruction::define_local(register, local_index, false),
identifier_position, identifier_position,
); );
self.commit_current_statement();
self.current_is_expression = false;
self.commit_current_statement()?;
} else { } else {
self.emit_constant(function, Span(function_start, function_end))?; self.emit_constant(function, Span(function_start, function_end))?;
self.current_is_expression = true;
} }
Ok(()) Ok(())
@ -1318,9 +1362,17 @@ impl<'src> Parser<'src> {
Span(start, end), Span(start, end),
); );
self.current_is_expression = true;
Ok(()) Ok(())
} }
fn parse_semicolon(&mut self, _: Allowed) -> Result<(), ParseError> {
self.current_is_expression = false;
self.advance()
}
fn expect_expression(&mut self, _: Allowed) -> Result<(), ParseError> { fn expect_expression(&mut self, _: Allowed) -> Result<(), ParseError> {
if self.current_token.is_expression() { if self.current_token.is_expression() {
Ok(()) Ok(())
@ -1657,7 +1709,7 @@ impl From<&Token<'_>> for ParseRule<'_> {
precedence: Precedence::None, precedence: Precedence::None,
}, },
Token::Semicolon => ParseRule { Token::Semicolon => ParseRule {
prefix: Some(Parser::expect_expression), prefix: Some(Parser::parse_semicolon),
infix: None, infix: None,
precedence: Precedence::None, precedence: Precedence::None,
}, },

View File

@ -538,21 +538,23 @@ fn if_else_complex() {
*Instruction::equal(true, 0, 1) *Instruction::equal(true, 0, 1)
.set_b_is_constant() .set_b_is_constant()
.set_c_is_constant(), .set_c_is_constant(),
Span(9, 11) Span(14, 16)
), ),
(Instruction::jump(7), Span(9, 11)), (Instruction::jump(7), Span(14, 16)),
(Instruction::load_constant(0, 0, false), Span(9, 11)), (Instruction::load_constant(0, 2, false), Span(33, 34)),
(Instruction::load_constant(1, 1, false), Span(9, 11)), (Instruction::load_constant(1, 3, false), Span(36, 37)),
(Instruction::load_constant(2, 2, false), Span(9, 11)), (Instruction::load_constant(2, 4, false), Span(39, 40)),
(Instruction::load_constant(3, 3, false), Span(9, 11)), (Instruction::load_constant(3, 5, false), Span(42, 43)),
(Instruction::jump(11), Span(9, 11)), (Instruction::jump(11), Span(95, 95)),
(Instruction::load_constant(0, 0, false), Span(9, 11)), (Instruction::load_constant(4, 6, false), Span(74, 75)),
(Instruction::load_constant(1, 1, false), Span(9, 11)), (Instruction::load_constant(5, 7, false), Span(77, 78)),
(Instruction::load_constant(2, 2, false), Span(9, 11)), (Instruction::load_constant(6, 8, false), Span(80, 81)),
(Instruction::load_constant(3, 3, false), Span(9, 11)), (Instruction::load_constant(7, 9, false), Span(83, 84)),
(Instruction::r#return(true), Span(11, 11)), (Instruction::r#return(true), Span(95, 95)),
], ],
vec![ vec![
Value::integer(1),
Value::integer(1),
Value::integer(1), Value::integer(1),
Value::integer(2), Value::integer(2),
Value::integer(3), Value::integer(3),