1
0

Improve precedence parsing

This commit is contained in:
Jeff 2024-09-15 06:26:31 -04:00
parent 4653a3f506
commit b66710e3eb

View File

@ -71,6 +71,8 @@ impl<'src> Parser<'src> {
} else { } else {
self.current_register += 1; self.current_register += 1;
log::trace!("Incremented register to {}", self.current_register);
Ok(()) Ok(())
} }
} }
@ -85,6 +87,8 @@ impl<'src> Parser<'src> {
} else { } else {
self.current_register -= 1; self.current_register -= 1;
log::trace!("Decremented register to {}", self.current_register);
Ok(()) Ok(())
} }
} }
@ -258,19 +262,44 @@ impl<'src> Parser<'src> {
} }
fn parse_binary(&mut self) -> Result<(), ParseError> { fn parse_binary(&mut self) -> Result<(), ParseError> {
let (left_instruction, left_position) =
self.chunk.pop_instruction(self.current_position)?;
let mut push_back_left = false;
let mut left_is_constant = false;
let left = match left_instruction.operation() {
Operation::LoadConstant => {
left_is_constant = true;
self.decrement_register()?;
left_instruction.first_argument()
}
Operation::GetLocal => {
self.decrement_register()?;
left_instruction.first_argument()
}
_ => {
push_back_left = true;
self.current_register - 1
}
};
if push_back_left {
self.emit_instruction(left_instruction, left_position);
}
let operator_position = self.previous_position; let operator_position = self.previous_position;
let operator = self.previous_token.kind(); let operator = self.previous_token.kind();
let rule = ParseRule::from(&operator); let rule = ParseRule::from(&operator);
self.parse(rule.precedence.increment())?; self.parse(rule.precedence)?;
let mut push_back_right = false;
let mut push_back_left = false;
let mut right_is_constant = false;
let mut left_is_constant = false;
let (right_instruction, right_position) = let (right_instruction, right_position) =
self.chunk.pop_instruction(self.current_position)?; self.chunk.pop_instruction(self.current_position)?;
let mut push_back_right = false;
let mut right_is_constant = false;
let right = match right_instruction.operation() { let right = match right_instruction.operation() {
Operation::LoadConstant => { Operation::LoadConstant => {
right_is_constant = true; right_is_constant = true;
@ -288,33 +317,6 @@ impl<'src> Parser<'src> {
self.current_register - 1 self.current_register - 1
} }
}; };
let (left_instruction, left_position) =
self.chunk.pop_instruction(self.current_position)?;
let left = match left_instruction.operation() {
Operation::LoadConstant => {
left_is_constant = true;
self.decrement_register()?;
left_instruction.first_argument()
}
Operation::GetLocal => {
self.decrement_register()?;
left_instruction.first_argument()
}
_ => {
push_back_left = true;
if push_back_right {
self.current_register - 2
} else {
self.current_register - 1
}
}
};
if push_back_left {
self.emit_instruction(left_instruction, left_position);
}
if push_back_right { if push_back_right {
self.emit_instruction(right_instruction, right_position); self.emit_instruction(right_instruction, right_position);
@ -520,13 +522,11 @@ impl<'src> Parser<'src> {
} }
fn parse(&mut self, precedence: Precedence) -> Result<(), ParseError> { fn parse(&mut self, precedence: Precedence) -> Result<(), ParseError> {
self.advance()?; let prefix_parser = if let Some(prefix) = ParseRule::from(&self.current_token.kind()).prefix
{
let prefix_parser =
if let Some(prefix) = ParseRule::from(&self.previous_token.kind()).prefix {
log::trace!( log::trace!(
"Parsing {} as prefix with precedence {precedence}", "Parsing {} as prefix with precedence {precedence}",
self.previous_token, self.current_token,
); );
prefix prefix
@ -538,12 +538,15 @@ impl<'src> Parser<'src> {
}; };
let allow_assignment = precedence < Precedence::Assignment; let allow_assignment = precedence < Precedence::Assignment;
self.advance()?;
prefix_parser(self, allow_assignment)?; prefix_parser(self, allow_assignment)?;
while precedence < ParseRule::from(&self.current_token.kind()).precedence { let mut infix_rule = ParseRule::from(&self.current_token.kind());
while precedence < infix_rule.precedence {
self.advance()?; self.advance()?;
if let Some(infix_parser) = ParseRule::from(&self.previous_token.kind()).infix { if let Some(infix_parser) = infix_rule.infix {
log::trace!( log::trace!(
"Parsing {} as infix with precedence {precedence}", "Parsing {} as infix with precedence {precedence}",
self.previous_token, self.previous_token,
@ -560,6 +563,8 @@ impl<'src> Parser<'src> {
} else { } else {
break; break;
} }
infix_rule = ParseRule::from(&self.current_token.kind());
} }
Ok(()) Ok(())