refactor(tazjin/rlox): Refactor Compiler::consume into a macro

Making this function a macro instead makes it possible to match
arbitrary token kinds, even the ones that carry data, without changing
the syntax too much.

Change-Id: I5cda9e36d6833bd9c259f7d4d8340db6e783b4e8
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2593
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2021-03-05 21:43:28 +02:00 committed by tazjin
parent 822e5ae57f
commit b7b94335cc

View file

@ -153,6 +153,15 @@ fn rule_for<T: Iterator<Item = Token>>(token: &TokenKind) -> ParseRule<T> {
} }
} }
macro_rules! consume {
( $self:ident, $expected:pat, $err:expr ) => {
match $self.current().kind {
$expected => $self.advance(),
_ => $self.error_at($self.current().line, $err),
}
};
}
impl<T: Iterator<Item = Token>> Compiler<T> { impl<T: Iterator<Item = Token>> Compiler<T> {
fn compile(&mut self) -> LoxResult<()> { fn compile(&mut self) -> LoxResult<()> {
self.advance(); self.advance();
@ -193,9 +202,10 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
fn print_statement(&mut self) -> LoxResult<()> { fn print_statement(&mut self) -> LoxResult<()> {
self.expression()?; self.expression()?;
self.consume( consume!(
&TokenKind::Semicolon, self,
ErrorKind::ExpectedToken("Expected ';' after value"), TokenKind::Semicolon,
ErrorKind::ExpectedToken("Expected ';' after value")
); );
self.emit_op(OpCode::OpPrint); self.emit_op(OpCode::OpPrint);
Ok(()) Ok(())
@ -203,9 +213,10 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
fn expression_statement(&mut self) -> LoxResult<()> { fn expression_statement(&mut self) -> LoxResult<()> {
self.expression()?; self.expression()?;
self.consume( consume!(
&TokenKind::Semicolon, self,
ErrorKind::ExpectedToken("Expected ';' after expression"), TokenKind::Semicolon,
ErrorKind::ExpectedToken("Expected ';' after expression")
); );
self.emit_op(OpCode::OpPop); self.emit_op(OpCode::OpPop);
Ok(()) Ok(())
@ -222,9 +233,10 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
fn grouping(&mut self) -> LoxResult<()> { fn grouping(&mut self) -> LoxResult<()> {
self.expression()?; self.expression()?;
self.consume( consume!(
&TokenKind::RightParen, self,
ErrorKind::ExpectedToken("Expected ')' after expression"), TokenKind::RightParen,
ErrorKind::ExpectedToken("Expected ')' after expression")
); );
Ok(()) Ok(())
} }
@ -334,15 +346,6 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
Ok(()) Ok(())
} }
fn consume(&mut self, expected: &TokenKind, err: ErrorKind) {
if self.current().kind == *expected {
self.advance();
return;
}
self.error_at(self.current().line, err);
}
fn current_chunk(&mut self) -> &mut Chunk { fn current_chunk(&mut self) -> &mut Chunk {
&mut self.chunk &mut self.chunk
} }