use crate::parse::*;
use formally_support::*;
pub fn any() -> Parser<'static, char> {
Parser::new(move |state: &mut State| {
let mut saved = state.view.clone();
match saved.next() {
Some(ch) => {
state.view = saved;
Ok(ch)
}
None => {
let span = Span::Span {
origin: state.origin.clone(),
begin: saved.location,
end: saved.location,
};
error!(state, span, SyntaxIssue::UnexpectedEOF);
Err(DiagnosticEmitted.into())
}
}
})
}
pub fn eof() -> Parser<'static, ()> {
Parser::new(move |state: &mut State| {
let mut split = state.split();
match split.view.next() {
None => Ok(()),
Some(_) => {
let Token(token, span) = state.token();
error!(
state,
span,
SyntaxIssue::Expected(
Name::Name {
singular: "EOF".to_string(),
plural: "EOFs".to_string(),
},
token.to_string()
)
);
Err(DiagnosticEmitted.into())
}
}
})
}
pub fn char(ch: char) -> Parser<'static, char> {
any()
.only_if(move |c| *c == ch)
.named(format!("character '{ch}'"), format!("characters '{ch}'"))
}
pub fn text(txt: &str) -> Parser<'_, String> {
foreach(txt.chars(), char).to_string().silent().named(
format!("occurrence of \"{txt}\""),
format!("occurrences of \"{txt}\""),
)
}
pub fn keyword(kw: &str) -> Parser<'_, String> {
text(kw).named(format!("keyword \"{kw}\""), format!("keywords \"{kw}\""))
}
pub fn alphabetic() -> Parser<'static, char> {
any()
.only_if(|c| c.is_alphabetic())
.named("alphabetic character", "alphabetic characters")
}
pub fn alphanumeric() -> Parser<'static, char> {
any()
.only_if(|c| c.is_alphanumeric())
.named("alphanumeric character", "alphanumeric characters")
}
pub fn digit(radix: u32) -> Parser<'static, char> {
any().only_if(move |c| c.is_digit(radix)).named(
format!("base-{radix} digit"),
format!("base-{radix} digits"),
)
}
pub fn lowercase() -> Parser<'static, char> {
any()
.only_if(|c| c.is_lowercase())
.named("lowercase character", "lowercase characters")
}
pub fn numeric() -> Parser<'static, char> {
any().only_if(|c| c.is_numeric()).named("digit", "digits")
}
pub fn uppercase() -> Parser<'static, char> {
any()
.only_if(|c| c.is_uppercase())
.named("uppercase character", "uppercase characters")
}
pub fn whitespace() -> Parser<'static, char> {
any()
.only_if(|c| c.is_whitespace())
.named("whitespace character", "whitespace characters")
}
pub fn ascii() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii())
.named("ascii character", "ascii characters")
}
pub fn ascii_alphabetic() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii_alphabetic())
.named("ascii alphabetic character", "ascii alphabetic characters")
}
pub fn ascii_alphanumeric() -> Parser<'static, char> {
any().only_if(|c| c.is_ascii_alphanumeric()).named(
"ascii alphanumeric character",
"ascii alphanumeric characters",
)
}
pub fn ascii_digit() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii_digit())
.named("ascii digit", "ascii digits")
}
pub fn ascii_graphic() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii_graphic())
.named("ascii graphic character", "ascii graphic characters")
}
pub fn ascii_hexdigit() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii_hexdigit())
.named("ascii hexadecimal digit", "ascii graphic characters")
}
pub fn ascii_binary_digit() -> Parser<'static, char> {
any()
.only_if(|c| *c == '0' || *c == '1')
.named("binary digit", "binary digits")
}
pub fn ascii_lowercase() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii_lowercase())
.named("ascii lowercase character", "ascii lowercase character")
}
pub fn ascii_punctuation() -> Parser<'static, char> {
any().only_if(|c| c.is_ascii_punctuation()).named(
"ascii punctuation character",
"ascii punctuation characters",
)
}
pub fn ascii_uppercase() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii_uppercase())
.named("ascii uppercase character", "ascii uppercase character")
}
pub fn ascii_whitespace() -> Parser<'static, char> {
any()
.only_if(|c| c.is_ascii_whitespace())
.named("ascii whitespace character", "ascii whitespace character")
}