use crate::{ArrayPattern, Error, Interval, Pattern, Result, parse::Token};
pub(crate) fn parse_bracket_array(
lexer: &mut logos::Lexer<Token>,
) -> Result<Pattern> {
let mut lookahead = lexer.clone();
match lookahead.next() {
Some(Ok(Token::Range(res))) => {
let quantifier = res?;
lexer.next();
let pattern = ArrayPattern::with_length_interval(quantifier.into());
match lexer.next() {
Some(Ok(Token::BracketClose)) => Ok(Pattern::Structure(
crate::pattern::StructurePattern::Array(pattern),
)),
Some(Ok(token)) => {
Err(Error::UnexpectedToken(Box::new(token), lexer.span()))
}
Some(Err(e)) => Err(e),
None => Err(Error::ExpectedCloseBracket(lexer.span())),
}
}
Some(Ok(Token::BracketClose)) => {
lexer.next(); Ok(Pattern::Structure(crate::pattern::StructurePattern::Array(
ArrayPattern::with_length_interval(Interval::default()),
)))
}
_ => {
let element_pattern = parse_array_or(lexer)?;
let pattern = ArrayPattern::with_elements(element_pattern);
match lexer.next() {
Some(Ok(Token::BracketClose)) => Ok(Pattern::Structure(
crate::pattern::StructurePattern::Array(pattern),
)),
Some(Ok(token)) => {
Err(Error::UnexpectedToken(Box::new(token), lexer.span()))
}
Some(Err(e)) => Err(e),
None => Err(Error::ExpectedCloseBracket(lexer.span())),
}
}
}
}
pub(crate) fn parse_array_or(
lexer: &mut logos::Lexer<Token>,
) -> Result<Pattern> {
let mut patterns = vec![parse_array_and(lexer)?];
loop {
let mut lookahead = lexer.clone();
match lookahead.next() {
Some(Ok(Token::Or)) => {
lexer.next(); patterns.push(parse_array_and(lexer)?);
}
_ => break,
}
}
if patterns.len() == 1 {
Ok(patterns.remove(0))
} else {
Ok(Pattern::or(patterns))
}
}
pub(crate) fn parse_array_and(
lexer: &mut logos::Lexer<Token>,
) -> Result<Pattern> {
let mut patterns = vec![parse_array_not(lexer)?];
loop {
let mut lookahead = lexer.clone();
match lookahead.next() {
Some(Ok(Token::And)) => {
lexer.next(); patterns.push(parse_array_not(lexer)?);
}
_ => break,
}
}
if patterns.len() == 1 {
Ok(patterns.remove(0))
} else {
Ok(Pattern::and(patterns))
}
}
pub(crate) fn parse_array_not(
lexer: &mut logos::Lexer<Token>,
) -> Result<Pattern> {
let mut lookahead = lexer.clone();
match lookahead.next() {
Some(Ok(Token::Not)) => {
lexer.next(); let pattern = parse_array_not(lexer)?; Ok(Pattern::not_matching(pattern))
}
_ => parse_array_sequence(lexer),
}
}
pub(crate) fn parse_array_sequence(
lexer: &mut logos::Lexer<Token>,
) -> Result<Pattern> {
let mut patterns = vec![super::super::meta::parse_or(lexer)?];
loop {
let mut lookahead = lexer.clone();
match lookahead.next() {
Some(Ok(Token::Comma)) => {
lexer.next(); patterns.push(super::super::meta::parse_or(lexer)?);
}
_ => break,
}
}
if patterns.len() == 1 {
Ok(patterns.remove(0))
} else {
Ok(Pattern::sequence(patterns))
}
}
#[cfg(test)]
mod tests {
use logos::Logos;
use super::*;
#[test]
fn test_parse_bracket_array_single_any_element() {
let mut lexer = Token::lexer("[*]");
lexer.next(); let pattern = parse_bracket_array(&mut lexer).unwrap();
if let Pattern::Structure(crate::pattern::StructurePattern::Array(
ArrayPattern::Elements(inner_pattern),
)) = pattern
{
if let Pattern::Meta(crate::pattern::MetaPattern::Any(_)) =
inner_pattern.as_ref()
{
} else {
panic!(
"Expected inner pattern to be Any, got: {:?}",
inner_pattern
);
}
} else {
panic!("Expected ArrayPattern::Elements, got: {:?}", pattern);
}
}
#[test]
fn test_parse_bracket_array_empty() {
let mut lexer = Token::lexer("[]");
lexer.next(); let pattern = parse_bracket_array(&mut lexer).unwrap();
assert_eq!(
pattern,
Pattern::Structure(crate::pattern::StructurePattern::Array(
ArrayPattern::with_length_interval(Interval::default())
))
);
}
#[test]
fn test_parse_bracket_array_with_pattern() {
let mut lexer = Token::lexer("[42]");
lexer.next(); let pattern = parse_bracket_array(&mut lexer).unwrap();
if let Pattern::Structure(crate::pattern::StructurePattern::Array(
ArrayPattern::Elements(_),
)) = pattern
{
} else {
panic!("Expected ArrayPattern::WithElements");
}
}
}