Move token matching into a macro
parent
8cdfbd61a9
commit
d497e19564
27
src/parse.rs
27
src/parse.rs
|
@ -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> {
|
||||||
|
|
Loading…
Reference in New Issue