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
}
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?
fn synchronize_to_next_statement<I: Iterator<Item = Token>>(iter: &mut I) {
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> {
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 })
} else {
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
let next_token_line = iter.peek().map(Token::line);
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))
} else {
Err(ParseError {
@ -117,7 +132,7 @@ fn parse_binary<I: Iterator<Item = Token>, F: Fn(&mut Peekable<I>) -> Result<Exp
) -> Result<Expr, ParseError> {
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 right = parse_operand(iter)?;
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> {
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 right = parse_unary(iter)?;
Ok(Expr::Unary {
@ -178,7 +193,7 @@ fn parse_primary<I: Iterator<Item = Token>>(iter: &mut Peekable<I>) -> Result<Ex
// consume the left paren
iter.next();
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 {
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>,
valid_kinds: &[TokenKind],
) -> Option<Token> {