#![deny(unsafe_code)]
#![deny(clippy::all)]
#![warn(missing_docs)]
use error::LResultExt;
use parse::{alt, eof, whitespace1, Parseable, Parser};
use syn::{punctuated::Punctuated, Label, LitStr, Token};
mod error;
mod locate;
pub mod parse;
pub use error::{ErrFlow, Error, LResult, ParseErr};
pub use locate::Located;
use crate::parse::{many_till, many_until, tag, take_till, take_until, whitespace0};
type CowStr<'a> = std::borrow::Cow<'a, str>;
type Delims<'a> = [&'a str; 2];
#[derive(Clone, Copy)]
pub struct Ctx {
    pub allow_blocks: bool,
    pub allow_extends: bool,
}
impl Ctx {
    pub const fn allow() -> Self {
        Self {
            allow_blocks: true,
            allow_extends: true,
        }
    }
    pub const fn block_only() -> Self {
        Self {
            allow_blocks: true,
            allow_extends: false,
        }
    }
    pub const fn deny() -> Self {
        Self {
            allow_blocks: false,
            allow_extends: false,
        }
    }
}
const EXPECT_END_MSG: &str = "expected closing {% end %} expression";
fn parse_delimited<'i>(delims: Delims<'i>) -> impl FnMut(Located<'i>) -> LResult<'i, Located<'i>> {
    fn parse_string(input: Located) -> LResult<()> {
        fn update_err<'a>(e: Error<'a>, s: Located<'a>) -> Error<'a> {
            e.msg("expected string to close within an expression")
                .label("string opened here")
                .span(s)
        }
        alt((
            tag("\"")
                .and_then(|rem, t| {
                    take_till(tag("\""))(rem).map_err_incomplete(|e| update_err(e, t))
                })
                .map(|_| ()),
            tag("r\"")
                .and_then(|rem, t| {
                    take_till(tag("\""))(rem).map_err_incomplete(|e| update_err(e, t))
                })
                .map(|_| ()),
            tag("r")
                .and_then(|rem, t| {
                    many_till(tag("#"), tag("\""))(rem).map(|(rem, (p, t2))| (rem, (p, t.join(t2))))
                })
                .and_then(|rem, (pounds, t)| {
                    let pounds = pounds.first().unwrap().join(*pounds.last().unwrap());
                    let (rem, _) = take_till(tag(pounds))(rem)
                        .map_err_incomplete(|e| update_err(e, t))
                        .map_err(ErrFlow::to_unrecoverable)?;
                    LResult::<_, Error>::Ok((rem, ()))
                }),
        ))(input)
    }
    fn string_start(input: Located) -> LResult<()> {
        alt((
            tag("\"").map(|_| ()),
            tag("r\"").map(|_| ()),
            tag("r")
                .and_then(|rem, _| many_till(tag("#"), tag("\""))(rem))
                .map(|_| ()),
        ))(input)
    }
    move |input| {
        let (input, _) = tag(delims[0])(input)?;
        let (mut input, mut inner) =
            take_until(alt((tag(delims[1]).map(|_| ()), string_start)))(input)
                .map_err(ErrFlow::to_unrecoverable)?;
        let mut res = tag(delims[1])(input);
        while let Err(ErrFlow::Backtrack(_)) = res {
            let (next, _) = parse_string(input).map_err(ErrFlow::to_unrecoverable)?;
            let (next, next_inner) =
                take_until(alt((tag(delims[1]).map(|_| ()), string_start)))(next)
                    .map_err(ErrFlow::to_unrecoverable)?;
            inner = inner.join(next_inner);
            input = next;
            res = tag(delims[1])(input)
        }
        match res {
            Ok((rem, _)) => Ok((rem, inner)),
            Err(e) => Err(e),
        }
    }
}
#[derive(Clone, Debug)]
pub enum Expr<'a> {
    Extends(ExtendsExpr),
    Block(BlockExpr<'a>),
    Include(IncludeExpr),
    For(ForExpr<'a>),
    If(IfExpr<'a>),
    Match(MatchExpr<'a>),
    Macro(MacroExpr<'a>),
    CallMacro(CallMacroExpr),
    Stmt(syn::Stmt),
    Expr(syn::Expr),
}
impl<'i> Expr<'i> {
    fn fallback(input: Located<'i>) -> LResult<'i, Self> {
        let _ = tag("{%")(input)
            .map_err(|e| e.msg("expected delim for expresion").span(input.slice(..0)))?;
        let (rem, inner) =
            parse_delimited(["{%", "%}"])(input).map_err(ErrFlow::to_unrecoverable)?;
        if let Ok(stmt) = syn::parse_str(inner.as_ref()) {
            Ok((rem, Expr::Stmt(stmt)))
        } else {
            let expr = syn::parse_str(inner.as_ref())
                .map_err(|err| Error::from_syn(inner, err))
                .map_err(ErrFlow::Unrecoverable)?;
            Ok((rem, Expr::Expr(expr)))
        }
    }
    pub fn parser(ctx: Ctx) -> impl FnMut(Located<'i>) -> LResult<'i, Expr<'i>> {
        move |input| {
            alt((
                ExtendsExpr::parse_next.and_then(move |rem, extends| match ctx.allow_extends {
                    true => Ok((rem, Self::Extends(extends))),
                    false => Err(ErrFlow::Unrecoverable(
                        Error::new("extends expressions not allowed in this context")
                            .span(input.slice(..0)),
                    )),
                }),
                BlockExpr::parse_next.and_then(move |rem, block| match ctx.allow_blocks {
                    true => Ok((rem, Self::Block(block))),
                    false => Err(ErrFlow::Unrecoverable(
                        Error::new("blocks not allowed in this context").span(input.slice(..0)),
                    )),
                }),
                IncludeExpr::parse_next.map(Self::Include),
                ForExpr::parse_next.map(Self::For),
                IfExpr::parse_next.map(Self::If),
                MatchExpr::parse_next.map(Self::Match),
                MacroExpr::parse_next.map(Self::Macro),
                CallMacroExpr::parse_next.map(Self::CallMacro),
                Self::fallback,
            ))(input)
        }
    }
}
#[derive(Clone, Debug)]
pub enum Item<'a> {
    Expr(Expr<'a>),
    Content(CowStr<'a>),
}
impl<'i> Item<'i> {
    pub fn into_owned(self) -> Item<'static> {
        match self {
            Self::Content(c) => Item::Content(c.into_owned().into()),
            Self::Expr(Expr::Extends(e)) => Item::Expr(Expr::Extends(e)),
            Self::Expr(Expr::Include(i)) => Item::Expr(Expr::Include(i)),
            Self::Expr(Expr::Stmt(s)) => Item::Expr(Expr::Stmt(s)),
            Self::Expr(Expr::Expr(e)) => Item::Expr(Expr::Expr(e)),
            Self::Expr(Expr::Block(b)) => Item::Expr(Expr::Block(BlockExpr {
                name: b.name,
                content: b.content.into_iter().map(BlockItem::into_owned).collect(),
            })),
            Self::Expr(Expr::If(i)) => Item::Expr(Expr::If(IfExpr {
                cond: i.cond,
                then: i.then.into_iter().map(Item::into_owned).collect(),
                close: i.close.into_owned(),
            })),
            Self::Expr(Expr::For(f)) => Item::Expr(Expr::For(ForExpr {
                label: f.label,
                pat: f.pat,
                expr: f.expr,
                content: f.content.into_iter().map(Item::into_owned).collect(),
            })),
            Self::Expr(Expr::Match(m)) => Item::Expr(Expr::Match(MatchExpr {
                expr: m.expr,
                arms: m
                    .arms
                    .into_iter()
                    .map(|a| MatchArm {
                        pat: a.pat,
                        guard: a.guard,
                        content: a.content.into_iter().map(Item::into_owned).collect(),
                    })
                    .collect(),
            })),
            Self::Expr(Expr::Macro(m)) => Item::Expr(Expr::Macro(MacroExpr {
                name: m.name,
                args: m.args,
                content: m.content.into_iter().map(Item::into_owned).collect(),
            })),
            Self::Expr(Expr::CallMacro(c)) => Item::Expr(Expr::CallMacro(c)),
        }
    }
}
impl<'i> Item<'i> {
    pub fn parser(ctx: Ctx) -> impl FnMut(Located<'i>) -> LResult<'i, Item<'i>> {
        move |input| match tag("{%")(input) {
            Ok(_) => {
                let (rem, expr) = Expr::parser(ctx)(input)?;
                Ok((rem, Self::Expr(expr)))
            }
            Err(ErrFlow::Backtrack(_)) | Err(ErrFlow::Incomplete(_)) => {
                match take_until(tag("{%"))(input) {
                    Ok((rem, content)) => Ok((rem, Self::Content(content.into()))),
                    Err(ErrFlow::Incomplete(_)) => {
                        Ok((input.slice(input.len()..), Self::Content(input.into())))
                    }
                    Err(e) => Err(e),
                }
            }
            Err(e) => Err(e),
        }
    }
}
#[derive(Clone, Debug)]
pub struct ExtendsExpr {
    pub reference: LitStr,
}
impl<'i> Parseable<'i> for ExtendsExpr {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?;
        let (inner, _) = tag("extends")(inner)
            .map_err(ErrFlow::to_backtrack)?;
        let (inner, _) = whitespace1(inner).map_err(ErrFlow::to_unrecoverable)?;
        let reference = syn::parse_str(inner.as_ref())
            .map_err(|err| Error::from_syn(inner, err))
            .map_err(ErrFlow::Unrecoverable)?;
        Ok((input, Self { reference }))
    }
}
#[derive(Clone, Debug)]
pub struct BlockExpr<'a> {
    pub name: syn::Ident,
    pub content: Vec<BlockItem<'a>>,
}
impl<'i> Parseable<'i> for BlockExpr<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?;
        let (inner, block_tag) = tag("block")(inner)
            .map_err(ErrFlow::to_backtrack)?;
        let (inner, _) = whitespace1(inner).map_err(ErrFlow::to_unrecoverable)?;
        let name = syn::parse_str(inner.as_ref())
            .map_err(|err| Error::from_syn(inner, err))
            .map_err(ErrFlow::Unrecoverable)?;
        let (input, (content, _)) = many_till(BlockItem::parse_next, End::parse_next)(input)
            .map_err_incomplete(|e| e.span(block_tag).msg(EXPECT_END_MSG))
            .map_err(ErrFlow::to_unrecoverable)?;
        Ok((input, Self { name, content }))
    }
}
#[derive(Clone, Debug)]
pub enum BlockItem<'i> {
    Item(Item<'i>),
    SuperCall,
}
impl<'i> BlockItem<'i> {
    pub(crate) fn into_owned(self) -> BlockItem<'static> {
        match self {
            Self::Item(i) => BlockItem::Item(i.into_owned()),
            Self::SuperCall => BlockItem::SuperCall,
        }
    }
}
impl<'i> Parseable<'i> for BlockItem<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self, Error> {
        alt((
            SuperCall::parse_next.map(|_| Self::SuperCall),
            Item::parser(Ctx::block_only()).map(Self::Item),
        ))(input)
    }
}
#[derive(Clone, Debug)]
pub struct SuperCall;
impl<'i> Parseable<'i> for SuperCall {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self, Error> {
        let (input, _) = tag("{%")(input)?;
        let (input, _) = whitespace0(input)?;
        let (input, _) = tag("super()")(input)?;
        let (input, _) = whitespace0(input)?;
        let (input, _) = tag("%}")(input).map_err(ErrFlow::to_unrecoverable)?;
        Ok((input, Self))
    }
}
#[derive(Clone, Debug)]
pub struct IncludeExpr {
    pub includes: LitStr,
}
impl<'i> Parseable<'i> for IncludeExpr {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?;
        let (inner, _) = tag("include")(inner)
            .map_err(ErrFlow::to_backtrack)?;
        let (inner, _) = whitespace1(inner).map_err(ErrFlow::to_unrecoverable)?;
        let includes = syn::parse_str(inner.as_ref())
            .map_err(|err| Error::from_syn(inner, err))
            .map_err(ErrFlow::Unrecoverable)?;
        Ok((input, Self { includes }))
    }
}
#[derive(Clone, Debug)]
pub struct ForExpr<'a> {
    pub label: Option<Label>,
    pub pat: syn::Pat,
    pub expr: syn::Expr,
    pub content: Vec<Item<'a>>,
}
impl<'i> Parseable<'i> for ForExpr<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?; let open: ForOpen = syn::parse_str(inner.as_ref())
            .map_err(|err| Error::from_syn(inner, err))
            .map_err(ErrFlow::Backtrack)?;
        let (input, (content, _)) = many_till(Item::parser(Ctx::deny()), End::parse_next)(input)
            .map_err_incomplete(|e| e.span(inner).msg(EXPECT_END_MSG))
            .map_err(ErrFlow::to_unrecoverable)?;
        Ok((
            input,
            Self {
                label: open.label,
                pat: open.pat,
                expr: open.expr,
                content,
            },
        ))
    }
}
#[derive(Clone, Debug)]
struct ForOpen {
    pub label: Option<Label>,
    #[allow(dead_code)]
    for_token: Token![for],
    pub pat: syn::Pat,
    #[allow(dead_code)]
    in_token: Token![in],
    pub expr: syn::Expr,
}
impl syn::parse::Parse for ForOpen {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Self {
            label: input.parse()?,
            for_token: input.parse()?,
            pat: input.call(syn::Pat::parse_single)?,
            in_token: input.parse()?,
            expr: input.parse()?,
        })
    }
}
#[derive(Clone, Debug)]
pub struct End;
impl<'i> Parseable<'i> for End {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, _) = tag("{%")(input)?;
        let (input, _) = whitespace0(input)?;
        let (input, _) = tag("end")(input)
            .map_err(ErrFlow::to_backtrack)?;
        let (input, _) = whitespace0(input)?;
        let (input, _) = tag("%}")(input).map_err(ErrFlow::to_unrecoverable)?;
        Ok((input, Self))
    }
}
#[derive(Clone, Debug)]
pub struct IfExpr<'a> {
    pub cond: syn::Expr,
    pub then: Vec<Item<'a>>,
    pub close: IfClose<'a>,
}
impl<'i> Parseable<'i> for IfExpr<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self, Error> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?; let open: IfOpen = syn::parse_str(inner.as_ref())
            .map_err(|err| Error::from_syn(inner, err))
            .map_err(ErrFlow::Backtrack)?;
        let (input, (then, close)) =
            many_till(Item::parser(Ctx::deny()), IfClose::parse_next)(input)
                .map_err_incomplete(|e| e.span(inner).msg(EXPECT_END_MSG))
                .map_err(ErrFlow::to_unrecoverable)?;
        Ok((
            input,
            Self {
                cond: open.cond,
                then,
                close,
            },
        ))
    }
}
#[derive(Clone, Debug)]
struct IfOpen {
    #[allow(dead_code)]
    if_token: Token![if],
    pub cond: syn::Expr,
}
impl syn::parse::Parse for IfOpen {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Self {
            if_token: input.parse()?,
            cond: input.parse()?,
        })
    }
}
#[derive(Clone, Debug)]
struct ElseIfOpen {
    #[allow(dead_code)]
    else_token: Token![else],
    #[allow(dead_code)]
    if_token: Token![if],
    pub cond: syn::Expr,
}
impl syn::parse::Parse for ElseIfOpen {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Self {
            else_token: input.parse()?,
            if_token: input.parse()?,
            cond: input.parse()?,
        })
    }
}
#[derive(Clone, Debug)]
pub enum IfClose<'a> {
    Close,
    Else {
        then: Vec<Item<'a>>,
    },
    ElseIf {
        cond: syn::Expr,
        then: Vec<Item<'a>>,
        close: Box<IfClose<'a>>,
    },
}
impl<'i> IfClose<'i> {
    pub(crate) fn into_owned(self) -> IfClose<'static> {
        match self {
            Self::Else { then } => IfClose::Else {
                then: then.into_iter().map(Item::into_owned).collect(),
            },
            Self::ElseIf { cond, then, close } => IfClose::ElseIf {
                cond,
                then: then.into_iter().map(Item::into_owned).collect(),
                close: Box::new(close.into_owned()),
            },
            Self::Close => IfClose::Close,
        }
    }
}
impl<'i> Parseable<'i> for IfClose<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        if let Ok((rem, _)) = End::parse_next(input) {
            return Ok((rem, Self::Close));
        }
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?;
        let (else_if_inner, _) = tag("else")(inner)?; let (else_if_inner, _) = whitespace1(else_if_inner)?;
        if tag::<Error>("if")(else_if_inner).is_ok() {
            let open: ElseIfOpen = syn::parse_str(inner.as_ref())
                .map_err(|err| Error::from_syn(inner, err))
                .map_err(ErrFlow::Unrecoverable)?;
            let (remaining, (then, close)) =
                many_till(Item::parser(Ctx::deny()), Self::parse_next)(input)
                    .map_err_incomplete(|e| e.span(inner).msg(EXPECT_END_MSG))
                    .map_err(ErrFlow::to_unrecoverable)?;
            Ok((
                remaining,
                Self::ElseIf {
                    cond: open.cond,
                    then,
                    close: Box::new(close),
                },
            ))
        } else {
            syn::parse_str::<Token![else]>(inner.as_ref())
                .map_err(|err| Error::from_syn(inner, err))
                .map_err(ErrFlow::Unrecoverable)?;
            let (remaining, (then, _)) =
                many_till(Item::parser(Ctx::deny()), End::parse_next)(input)
                    .map_err_incomplete(|e| e.span(inner))
                    .map_err(ErrFlow::to_unrecoverable)?;
            Ok((remaining, Self::Else { then }))
        }
    }
}
#[derive(Clone, Debug)]
pub struct MatchExpr<'a> {
    pub expr: syn::Expr,
    pub arms: Vec<MatchArm<'a>>,
}
impl<'i> Parseable<'i> for MatchExpr<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (input, _) = whitespace0(input)?;
        let (inner, _) = whitespace0(inner)?; let open: MatchOpen = syn::parse_str(inner.as_ref())
            .map_err(|err| Error::from_syn(inner, err))
            .map_err(ErrFlow::Backtrack)?;
        let (input, (arms, _)) = many_till(MatchArm::parse_next, End::parse_next)(input)
            .map_err_incomplete(|e| e.span(inner).msg(EXPECT_END_MSG))
            .map_err(ErrFlow::to_unrecoverable)?;
        Ok((
            input,
            Self {
                expr: open.expr,
                arms,
            },
        ))
    }
}
#[derive(Clone, Debug)]
struct MatchOpen {
    #[allow(dead_code)]
    match_token: Token![match],
    pub expr: syn::Expr,
}
impl syn::parse::Parse for MatchOpen {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        Ok(Self {
            match_token: input.parse()?,
            expr: input.parse()?,
        })
    }
}
#[derive(Clone, Debug)]
pub struct MatchArm<'a> {
    pub pat: syn::Pat,
    pub guard: Option<syn::Expr>,
    pub content: Vec<Item<'a>>,
}
#[derive(Clone, Debug)]
struct MatchArmOpen {
    pat: syn::Pat,
    guard: Option<(Token![if], syn::Expr)>,
}
impl syn::parse::Parse for MatchArmOpen {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let pat = syn::Pat::parse_multi(input)?;
        if let Ok(if_token) = input.parse() {
            let expr = input.parse()?;
            Ok(Self {
                pat,
                guard: Some((if_token, expr)),
            })
        } else {
            Ok(Self {
                pat,
                guard: None,
            })
        }
    }
}
impl<'i> Parseable<'i> for MatchArm<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self, Error> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?;
        let (inner, _) = tag("when")(inner)?;
        let open: MatchArmOpen = syn::parse_str(inner.as_ref())
        .map_err(|err| Error::from_syn(inner, err))
            .map_err(ErrFlow::Unrecoverable)?;
        let (remaining, content) = many_until(
            Item::parser(Ctx::deny()),
            alt((
                End::parse_next.map(|_| ()),
                MatchArm::parse_next.map(|_| ()),
            )),
        )(input)
        .map_err(ErrFlow::to_unrecoverable)?;
        Ok((remaining, Self {
            pat: open.pat,
            guard: open.guard.map(|g| g.1),
            content
        }))
    }
}
#[derive(Clone, Debug)]
pub struct MacroExpr<'a> {
    pub name: syn::Ident,
    pub args: Punctuated<syn::FnArg, Token![,]>,
    pub content: Vec<Item<'a>>,
}
impl<'i> Parseable<'i> for MacroExpr<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?;
        let (inner, _) = tag("macro")(inner)
            .map_err(ErrFlow::to_backtrack)?;
        let (inner, _) = whitespace1(inner)
            .map_err(|e| e.msg("at least one space required after macro keyword"))
            .map_err(ErrFlow::to_unrecoverable)?;
        let (args, (name, _)) = take_till(tag("("))(inner)
            .map_err(|e| e.msg("expected opening parenthesis for macro arguments"))
            .map_err(ErrFlow::to_unrecoverable)?;
        let name = syn::parse_str(name.as_ref())
            .map_err(|err| Error::from_syn(name, err))
            .map_err(ErrFlow::Unrecoverable)?;
        let (_, (args, _)) = take_till(tag(")"))(args)
            .map_err_incomplete(|e: Error| e.msg("expected ) to end list of arguments"))
            .map_err(ErrFlow::to_unrecoverable)?;
        let arg_parser = Punctuated::<syn::FnArg, Token![,]>::parse_terminated;
        let args = syn::parse::Parser::parse_str(arg_parser, args.as_ref())
            .map_err(|err| Error::from_syn(args, err))
            .map_err(ErrFlow::Unrecoverable)?;
        let (input, (content, _)) = many_till(Item::parser(Ctx::deny()), End::parse_next)(input)
            .map_err_incomplete(|e| e.span(inner).msg(EXPECT_END_MSG))
            .map_err(ErrFlow::to_unrecoverable)?;
        Ok((
            input,
            Self {
                name,
                args,
                content,
            },
        ))
    }
}
#[derive(Clone, Debug)]
pub struct CallMacroExpr {
    pub name: syn::Ident,
    pub args: Punctuated<syn::Expr, Token![,]>,
}
impl<'i> Parseable<'i> for CallMacroExpr {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self, Error> {
        let (input, inner) = parse_delimited(["{%", "%}"])(input)?;
        let (inner, _) = whitespace0(inner)?;
        let (inner, _) = tag("call")(inner)
            .map_err(ErrFlow::to_backtrack)?;
        let (inner, _) = whitespace1(inner)
            .map_err(|e| e.msg("at least one space required after call keyword"))
            .map_err(ErrFlow::to_unrecoverable)?;
        let (args, (name, _)) = take_till(tag("("))(inner)
            .map_err(|e| e.msg("expected opening parenthesis for call arguments"))
            .map_err(ErrFlow::to_unrecoverable)?;
        let name = syn::parse_str(name.as_ref())
            .map_err(|err| Error::from_syn(name, err))
            .map_err(ErrFlow::Unrecoverable)?;
        let (_, (args, _)) = take_till(tag(")"))(args)
            .map_err_incomplete(|e: Error| e.msg("expected ) to end list of arguments"))
            .map_err(ErrFlow::to_unrecoverable)?;
        let arg_parser = Punctuated::parse_terminated;
        let args = syn::parse::Parser::parse_str(arg_parser, args.as_ref())
            .map_err(|err| Error::from_syn(args, err))
            .map_err(ErrFlow::Unrecoverable)?;
        Ok((input, Self { name, args }))
    }
}
#[derive(Clone, Debug)]
pub struct Root<'a> {
    pub content: Vec<Item<'a>>,
}
impl<'i> Root<'i> {
    pub fn into_owned(self) -> Root<'static> {
        let content = self.content.into_iter().map(Item::into_owned).collect();
        Root { content }
    }
}
impl<'i> Root<'i> {
    pub fn parse(input: &'i str) -> Result<Self, Error<'static>> {
        <Root as Parseable>::parse(input).map_err(Error::into_owned)
    }
}
impl<'i> Parseable<'i> for Root<'i> {
    fn parse_next(input: Located<'i>) -> LResult<'i, Self> {
        let (input, _) = whitespace0(input)?;
        let (input, first) = Item::parser(Ctx::allow())(input)?;
        let (input, (content, _)) = many_till(Item::parser(Ctx::block_only()), eof)(input)?;
        let mut v = Vec::with_capacity(content.len() + 1);
        v.push(first);
        v.extend(content);
        Ok((input, Self { content: v }))
    }
}