pub mod capture;
pub mod deferred;
pub mod erase_types;
pub mod impl_parser;
pub mod memoized;
pub mod multiple;
pub mod output_mapper;
pub mod range_parser;
pub mod recover_error;
pub mod single_token;
pub mod token_parser;
pub use capture::{
BindDebugInfo, BoundResult, BoundValue, Capture, MultipleProperty, OptionalProperty, Property,
ResultBinder, SingleProperty, SpanBinder, bind_result, bind_span,
};
pub use deferred::{Deferred, DeferredWeak, recursive};
pub use impl_parser::as_parser;
pub use memoized::Memoized;
pub use multiple::MultipleParser;
pub use range_parser::RangeParser;
pub use recover_error::ErrorRecoverer;
pub use single_token::SingleTokenParser;
use std::rc::Rc;
pub use token_parser::{TokenParser, token_parser};
#[cfg(feature = "parser-trace")]
use crate::trace::{TraceFormat, TraceSession};
#[cfg(feature = "parser-trace")]
type ParseWithTraceResult<Out> =
Result<(Out, Vec<ParserError>, TraceSession), FurthestFailError>;
use crate::{
context::ParserContext,
error::{
FurthestFailError, MatcherRunError, ParserError,
error_handler::{ErrorHandler, ErrorHandlerChoice},
},
input::{Input, InputStream},
matcher::{ErrorContextualizer, ignore_result::IgnoreResult},
parser::recover_error::ErrorRecoverer as ErrorRecovererInner,
};
pub(crate) mod internal {
use std::fmt::{Debug, Display};
use crate::{
context::ParserContext,
error::{MatcherRunError, error_handler::ErrorHandler},
input::{Input, InputStream},
parser::ParserCombinator,
};
pub trait ParserImpl<'src, Inp>: Debug + ParserCombinator + Clone
where
Inp: Input<'src>,
{
type Output;
const CAN_FAIL: bool;
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: &mut impl ErrorHandler,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Self::Output>, MatcherRunError>;
#[inline]
fn maybe_label(&self) -> Option<Box<dyn Display>> {
None
}
}
}
pub trait Parser<'src, Inp: Input<'src>>: internal::ParserImpl<'src, Inp>
where
Self: 'src,
{
fn parse_whole_input(
&self,
input: Inp,
) -> Result<
(
<Self as internal::ParserImpl<'src, Inp>>::Output,
Vec<ParserError>,
),
FurthestFailError,
>
where
Self: Clone,
Inp: Clone + 'src,
{
crate::parse_whole_input_with_default_eof(self, input)
}
fn parse_str(
&self,
src: &'src str,
) -> Result<
(
<Self as internal::ParserImpl<'src, &'src str>>::Output,
Vec<ParserError>,
),
FurthestFailError,
>
where
Self: Parser<'src, &'src str> + Clone,
{
crate::parse_whole_input_with_default_eof(self, src)
}
#[cfg(feature = "parser-trace")]
fn parse_whole_input_with_trace(
&self,
input: Inp,
) -> ParseWithTraceResult<<Self as internal::ParserImpl<'src, Inp>>::Output>
where
Self: Clone,
Inp: Clone + 'src,
{
let (result, trace) =
crate::parse_whole_input_inner_with_trace(self, input, TraceSession::new());
result.map(|(output, errors)| (output, errors, trace))
}
#[cfg(feature = "parser-trace")]
fn parse_whole_input_with_trace_session(
&self,
input: Inp,
trace_session: TraceSession,
) -> ParseWithTraceResult<<Self as internal::ParserImpl<'src, Inp>>::Output>
where
Self: Clone,
Inp: Clone + 'src,
{
let (result, trace) = crate::parse_whole_input_inner_with_trace(self, input, trace_session);
result.map(|(output, errors)| (output, errors, trace))
}
#[cfg(feature = "parser-trace")]
fn parse_str_with_trace(
&self,
src: &'src str,
) -> ParseWithTraceResult<<Self as internal::ParserImpl<'src, &'src str>>::Output>
where
Self: Parser<'src, &'src str> + Clone,
{
self.parse_whole_input_with_trace(src)
}
#[cfg(feature = "parser-trace")]
fn parse_whole_input_with_trace_to_file(
&self,
input: Inp,
trace_path: impl AsRef<std::path::Path>,
format: TraceFormat,
) -> Result<
(
<Self as internal::ParserImpl<'src, Inp>>::Output,
Vec<ParserError>,
),
crate::ParseWithTraceToFileError,
>
where
Self: Clone,
Inp: Clone + 'src,
{
let (result, trace) =
crate::parse_whole_input_inner_with_trace(self, input, TraceSession::new());
crate::write_trace_to_file(&trace, trace_path, format)?;
match result {
Ok((output, errors)) => Ok((output, errors)),
Err(parse_err) => Err(crate::ParseWithTraceToFileError::Parse(parse_err)),
}
}
#[cfg(feature = "parser-trace")]
fn parse_str_with_trace_to_file(
&self,
src: &'src str,
trace_path: impl AsRef<std::path::Path>,
format: TraceFormat,
) -> Result<
(
<Self as internal::ParserImpl<'src, &'src str>>::Output,
Vec<ParserError>,
),
crate::ParseWithTraceToFileError,
>
where
Self: Parser<'src, &'src str> + Clone,
{
let (result, mut trace) =
crate::parse_whole_input_inner_with_trace(self, src, TraceSession::new());
trace.set_source_text(src);
crate::write_trace_to_file(&trace, trace_path, format)?;
match result {
Ok((output, errors)) => Ok((output, errors)),
Err(parse_err) => Err(crate::ParseWithTraceToFileError::Parse(parse_err)),
}
}
}
pub trait ParserCombinator {
fn memoized<T>(self) -> memoized::Memoized<Self, T>
where
Self: Sized,
{
memoized::Memoized::new(self)
}
fn recover_with<RecoveryParser>(
self,
recover_parser: RecoveryParser,
) -> ErrorRecovererInner<Self, RecoveryParser>
where
Self: Sized,
{
ErrorRecovererInner::new(self, recover_parser)
}
#[cfg(feature = "parser-trace")]
#[track_caller]
fn add_error_info<Pars>(self, error_parser: Pars) -> ErrorContextualizer<Self, Pars>
where
Self: Sized,
{
ErrorContextualizer::new(self, error_parser)
}
#[cfg(not(feature = "parser-trace"))]
fn add_error_info<Pars>(self, error_parser: Pars) -> ErrorContextualizer<Self, Pars>
where
Self: Sized,
{
ErrorContextualizer::new(self, error_parser)
}
#[cfg(feature = "parser-trace")]
#[track_caller]
fn ignore_result(self) -> IgnoreResult<Self>
where
Self: Sized,
{
IgnoreResult::new(self)
}
#[cfg(not(feature = "parser-trace"))]
fn ignore_result(self) -> IgnoreResult<Self>
where
Self: Sized,
{
IgnoreResult::new(self)
}
fn map_output<MapFn>(self, map_fn: MapFn) -> output_mapper::OutputMapper<Self, MapFn>
where
Self: Sized,
{
output_mapper::OutputMapper::new(self, map_fn)
}
fn erase_types<'src, Inp, Out>(self) -> erase_types::Erased<'src, 'src, Inp, Out>
where
Self: Sized + Parser<'src, Inp, Output = Out> + 'src,
Inp: Input<'src> + 'src,
Out: 'src,
{
erase_types::erase(self)
}
}
impl<'src, Inp: Input<'src>, P> Parser<'src, Inp> for P where
P: internal::ParserImpl<'src, Inp> + 'src
{
}
pub(crate) trait ParserObjSafe<'src, Inp: Input<'src>, Output>: std::fmt::Debug {
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: ErrorHandlerChoice<'_>,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Output>, MatcherRunError>;
fn maybe_label(&self) -> Option<Box<dyn std::fmt::Display>>;
fn clone_boxed<'a>(&self) -> Box<dyn ParserObjSafe<'src, Inp, Output> + 'a>
where
Self: 'a;
}
impl<'src, Inp: Input<'src>, Output, P> ParserObjSafe<'src, Inp, Output> for P
where
P: internal::ParserImpl<'src, Inp, Output = Output>,
{
#[inline]
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: ErrorHandlerChoice<'_>,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Output>, MatcherRunError> {
match error_handler {
ErrorHandlerChoice::Empty(handler) => self.parse(context, handler, input),
ErrorHandlerChoice::Multi(handler) => self.parse(context, handler, input),
}
}
#[inline]
fn maybe_label(&self) -> Option<Box<dyn std::fmt::Display>> {
<Self as internal::ParserImpl<'src, Inp>>::maybe_label(self)
}
fn clone_boxed<'a>(&self) -> Box<dyn ParserObjSafe<'src, Inp, Output> + 'a>
where
Self: 'a,
{
Box::new(self.clone())
}
}
impl<Inner> ParserCombinator for &Inner where Inner: ParserCombinator {}
impl<'src, Inner, Inp: Input<'src>> internal::ParserImpl<'src, Inp> for &Inner
where
Inner: Parser<'src, Inp>,
{
type Output = <Inner as internal::ParserImpl<'src, Inp>>::Output;
const CAN_FAIL: bool = Inner::CAN_FAIL;
#[inline]
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: &mut impl ErrorHandler,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Self::Output>, MatcherRunError> {
(**self).parse(context, error_handler, input)
}
#[inline]
fn maybe_label(&self) -> Option<Box<dyn std::fmt::Display>> {
(**self).maybe_label()
}
}
impl<Inner> ParserCombinator for Rc<Inner> where Inner: ParserCombinator {}
impl<'src, Inner, Inp: Input<'src>> internal::ParserImpl<'src, Inp> for Rc<Inner>
where
Inner: Parser<'src, Inp>,
{
type Output = <Inner as internal::ParserImpl<'src, Inp>>::Output;
const CAN_FAIL: bool = Inner::CAN_FAIL;
#[inline]
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: &mut impl ErrorHandler,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Self::Output>, MatcherRunError> {
(**self).parse(context, error_handler, input)
}
#[inline]
fn maybe_label(&self) -> Option<Box<dyn std::fmt::Display>> {
(**self).maybe_label()
}
}
impl<Inner> ParserCombinator for Box<Inner> where Inner: ParserCombinator {}
impl<'src, Inner, Inp: Input<'src>> internal::ParserImpl<'src, Inp> for Box<Inner>
where
Inner: Parser<'src, Inp>,
{
type Output = <Inner as internal::ParserImpl<'src, Inp>>::Output;
const CAN_FAIL: bool = Inner::CAN_FAIL;
#[inline]
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: &mut impl ErrorHandler,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Self::Output>, MatcherRunError> {
(**self).parse(context, error_handler, input)
}
#[inline]
fn maybe_label(&self) -> Option<Box<dyn std::fmt::Display>> {
(**self).maybe_label()
}
}