use std::{
cell::OnceCell,
rc::{Rc, Weak},
};
use crate::{
context::ParserContext,
error::{MatcherRunError, error_handler::ErrorHandler},
input::{Input, InputStream},
parser::{Parser, ParserCombinator, ParserObjSafe},
};
pub struct Deferred<'a, 'src, Inp, Output> {
parser: Rc<OnceCell<Box<dyn ParserObjSafe<'src, Inp, Output> + 'a>>>,
}
impl<'a, 'src, Inp, Output> Clone for Deferred<'a, 'src, Inp, Output> {
fn clone(&self) -> Self {
Self {
parser: Rc::clone(&self.parser),
}
}
}
impl<'a, 'src, Inp, Output> std::fmt::Debug for Deferred<'a, 'src, Inp, Output> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Deferred").finish()
}
}
impl<'a, 'src, Inp, Output> ParserCombinator for Deferred<'a, 'src, Inp, Output> where
Inp: Input<'src>
{
}
pub struct DeferredWeak<'a, 'src, Inp, Output> {
parser: Weak<OnceCell<Box<dyn ParserObjSafe<'src, Inp, Output> + 'a>>>,
}
impl<'a, 'src, Inp, Output> Clone for DeferredWeak<'a, 'src, Inp, Output> {
fn clone(&self) -> Self {
Self {
parser: self.parser.clone(),
}
}
}
impl<'a, 'src, Inp, Output> std::fmt::Debug for DeferredWeak<'a, 'src, Inp, Output>
where
Inp: Input<'src>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DeferredWeak").finish()
}
}
impl<'a, 'src, Inp, Output> ParserCombinator for DeferredWeak<'a, 'src, Inp, Output> where
Inp: Input<'src>
{
}
impl<'a, 'src, Inp, Output> Deferred<'a, 'src, Inp, Output>
where
Inp: Input<'src>,
{
fn new() -> Self {
Self {
parser: Rc::new(OnceCell::new()),
}
}
fn set_parser<P>(&self, parser: P) -> Result<(), &'static str>
where
P: Parser<'src, Inp, Output = Output> + 'a,
{
self.parser
.set(Box::new(parser))
.map_err(|_| "Parser has already been set")
}
fn clone_weak(&self) -> DeferredWeak<'a, 'src, Inp, Output> {
DeferredWeak {
parser: Rc::downgrade(&self.parser),
}
}
}
impl<'a, 'src, Inp, Output> super::internal::ParserImpl<'src, Inp>
for Deferred<'a, 'src, Inp, Output>
where
Inp: Input<'src> + Clone,
{
type Output = Output;
const CAN_FAIL: bool = true;
#[inline]
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: &mut impl ErrorHandler,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Self::Output>, MatcherRunError> {
if let Some(parser) = self.parser.get() {
parser.parse(context, error_handler.to_choice(), input)
} else {
panic!("Deferred parser was not set before parsing")
}
}
#[inline]
fn maybe_label(&self) -> Option<Box<dyn std::fmt::Display>> {
self.parser.get().and_then(|p| p.maybe_label())
}
}
impl<'a, 'src, Inp, Output> super::internal::ParserImpl<'src, Inp>
for DeferredWeak<'a, 'src, Inp, Output>
where
Inp: Input<'src> + Clone,
{
type Output = Output;
const CAN_FAIL: bool = true;
#[inline]
fn parse(
&self,
context: &mut ParserContext<'src>,
error_handler: &mut impl ErrorHandler,
input: &mut InputStream<'src, Inp>,
) -> Result<Option<Self::Output>, MatcherRunError> {
if let Some(parser) = self.parser.upgrade() {
if let Some(parser) = parser.get() {
parser.parse(context, error_handler.to_choice(), input)
} else {
panic!("Deferred parser was not set before parsing")
}
} else {
panic!("Deferred parser was dropped before parsing")
}
}
#[inline]
fn maybe_label(&self) -> Option<Box<dyn std::fmt::Display>> {
let cell = self.parser.upgrade()?;
cell.get()?.maybe_label()
}
}
pub fn recursive<'src, Inp, Output, F, Pars>(parser_fn: F) -> Deferred<'src, 'src, Inp, Output>
where
Inp: Input<'src>,
F: FnOnce(DeferredWeak<'src, 'src, Inp, Output>) -> Pars,
Pars: Parser<'src, Inp, Output = Output> + 'src,
{
let deferred = Deferred::new();
let parser = parser_fn(deferred.clone_weak());
deferred.set_parser(parser).expect("Failed to set parser");
deferred
}