Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ that you may need. It also has `no_std` support, making it suitable for embedded
- ☑️ **Check-only mode** for fast verification of inputs, automatically supported
- 🚀 **Internal optimiser** leverages the power of [GATs](https://smallcultfollowing.com/babysteps/blog/2022/06/27/many-modes-a-gats-pattern/) to optimise your parser for you
- 📖 **Text-oriented parsers** for text inputs (i.e: `&[u8]` and `&str`)
- 👁️‍🗨️ **Context-free grammars** are fully supported, with support for context-sensitivity
- 👁️ **Context-free grammars** are fully supported, with support for context-sensitivity
- 🔄 **Left recursion and memoization** have opt-in support
- 🪺 **Nested inputs** such as token trees are fully supported both as inputs and outputs
- 🏷️ **Pattern labelling** for dynamic, user-friendly error messages
Expand Down
12 changes: 8 additions & 4 deletions benches/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,14 @@ mod chumsky_zero_copy {
just(b"null").to(JsonZero::Null),
just(b"true").to(JsonZero::Bool(true)),
just(b"false").to(JsonZero::Bool(false)),
number.map(JsonZero::Num),
string.map(JsonZero::Str),
array.map(JsonZero::Array),
object.map(JsonZero::Object),
one_of(b"0123456789-")
.rewind()
.ignore_then(number.map(JsonZero::Num)),
just(b'"').rewind().ignore_then(string.map(JsonZero::Str)),
just(b'[').rewind().ignore_then(array.map(JsonZero::Array)),
just(b'{')
.rewind()
.ignore_then(object.map(JsonZero::Object)),
))
.padded()
})
Expand Down
22 changes: 22 additions & 0 deletions src/combinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ where
}

go_extra!(I::Slice);
could_match!(parser : A);
}

/// See [`Parser::filter`].
Expand Down Expand Up @@ -323,6 +324,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

impl<'src, I, O, E, A, OA, F> IterParser<'src, I, O, E> for Map<A, OA, F>
Expand Down Expand Up @@ -396,6 +398,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

impl<'src, I, O, E, A, OA, F> IterParser<'src, I, O, E> for MapWith<A, OA, F>
Expand Down Expand Up @@ -474,6 +477,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

#[cfg(feature = "nightly")]
Expand Down Expand Up @@ -544,6 +548,7 @@ where
}

go_extra!(I::Span);
could_match!(parser : A);
}

/// See [`Parser::try_foldl`].
Expand Down Expand Up @@ -607,6 +612,7 @@ where
}

go_extra!(OA);
could_match!(parser_a : A);
}

/// See [`Parser::try_map`].
Expand Down Expand Up @@ -779,6 +785,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

/// See [`Parser::into_iter`].
Expand Down Expand Up @@ -812,6 +819,7 @@ where
}

go_extra!(());
could_match!(parser : A);
}

impl<'src, A, O, I, E> IterParser<'src, I, O::Item, E> for IntoIter<A, O>
Expand Down Expand Up @@ -875,6 +883,7 @@ where
}

go_extra!(());
could_match!(parser : A);
}

/// See [`Parser::unwrapped`].
Expand Down Expand Up @@ -1118,6 +1127,7 @@ where
}

go_extra!(OB);
could_match!(parser_a : A);
}

/// See [`Parser::then_ignore`].
Expand Down Expand Up @@ -1154,6 +1164,7 @@ where
}

go_extra!(OA);
could_match!(parser_a : A);
}

/// See [`Parser::nested_in`].
Expand Down Expand Up @@ -1213,6 +1224,7 @@ where
}

go_extra!(O);
could_match!(parser_b : B);
}

/// See [`Parser::ignore_with_ctx`].
Expand Down Expand Up @@ -1250,6 +1262,7 @@ where
}

go_extra!(OB);
could_match!(parser : A);
}

impl<'src, I, E, A, B, OA, OB> IterParser<'src, I, OB, E>
Expand Down Expand Up @@ -1325,6 +1338,7 @@ where
}

go_extra!((OA, OB));
could_match!(parser : A);
}

impl<'src, I, E, A, B, OA, OB> IterParser<'src, I, OB, E>
Expand Down Expand Up @@ -1393,6 +1407,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

/// See [`Parser::with_state`].
Expand Down Expand Up @@ -1424,6 +1439,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

/// See [`Parser::delimited_by`].
Expand Down Expand Up @@ -1464,6 +1480,7 @@ where
}

go_extra!(OA);
could_match!(start : B);
}

/// See [`Parser::padded_by`].
Expand Down Expand Up @@ -1501,6 +1518,7 @@ where
}

go_extra!(OA);
could_match!(padding : B);
}

/// See [`Parser::or`].
Expand Down Expand Up @@ -2773,6 +2791,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

/// See [`Parser::map_err`].
Expand Down Expand Up @@ -2800,6 +2819,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

// /// See [`Parser::map_err_with_span`].
Expand Down Expand Up @@ -2881,6 +2901,7 @@ where
}

go_extra!(O);
could_match!(parser : A);
}

/// See [`Parser::validate`]
Expand Down Expand Up @@ -2926,6 +2947,7 @@ where
}

go_extra!(U);
could_match!(parser : A);
}

// /// See [`Parser::or_else`].
Expand Down
12 changes: 11 additions & 1 deletion src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,17 @@ impl<'p> Seq<'p, &'p Grapheme> for &'p Graphemes {
/// A utility trait to abstract over *linear* container-like things.
///
/// This trait is likely to change in future versions of the crate, so avoid implementing it yourself.
pub trait OrderedSeq<'p, T>: Seq<'p, T> {}
pub trait OrderedSeq<'p, T>: Seq<'p, T> {
#[doc(hidden)]
#[cfg(feature = "nightly")]
#[inline]
fn matches_first(&self, start: &T) -> bool
where
T: PartialEq,
{
self.seq_iter().next().map_or(true, |x| start == x.borrow())
}
}

impl<T: Clone> OrderedSeq<'_, T> for T {}
impl<'p, T> OrderedSeq<'p, T> for &'p T {}
Expand Down
9 changes: 7 additions & 2 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1605,13 +1605,18 @@ impl<'src, 'parse, I: Input<'src>, E: ParserExtra<'src, I>> InputRef<'src, 'pars
self.next_ref_inner()
}

#[inline(always)]
pub(crate) fn peek_maybe_inner(&mut self) -> Option<I::MaybeToken> {
// SAFETY: cursor was generated by previous call to `Input::next`
unsafe { I::next_maybe(self.cache, &mut self.cursor.clone()) }
}

/// Peek the next token in the input. Returns `None` if the end of the input has been reached.
///
/// See [`InputRef::next_maybe`] for more information about what this function guarantees.
#[inline(always)]
pub fn peek_maybe(&mut self) -> Option<MaybeRef<'src, I::Token>> {
// SAFETY: cursor was generated by previous call to `Input::next`
unsafe { I::next_maybe(self.cache, &mut self.cursor.clone()).map(Into::into) }
self.peek_maybe_inner().map(Into::into)
}

/// Peek the next token in the input. Returns `None` if the end of the input has been reached.
Expand Down
44 changes: 43 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg), deny(rustdoc::all))]
#![cfg_attr(
feature = "nightly",
feature(never_type, fn_traits, tuple_trait, unboxed_closures)
feature(
never_type,
fn_traits,
tuple_trait,
unboxed_closures,
associated_type_defaults
)
)]
#![doc = include_str!("../README.md")]
#![deny(missing_docs, clippy::undocumented_unsafe_blocks)]
Expand All @@ -28,6 +34,19 @@ macro_rules! go_extra {
};
}

macro_rules! could_match {
($field:ident : $T:ty) => {
#[cfg(feature = "nightly")]
type Jump = <$T>::Jump;

#[cfg(feature = "nightly")]
#[inline]
fn will_match(&self, start: &I::Token) -> bool {
self.$field.will_match(start)
}
};
}

mod blanket;
#[cfg(feature = "unstable")]
pub mod cache;
Expand Down Expand Up @@ -278,6 +297,16 @@ impl<T, E> ParseResult<T, E> {
}
}

#[doc(hidden)]
pub trait SupportsJump {
const SUPPORTS: bool = false;
}
#[doc(hidden)]
pub struct Jump<const SUPPORTS: bool>;
impl<const SUPPORTS: bool> SupportsJump for Jump<SUPPORTS> {
const SUPPORTS: bool = SUPPORTS;
}

/// A trait implemented by parsers.
///
/// Parsers take inputs of type `I`, which will implement [`Input`]. Refer to the documentation on [`Input`] for examples
Expand Down Expand Up @@ -320,6 +349,19 @@ impl<T, E> ParseResult<T, E> {
// )
// )]
pub trait Parser<'src, I: Input<'src>, O, E: ParserExtra<'src, I> = extra::Default> {
#[doc(hidden)]
#[cfg(feature = "nightly")]
type Jump: SupportsJump
= Jump<false>
where
Self: Sized;

#[doc(hidden)]
#[cfg(feature = "nightly")]
fn will_match(&self, _i: &I::Token) -> bool {
unimplemented!()
}

#[doc(hidden)]
fn go<M: Mode>(&self, inp: &mut InputRef<'src, '_, I, E>) -> PResult<M, O>
where
Expand Down
Loading
Loading