use crate::parse::{parsers::*, *};
use formally_support::*;
pub trait Control<'c, Out: 'c>: Parse<'c, Out> {
fn map<F, R>(self, f: F) -> Parser<'c, R>
where
F: 'c + Fn(Out) -> R,
R: 'c,
{
Parser::new_with_name(self.name().clone(), move |state: &mut State| {
Ok(f(self.parse_from(state)?))
})
}
fn or(self, other: impl Parse<'c, Out>) -> Parser<'c, Out> {
let name = self.name().or(other.name());
Parser::new_with_name(name.clone(), move |state: &mut State| {
let mut first = state.split();
match self.parse_from(&mut first) {
Ok(out) => {
first.commit();
Ok(out)
}
Err(_) if !first.has_advanced() => {
let mut second = state.split();
match other.parse_from(&mut second) {
Ok(out) => {
second.commit();
Ok(out)
}
Err(_) if !second.has_advanced() => {
let Token(token, span) = state.token();
error!(
state,
span,
SyntaxIssue::Expected(name.clone(), token.to_string())
);
Err(DiagnosticEmitted.into())
}
Err(err) => {
second.commit();
Err(err)
}
}
}
Err(err) => {
first.commit();
Err(err)
}
}
})
}
fn silent(self) -> Parser<'c, Out> {
Parser::new_with_name(self.name().clone(), move |state: &mut State| {
let mut split = state.split();
match self.parse_from(&mut split) {
Ok(out) => {
split.commit();
Ok(out)
}
Err(_) => Err(ParseError::Reject),
}
})
}
fn and<T>(self, other: impl Parse<'c, T>) -> Parser<'c, (Out, T)>
where
T: 'c,
{
Parser::new(move |state: &mut State| {
let v1 = self.parse_from(state)?;
state.skip();
let v2 = other.parse_from(state)?;
Ok((v1, v2))
})
}
fn then<T>(self, other: impl Parse<'c, T>) -> Parser<'c, T>
where
T: 'c,
{
Parser::new(move |state: &mut State| {
self.parse_from(state)?;
state.skip();
other.parse_from(state)
})
}
fn requires<F>(self, test: F, error: impl Into<String>) -> Parser<'c, Out>
where
F: 'c + Fn(&Out) -> bool,
{
let error = error.into();
Parser::new_with_name(self.name().clone(), move |state: &mut State| {
let mut split = state.split();
let v = self.parse_from(&mut split)?;
if !test(&v) {
let span = split.elapsed();
split.commit();
error!(state, span, error.clone());
Err(DiagnosticEmitted.into())
} else {
split.commit();
Ok(v)
}
})
}
fn only_if<F>(self, test: F) -> Parser<'c, Out>
where
F: 'c + Fn(&Out) -> bool,
{
Parser::new_with_name(self.name().clone(), move |state: &mut State| {
let mut new = state.split();
match self.parse_from(&mut new) {
Ok(out) if test(&out) => {
new.commit();
Ok(out)
}
_ => Err(ParseError::Reject),
}
})
}
fn skipping(self, p: Parser<'static, ()>) -> Parser<'c, Out> {
Parser::new_with_name(self.name().clone(), move |state: &mut State| {
let mut new = state.split().skipping(p.clone());
State::skip(&mut new);
let out = self.parse_from(&mut new);
new.commit();
out
})
}
fn named(self, singular: impl Into<String>, plural: impl Into<String>) -> Parser<'c, Out> {
let name = Name::Name {
singular: singular.into(),
plural: plural.into(),
};
Parser::new_with_name(name.clone(), move |state: &mut State| {
let mut split = state.split();
match self.parse_from(&mut split) {
Ok(out) => {
split.commit();
Ok(out)
}
Err(_) if !split.has_advanced() => {
let Token(token, span) = state.token();
error!(
state,
span,
SyntaxIssue::Expected(name.clone(), token.to_string())
);
Err(DiagnosticEmitted.into())
}
Err(_) => {
let elapsed = split.elapsed();
split.commit();
trace!(state, elapsed, SyntaxIssue::Trace(name.clone()));
Err(DiagnosticEmitted.into())
}
}
})
}
fn with_name(self, name: Name) -> Parser<'c, Out> {
Parser {
parse: Rc::new(move |state| self.parse_from(state)),
name,
}
}
fn spanned(self) -> Parser<'c, (Out, Span)> {
Parser::new_with_name(self.name().clone(), move |state: &mut State| {
let begin = state.location();
let value = self.parse_from(state)?;
let end = state.location();
let span = Span::Span {
origin: state.origin.clone(),
begin,
end,
};
Ok((value, span))
})
}
fn located(self) -> Parser<'c, <Out as Locatable>::Located>
where
Out: Locatable,
{
self.spanned().map(|(value, span)| value.over(span))
}
fn optional(self) -> Parser<'c, Option<Out>> {
self.map(Some).or(none())
}
fn with_value<T>(self, value: T) -> Parser<'c, T>
where
T: 'c + Clone,
{
self.map(move |_| value.clone())
}
fn ignore(self) -> Parser<'c, ()> {
self.with_value(())
}
fn whole(self) -> Parser<'c, Out> {
self.and(eof()).map(|(v, _)| v)
}
}
impl<'c, Out: 'c, T: Parse<'c, Out>> Control<'c, Out> for T {}
pub trait Unwrap<'c, Out: 'c>: Parse<'c, Option<Out>> {
fn unwrap(self) -> Parser<'c, Out> {
Parser::new(move |state: &mut State| {
self.parse_from(state).map(|o: Option<Out>| o.unwrap())
})
}
}
impl<'c, Out: 'c, T: Parse<'c, Option<Out>>> Unwrap<'c, Out> for T {}
pub trait Ok<'c, Out: 'c, E: 'c + Display>: Parse<'c, std::result::Result<Out, E>> {
fn ok(self) -> Parser<'c, Out> {
Parser::new_with_name(self.name().clone(), move |state: &mut State| {
let (value, span) = self.clone().spanned().parse_from(state)?;
match value {
Ok(value) => Ok(value),
Err(err) => {
error!(state, span, "{err}");
Err(DiagnosticEmitted.into())
}
}
})
}
}
impl<'c, Out: 'c, E: 'c + Display, T: Parse<'c, std::result::Result<Out, E>>> Ok<'c, Out, E> for T {}