use crate::error::Error;
use crate::tokenizer::{types::TokenChecker, Token};
pub(super) fn expect_keyword<'parser>(
tokens: &'parser [Token],
keyword: &str,
) -> Result<bool, Error> {
if tokens.len() == 0 {
Err(unexpected_end!())
} else {
Ok(tokens[0].is_given_keyword(keyword))
}
}
pub(super) fn expect_keywords<'parser>(
tokens: &'parser [Token],
keywords: &[&str],
) -> Result<bool, Error> {
if tokens.len() < keywords.len() {
Err(unexpected_end!())
} else {
Ok(keywords
.iter()
.zip(tokens.iter())
.all(|(k, t)| t.is_given_keyword(k)))
}
}
pub(super) fn expect_one_of_keywords<'parser>(
tokens: &'parser [Token],
keywords: &[&str],
) -> Result<bool, Error> {
if tokens.len() == 0 {
Err(unexpected_end!())
} else {
Ok(keywords.iter().any(|&k| expect_keyword(tokens, k).unwrap()))
}
}
pub(super) fn expect_token<'parser>(
tokens: &'parser [Token],
checker: TokenChecker,
) -> Result<bool, Error> {
if tokens.len() == 0 {
Err(unexpected_end!())
} else {
Ok(checker(&tokens[0]))
}
}
pub(super) fn expect_one_of_tokens<'parser>(
tokens: &'parser [Token],
checkers: &'parser [TokenChecker],
) -> Result<bool, Error> {
if tokens.len() == 0 {
Err(unexpected_end!())
} else {
Ok(checkers.iter().any(|&c| expect_token(tokens, c).unwrap()))
}
}
pub(super) fn expect_tokens<'parser>(
tokens: &'parser [Token],
checkers: &'parser [&'parser [TokenChecker]],
) -> Result<bool, Error> {
if tokens.len() < checkers.len() {
Err(unexpected_end!())
} else {
Ok(checkers
.iter()
.zip(tokens.iter())
.all(|(inner_tokens, t)| inner_tokens.iter().any(|c| c(t))))
}
}
pub(super) fn parse_set_ish_value<'parser>(
tokens: &'parser [Token],
) -> Result<(String, usize), Error> {
let (begin_token, end_token): (TokenChecker, TokenChecker) =
if expect_token(tokens, Token::is_curly_begin)? {
(Token::is_curly_begin, Token::is_curly_end)
} else if expect_token(tokens, Token::is_round_begin)? {
(Token::is_round_begin, Token::is_round_end)
} else {
return Err(unexpected_token!("'(' or '}'", tokens[0]));
};
let mut level = 0;
let mut consumed = 0;
loop {
if expect_token(&tokens[consumed..], begin_token)? {
level += 1;
}
consumed += 1;
if expect_token(&tokens[consumed..], end_token)? {
level -= 1;
if level == 0 {
consumed += 1;
return Ok((Token::concat(&tokens[0..consumed], " "), consumed));
}
}
}
}