Move token matching into a macro

master
Nick Krichevsky 2024-05-21 15:23:53 -04:00
parent 8cdfbd61a9
commit d497e19564
1 changed files with 21 additions and 6 deletions

View File

@ -41,6 +41,21 @@ pub fn parse_program<I: Iterator<Item = Token>, F: FnMut(ScriptError)>(
statements statements
} }
macro_rules! match_token_kind {
($tokens_peekable: expr, $($p:pat),+) => {{
match $tokens_peekable.peek().map(|token| token.kind()) {
$(
Some($p) => {
// consume the peeked token
let token = $tokens_peekable.next().unwrap();
Some(token)
}
)+
_ => None
}
}};
}
// To be used later? // To be used later?
fn synchronize_to_next_statement<I: Iterator<Item = Token>>(iter: &mut I) { fn synchronize_to_next_statement<I: Iterator<Item = Token>>(iter: &mut I) {
for item in iter { for item in iter {
@ -51,7 +66,7 @@ fn synchronize_to_next_statement<I: Iterator<Item = Token>>(iter: &mut I) {
} }
fn parse_statement<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Stmt, ParseError> { fn parse_statement<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Stmt, ParseError> {
if match_token(iter, &[TokenKind::Print]).is_some() { if match_token_kind!(iter, TokenKind::Print).is_some() {
parse_statement_containing_expression(iter, |expression| Stmt::Print { expression }) parse_statement_containing_expression(iter, |expression| Stmt::Print { expression })
} else { } else {
parse_statement_containing_expression(iter, |expression| Stmt::Expression { expression }) parse_statement_containing_expression(iter, |expression| Stmt::Expression { expression })
@ -65,7 +80,7 @@ fn parse_statement_containing_expression<I: Iterator<Item = Token>, F: Fn(Expr)
// Snatch the next token before we parse it, so we have line information // Snatch the next token before we parse it, so we have line information
let next_token_line = iter.peek().map(Token::line); let next_token_line = iter.peek().map(Token::line);
let expression = parse_expression(iter)?; let expression = parse_expression(iter)?;
if match_token(iter, &[TokenKind::SemiColon]).is_some() { if match_token_kind!(iter, TokenKind::SemiColon).is_some() {
Ok(make_statement(expression)) Ok(make_statement(expression))
} else { } else {
Err(ParseError { Err(ParseError {
@ -117,7 +132,7 @@ fn parse_binary<I: Iterator<Item = Token>, F: Fn(&mut Peekable<I>) -> Result<Exp
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
let mut expr = parse_operand(iter)?; let mut expr = parse_operand(iter)?;
while let Some(token) = match_token(iter, valid_operators) { while let Some(token) = match_token_kind_eq(iter, valid_operators) {
let operator = token; let operator = token;
let right = parse_operand(iter)?; let right = parse_operand(iter)?;
expr = Expr::Binary { expr = Expr::Binary {
@ -131,7 +146,7 @@ fn parse_binary<I: Iterator<Item = Token>, F: Fn(&mut Peekable<I>) -> Result<Exp
} }
fn parse_unary<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Expr, ParseError> { fn parse_unary<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Expr, ParseError> {
if let Some(token) = match_token(iter, &[TokenKind::Bang, TokenKind::Minus]) { if let Some(token) = match_token_kind!(iter, TokenKind::Bang, TokenKind::Minus) {
let operator = token; let operator = token;
let right = parse_unary(iter)?; let right = parse_unary(iter)?;
Ok(Expr::Unary { Ok(Expr::Unary {
@ -178,7 +193,7 @@ fn parse_primary<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Ex
// consume the left paren // consume the left paren
iter.next(); iter.next();
let expr = parse_expression(iter)?; let expr = parse_expression(iter)?;
if match_token(iter, &[TokenKind::RightParen]).is_some() { if match_token_kind!(iter, TokenKind::RightParen).is_some() {
Ok(Expr::Grouping { Ok(Expr::Grouping {
expr: Box::new(expr), expr: Box::new(expr),
}) })
@ -197,7 +212,7 @@ fn parse_primary<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Ex
} }
} }
fn match_token<I: Iterator<Item = Token>>( fn match_token_kind_eq<I: Iterator<Item = Token>>(
iter: &mut Peekable<I>, iter: &mut Peekable<I>,
valid_kinds: &[TokenKind], valid_kinds: &[TokenKind],
) -> Option<Token> { ) -> Option<Token> {