pub fn matches<'a, F>(
tokens: &'a [(crate::internal::lexer::Token, &'a str)],
pos: &mut usize,
pred: F,
) -> bool
where
F: Fn(&crate::internal::lexer::Token) -> bool,
{
if let Some((tok, _)) = tokens.get(*pos) {
if pred(tok) {
*pos += 1;
return true;
}
}
false
}
#[cfg(test)]
mod tests {
use super::*;
use crate::internal::lexer::Token;
#[test]
fn test_matches_consumes_when_predicate_true() {
let tokens = vec![(Token::Plus, "+"), (Token::ColumnName, "x")];
let mut pos = 0;
let result = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(result);
assert_eq!(pos, 1); }
#[test]
fn test_matches_does_not_consume_when_predicate_false() {
let tokens = vec![(Token::Minus, "-"), (Token::ColumnName, "x")];
let mut pos = 0;
let result = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(!result);
assert_eq!(pos, 0); }
#[test]
fn test_matches_with_multiple_plus_signs() {
let tokens = vec![
(Token::Plus, "+"),
(Token::Plus, "+"),
(Token::ColumnName, "x"),
];
let mut pos = 0;
let first = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(first);
assert_eq!(pos, 1);
let second = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(second);
assert_eq!(pos, 2);
let third = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(!third);
assert_eq!(pos, 2); }
#[test]
fn test_matches_at_end_of_tokens() {
let tokens = vec![(Token::ColumnName, "x")];
let mut pos = 1;
let result = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(!result);
assert_eq!(pos, 1); }
#[test]
fn test_matches_with_complex_predicate() {
let tokens = vec![
(Token::ColumnName, "x"),
(Token::Integer, "42"),
(Token::One, "1"),
];
let mut pos = 0;
let numeric_predicate = |t: &Token| matches!(t, Token::Integer | Token::One);
let first = matches(&tokens, &mut pos, numeric_predicate);
assert!(!first); assert_eq!(pos, 0);
pos = 1;
let second = matches(&tokens, &mut pos, numeric_predicate);
assert!(second); assert_eq!(pos, 2);
let third = matches(&tokens, &mut pos, numeric_predicate);
assert!(third); assert_eq!(pos, 3);
}
#[test]
fn test_matches_with_empty_tokens() {
let tokens: Vec<(Token, &str)> = vec![];
let mut pos = 0;
let result = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(!result);
assert_eq!(pos, 0); }
#[test]
fn test_matches_preserves_position_when_no_match() {
let tokens = vec![
(Token::ColumnName, "y"),
(Token::Tilde, "~"),
(Token::ColumnName, "x"),
];
let mut pos = 1;
let result = matches(&tokens, &mut pos, |t| matches!(t, Token::Plus));
assert!(!result);
assert_eq!(pos, 1); }
}