#![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 }))
}
}