Skip to content

Commit

Permalink
Skip generating zero-size alt errors, wow much speed
Browse files Browse the repository at this point in the history
  • Loading branch information
zesterer committed Oct 19, 2024
1 parent c9a2b3c commit f91f895
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 17 deletions.
13 changes: 5 additions & 8 deletions src/combinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,10 +823,7 @@ where
let res = self.parser.go::<M>(inp);

if res.is_err() {
inp.memos.insert(
key,
Some(inp.errors.alt.clone().expect("failure but no alt?!")),
);
inp.memos.insert(key, Some(inp.take_alt()));
} else {
inp.memos.remove(&key);
}
Expand Down Expand Up @@ -2593,7 +2590,7 @@ where
let res = self.parser.go::<M>(inp);

if res.is_err() {
let mut e = inp.errors.alt.take().expect("error but no alt?");
let mut e = inp.take_alt();
e.err = (self.mapper)(e.err);
inp.errors.alt = Some(e);
}
Expand Down Expand Up @@ -2627,7 +2624,7 @@ where
// let res = self.parser.go::<M>(inp);

// if res.is_err() {
// let mut e = inp.errors.alt.take().expect("error but no alt?");
// let mut e = inp.take_alt();
// let span = inp.span_since(start);
// e.err = (self.mapper)(e.err, span);
// inp.errors.alt = Some(e);
Expand Down Expand Up @@ -2662,7 +2659,7 @@ where
let res = self.parser.go::<M>(inp);

if res.is_err() {
let mut e = inp.errors.alt.take().expect("error but no alt?");
let mut e = inp.take_alt();
let span = inp.span_since(start);
e.err = (self.mapper)(e.err, span, inp.state());
inp.errors.alt = Some(e);
Expand Down Expand Up @@ -2742,7 +2739,7 @@ where
// match self.parser.go::<M>(inp) {
// Ok(out) => Ok(out),
// Err(()) => {
// let err = inp.errors.alt.take().expect("error but no alt?");
// let err = inp.take_alt();
// match (self.or_else)(err.err) {
// Ok(out) => {
// inp.rewind(before);
Expand Down
20 changes: 18 additions & 2 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ impl<'a, 'parse, I: Input<'a>, E: ParserExtra<'a, I>> InputRef<'a, 'parse, I, E>
pub fn parse<O, P: Parser<'a, I, O, E>>(&mut self, parser: P) -> Result<O, E::Error> {
match parser.go::<Emit>(self) {
Ok(out) => Ok(out),
Err(()) => Err(self.errors.alt.take().expect("error but no alt?").err),
Err(()) => Err(self.take_alt().err),
}
}

Expand All @@ -1268,7 +1268,7 @@ impl<'a, 'parse, I: Input<'a>, E: ParserExtra<'a, I>> InputRef<'a, 'parse, I, E>
pub fn check<O, P: Parser<'a, I, O, E>>(&mut self, parser: P) -> Result<(), E::Error> {
match parser.go::<Check>(self) {
Ok(()) => Ok(()),
Err(()) => Err(self.errors.alt.take().expect("error but no alt?").err),
Err(()) => Err(self.take_alt().err),
}
}

Expand Down Expand Up @@ -1459,6 +1459,9 @@ impl<'a, 'parse, I: Input<'a>, E: ParserExtra<'a, I>> InputRef<'a, 'parse, I, E>
found: Option<MaybeRef<'a, I::Token>>,
span: I::Span,
) {
if core::mem::size_of::<E::Error>() == 0 {
return;
}
// Prioritize errors before choosing whether to generate the alt (avoids unnecessary error creation)
self.errors.alt = Some(match self.errors.alt.take() {
Some(alt) => match alt.pos.into().cmp(&at.into()) {
Expand All @@ -1476,6 +1479,10 @@ impl<'a, 'parse, I: Input<'a>, E: ParserExtra<'a, I>> InputRef<'a, 'parse, I, E>

#[inline]
pub(crate) fn add_alt_err(&mut self, at: I::Offset, err: E::Error) {
if core::mem::size_of::<E::Error>() == 0 {
return;
}

// Prioritize errors
self.errors.alt = Some(match self.errors.alt.take() {
Some(alt) => match alt.pos.into().cmp(&at.into()) {
Expand All @@ -1486,6 +1493,15 @@ impl<'a, 'parse, I: Input<'a>, E: ParserExtra<'a, I>> InputRef<'a, 'parse, I, E>
None => Located::at(at, err),
});
}

// Take the alt error. If one doesn't exist, generate a fake one.
pub(crate) fn take_alt(&mut self) -> Located<I::Offset, E::Error> {
let start = self.offset();
let fake_span = self.span_since(start);
self.errors.alt.take().unwrap_or_else(|| {
Located::at(start.offset, E::Error::expected_found([], None, fake_span))
})
}
}

/// Struct used in [`Parser::validate`] to collect user-emitted errors
Expand Down
12 changes: 8 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,12 +367,12 @@ pub trait Parser<'a, I: Input<'a>, O, E: ParserExtra<'a, I> = extra::Default>:
let mut own = InputOwn::new_state(input, state);
let mut inp = own.as_ref_start();
let res = self.then_ignore(end()).go::<Emit>(&mut inp);
let alt = inp.errors.alt.take();
let alt = inp.take_alt();
let mut errs = own.into_errs();
let out = match res {
Ok(out) => Some(out),
Err(()) => {
errs.push(alt.expect("error but no alt?").err);
errs.push(alt.err);
None
}
};
Expand Down Expand Up @@ -412,12 +412,12 @@ pub trait Parser<'a, I: Input<'a>, O, E: ParserExtra<'a, I> = extra::Default>:
let mut own = InputOwn::new_state(input, state);
let mut inp = own.as_ref_start();
let res = self.then_ignore(end()).go::<Check>(&mut inp);
let alt = inp.errors.alt.take();
let alt = inp.take_alt();
let mut errs = own.into_errs();
let out = match res {
Ok(()) => Some(()),
Err(()) => {
errs.push(alt.expect("error but no alt?").err);
errs.push(alt.err);
None
}
};
Expand Down Expand Up @@ -2605,6 +2605,7 @@ where
I: Input<'a>,
E: ParserExtra<'a, I>,
{
#[inline]
fn go<M: Mode>(&self, inp: &mut InputRef<'a, '_, I, E>) -> PResult<M, O> {
M::invoke(&*self.inner, inp)
}
Expand All @@ -2626,6 +2627,7 @@ where
E: ParserExtra<'a, I>,
T: Parser<'a, I, O, E>,
{
#[inline]
fn go<M: Mode>(&self, inp: &mut InputRef<'a, '_, I, E>) -> PResult<M, O>
where
Self: Sized,
Expand All @@ -2642,6 +2644,7 @@ where
E: ParserExtra<'a, I>,
T: Parser<'a, I, O, E>,
{
#[inline]
fn go<M: Mode>(&self, inp: &mut InputRef<'a, '_, I, E>) -> PResult<M, O>
where
Self: Sized,
Expand All @@ -2658,6 +2661,7 @@ where
E: ParserExtra<'a, I>,
T: Parser<'a, I, O, E>,
{
#[inline]
fn go<M: Mode>(&self, inp: &mut InputRef<'a, '_, I, E>) -> PResult<M, O>
where
Self: Sized,
Expand Down
6 changes: 3 additions & 3 deletions src/recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ where
inp: &mut InputRef<'a, '_, I, E>,
_parser: &P,
) -> PResult<M, O> {
let alt = inp.errors.alt.take().expect("error but no alt?");
let alt = inp.take_alt();
let out = match self.0.go::<M>(inp) {
Ok(out) => out,
Err(()) => {
Expand Down Expand Up @@ -108,7 +108,7 @@ where
inp: &mut InputRef<'a, '_, I, E>,
parser: &P,
) -> PResult<M, O> {
let alt = inp.errors.alt.take().expect("error but no alt?");
let alt = inp.take_alt();
loop {
let before = inp.save();
if let Ok(()) = self.until.go::<Check>(inp) {
Expand Down Expand Up @@ -168,7 +168,7 @@ where
inp: &mut InputRef<'a, '_, I, E>,
_parser: &P,
) -> PResult<M, O> {
let alt = inp.errors.alt.take().expect("error but no alt?");
let alt = inp.take_alt();
loop {
let before = inp.save();
if let Ok(()) = self.until.go::<Check>(inp) {
Expand Down

0 comments on commit f91f895

Please sign in to comment.