Skip to content

Instantly share code, notes, and snippets.

@Plecra
Created May 9, 2020 21:37
Show Gist options
  • Save Plecra/2412e8871d624fa9d3e654dde656107a to your computer and use it in GitHub Desktop.
Save Plecra/2412e8871d624fa9d3e654dde656107a to your computer and use it in GitHub Desktop.
Annotate your nom inputs to use complete parsers
use error::*;
use nom::*;
#[derive(Debug, Clone)]
struct Complete<T>(T);
impl<T> Complete<T> {
fn into_inner(self) -> T {
self.0
}
}
impl<T: InputLength> InputLength for Complete<T> {
fn input_len(&self) -> usize {
self.0.input_len()
}
}
impl<T: Offset> Offset for Complete<T> {
fn offset(&self, second: &Self) -> usize {
self.0.offset(&second.0)
}
}
impl<T: AsBytes> AsBytes for Complete<T> {
fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
}
impl<T: InputIter> InputIter for Complete<T> {
type Item = T::Item;
type Iter = T::Iter;
type IterElem = T::IterElem;
fn iter_indices(&self) -> Self::Iter {
self.0.iter_indices()
}
fn iter_elements(&self) -> Self::IterElem {
self.0.iter_elements()
}
fn position<P>(&self, predicate: P) -> Option<usize>
where
P: Fn(Self::Item) -> bool,
{
self.0.position(predicate)
}
fn slice_index(&self, count: usize) -> Option<usize> {
self.0.slice_index(count)
}
}
impl<T: InputTake> InputTake for Complete<T> {
fn take(&self, count: usize) -> Self {
Self(self.0.take(count))
}
fn take_split(&self, count: usize) -> (Self, Self) {
let (start, end) = self.0.take_split(count);
(Self(start), Self(end))
}
}
struct CompleteParseError<E>(E);
impl<I, E: ParseError<Complete<I>>> ParseError<I> for CompleteParseError<E> {
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
Self(E::from_error_kind(Complete(input), kind))
}
fn append(input: I, kind: ErrorKind, other: Self) -> Self {
Self(E::append(Complete(input), kind, other.0))
}
fn from_char(input: I, c: char) -> Self {
Self(E::from_char(Complete(input), c))
}
fn or(self, other: Self) -> Self {
Self(self.0.or(other.0))
}
}
impl<T: InputTakeAtPosition> InputTakeAtPosition for Complete<T> {
type Item = T::Item;
fn split_at_position<P, E: ParseError<Self>>(&self, predicate: P) -> IResult<Self, Self, E>
where
P: Fn(Self::Item) -> bool,
{
self.split_at_position_complete(predicate)
}
fn split_at_position1<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind,
) -> IResult<Self, Self, E>
where
P: Fn(Self::Item) -> bool,
{
self.split_at_position1_complete(predicate, e)
}
fn split_at_position_complete<P, E: ParseError<Self>>(
&self,
predicate: P,
) -> IResult<Self, Self, E>
where
P: Fn(Self::Item) -> bool,
{
match self
.0
.split_at_position_complete::<_, CompleteParseError<E>>(predicate)
{
Ok((remaining, found)) => Ok((Self(remaining), Self(found))),
Err(Err::Error(e)) => Err(Err::Error(e.0)),
Err(Err::Failure(e)) => Err(Err::Failure(e.0)),
Err(Err::Incomplete(needed)) => Err(Err::Incomplete(needed)),
}
}
fn split_at_position1_complete<P, E: ParseError<Self>>(
&self,
predicate: P,
e: ErrorKind,
) -> IResult<Self, Self, E>
where
P: Fn(Self::Item) -> bool,
{
match self
.0
.split_at_position1_complete::<_, CompleteParseError<E>>(predicate, e)
{
Ok((remaining, found)) => Ok((Self(remaining), Self(found))),
Err(Err::Error(e)) => Err(Err::Error(e.0)),
Err(Err::Failure(e)) => Err(Err::Failure(e.0)),
Err(Err::Incomplete(needed)) => Err(Err::Incomplete(needed)),
}
}
}
impl<T: Compare<O>, O> Compare<O> for Complete<T> {
fn compare(&self, t: O) -> CompareResult {
match self.0.compare(t) {
CompareResult::Incomplete => CompareResult::Error,
res => res,
}
}
fn compare_no_case(&self, t: O) -> CompareResult {
match self.0.compare_no_case(t) {
CompareResult::Incomplete => CompareResult::Error,
res => res,
}
}
}
impl<T: FindToken<O>, O> FindToken<O> for Complete<T> {
fn find_token(&self, token: O) -> bool {
self.0.find_token(token)
}
}
impl<T: FindSubstring<O>, O> FindSubstring<O> for Complete<T> {
fn find_substring(&self, substr: O) -> Option<usize> {
self.0.find_substring(substr)
}
}
impl<T: ParseTo<R>, R> ParseTo<R> for Complete<T> {
fn parse_to(&self) -> Option<R> {
self.0.parse_to()
}
}
impl<T: Slice<R>, R> Slice<R> for Complete<T> {
fn slice(&self, range: R) -> Self {
Self(self.0.slice(range))
}
}
impl<T: ExtendInto> ExtendInto for Complete<T> {
type Item = T::Item;
type Extender = T::Extender;
fn new_builder(&self) -> Self::Extender {
self.0.new_builder()
}
fn extend_into(&self, acc: &mut Self::Extender) {
self.0.extend_into(acc)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment