Skip to content

Commit

Permalink
Merge pull request #712 from epage/modal
Browse files Browse the repository at this point in the history
fix!: Make ErrMode optional by using Result
  • Loading branch information
epage authored Jan 24, 2025
2 parents b9172d7 + 1550ff3 commit 8876c0a
Show file tree
Hide file tree
Showing 64 changed files with 1,412 additions and 1,172 deletions.
10 changes: 5 additions & 5 deletions benches/contains_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn contains_token(c: &mut criterion::Criterion) {
group.finish();
}

fn parser_slice(input: &mut &str) -> PResult<usize> {
fn parser_slice(input: &mut &str) -> ModalResult<usize> {
let contains = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'][..];
repeat(
0..,
Expand All @@ -59,7 +59,7 @@ fn parser_slice(input: &mut &str) -> PResult<usize> {
.parse_next(input)
}

fn parser_array(input: &mut &str) -> PResult<usize> {
fn parser_array(input: &mut &str) -> ModalResult<usize> {
let contains = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
repeat(
0..,
Expand All @@ -68,7 +68,7 @@ fn parser_array(input: &mut &str) -> PResult<usize> {
.parse_next(input)
}

fn parser_tuple(input: &mut &str) -> PResult<usize> {
fn parser_tuple(input: &mut &str) -> ModalResult<usize> {
let contains = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
repeat(
0..,
Expand All @@ -77,7 +77,7 @@ fn parser_tuple(input: &mut &str) -> PResult<usize> {
.parse_next(input)
}

fn parser_closure_or(input: &mut &str) -> PResult<usize> {
fn parser_closure_or(input: &mut &str) -> ModalResult<usize> {
let contains = |c: char| {
c == '0'
|| c == '1'
Expand All @@ -97,7 +97,7 @@ fn parser_closure_or(input: &mut &str) -> PResult<usize> {
.parse_next(input)
}

fn parser_closure_matches(input: &mut &str) -> PResult<usize> {
fn parser_closure_matches(input: &mut &str) -> ModalResult<usize> {
let contains = |c: char| matches!(c, '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9');
repeat(
0..,
Expand Down
4 changes: 2 additions & 2 deletions benches/find_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ fn find_slice(c: &mut criterion::Criterion) {
group.finish();
}

fn parser_byte(input: &mut &str) -> PResult<usize> {
fn parser_byte(input: &mut &str) -> ModalResult<usize> {
repeat(0.., (take_until(0.., "\r"), "\r")).parse_next(input)
}

fn parser_slice(input: &mut &str) -> PResult<usize> {
fn parser_slice(input: &mut &str) -> ModalResult<usize> {
repeat(0.., (take_until(0.., "\r\n"), "\r\n")).parse_next(input)
}

Expand Down
10 changes: 5 additions & 5 deletions benches/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn iter(c: &mut criterion::Criterion) {
group.finish();
}

fn iterate(input: &mut &[u8]) -> PResult<usize> {
fn iterate(input: &mut &[u8]) -> ModalResult<usize> {
let mut count = 0;
for byte in input.iter() {
if byte.is_dec_digit() {
Expand All @@ -62,7 +62,7 @@ fn iterate(input: &mut &[u8]) -> PResult<usize> {
Ok(count)
}

fn next_token(input: &mut &[u8]) -> PResult<usize> {
fn next_token(input: &mut &[u8]) -> ModalResult<usize> {
let mut count = 0;
while let Some(byte) = input.next_token() {
if byte.is_dec_digit() {
Expand All @@ -72,7 +72,7 @@ fn next_token(input: &mut &[u8]) -> PResult<usize> {
Ok(count)
}

fn opt_one_of(input: &mut &[u8]) -> PResult<usize> {
fn opt_one_of(input: &mut &[u8]) -> ModalResult<usize> {
let mut count = 0;
while !input.is_empty() {
while opt(one_of(AsChar::is_dec_digit))
Expand All @@ -89,7 +89,7 @@ fn opt_one_of(input: &mut &[u8]) -> PResult<usize> {
Ok(count)
}

fn take_while(input: &mut &[u8]) -> PResult<usize> {
fn take_while(input: &mut &[u8]) -> ModalResult<usize> {
let mut count = 0;
while !input.is_empty() {
count += winnow::token::take_while(0.., AsChar::is_dec_digit)
Expand All @@ -100,7 +100,7 @@ fn take_while(input: &mut &[u8]) -> PResult<usize> {
Ok(count)
}

fn repeat(input: &mut &[u8]) -> PResult<usize> {
fn repeat(input: &mut &[u8]) -> ModalResult<usize> {
let mut count = 0;
while !input.is_empty() {
count += winnow::combinator::repeat(0.., one_of(AsChar::is_dec_digit))
Expand Down
20 changes: 10 additions & 10 deletions benches/next_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,43 +89,43 @@ fn next_slice(c: &mut criterion::Criterion) {
group.finish();
}

fn parser_ascii_char(input: &mut &str) -> PResult<usize> {
fn parser_ascii_char(input: &mut &str) -> ModalResult<usize> {
repeat(0.., 'h').parse_next(input)
}

fn parser_ascii_str(input: &mut &str) -> PResult<usize> {
fn parser_ascii_str(input: &mut &str) -> ModalResult<usize> {
repeat(0.., "h").parse_next(input)
}

fn parser_ascii_one_of(input: &mut &str) -> PResult<usize> {
fn parser_ascii_one_of(input: &mut &str) -> ModalResult<usize> {
repeat(0.., one_of('h')).parse_next(input)
}

fn parser_ascii_tag_char(input: &mut &str) -> PResult<usize> {
fn parser_ascii_tag_char(input: &mut &str) -> ModalResult<usize> {
repeat(0.., literal('h')).parse_next(input)
}

fn parser_ascii_tag_str(input: &mut &str) -> PResult<usize> {
fn parser_ascii_tag_str(input: &mut &str) -> ModalResult<usize> {
repeat(0.., literal("h")).parse_next(input)
}

fn parser_utf8_char(input: &mut &str) -> PResult<usize> {
fn parser_utf8_char(input: &mut &str) -> ModalResult<usize> {
repeat(0.., '🧑').parse_next(input)
}

fn parser_utf8_str(input: &mut &str) -> PResult<usize> {
fn parser_utf8_str(input: &mut &str) -> ModalResult<usize> {
repeat(0.., "🧑").parse_next(input)
}

fn parser_utf8_one_of(input: &mut &str) -> PResult<usize> {
fn parser_utf8_one_of(input: &mut &str) -> ModalResult<usize> {
repeat(0.., one_of('🧑')).parse_next(input)
}

fn parser_utf8_tag_char(input: &mut &str) -> PResult<usize> {
fn parser_utf8_tag_char(input: &mut &str) -> ModalResult<usize> {
repeat(0.., literal('🧑')).parse_next(input)
}

fn parser_utf8_tag_str(input: &mut &str) -> PResult<usize> {
fn parser_utf8_tag_str(input: &mut &str) -> ModalResult<usize> {
repeat(0.., literal("🧑")).parse_next(input)
}

Expand Down
7 changes: 3 additions & 4 deletions benches/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use criterion::Criterion;

use winnow::ascii::float;
use winnow::binary::be_u64;
use winnow::error::ErrMode;
use winnow::error::ErrorKind;
use winnow::error::InputError;
use winnow::error::ParserError;
Expand All @@ -14,7 +13,7 @@ use winnow::stream::ParseSlice;

type Stream<'i> = &'i [u8];

fn parser(i: &mut Stream<'_>) -> PResult<u64> {
fn parser(i: &mut Stream<'_>) -> ModalResult<u64> {
be_u64.parse_next(i)
}

Expand Down Expand Up @@ -49,10 +48,10 @@ fn float_str(c: &mut Criterion) {
});
}

fn std_float(input: &mut &[u8]) -> PResult<f64> {
fn std_float(input: &mut &[u8]) -> ModalResult<f64> {
match input.parse_slice() {
Some(n) => Ok(n),
None => Err(ErrMode::from_error_kind(input, ErrorKind::Slice)),
None => Err(ParserError::from_error_kind(input, ErrorKind::Slice)),
}
}

Expand Down
9 changes: 5 additions & 4 deletions examples/arithmetic/parser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::str::FromStr;

use winnow::prelude::*;
use winnow::Result;
use winnow::{
ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
Expand All @@ -11,7 +12,7 @@ use winnow::{

// Parser definition

pub(crate) fn expr(i: &mut &str) -> PResult<i64> {
pub(crate) fn expr(i: &mut &str) -> Result<i64> {
let init = term.parse_next(i)?;

repeat(0.., (one_of(['+', '-']), term))
Expand All @@ -31,7 +32,7 @@ pub(crate) fn expr(i: &mut &str) -> PResult<i64> {
// We read an initial factor and for each time we find
// a * or / operator followed by another factor, we do
// the math by folding everything
fn term(i: &mut &str) -> PResult<i64> {
fn term(i: &mut &str) -> Result<i64> {
let init = factor.parse_next(i)?;

repeat(0.., (one_of(['*', '/']), factor))
Expand All @@ -52,7 +53,7 @@ fn term(i: &mut &str) -> PResult<i64> {
// We look for a digit suite, and try to convert it.
// If either str::from_utf8 or FromStr::from_str fail,
// we fallback to the parens parser defined above
fn factor(i: &mut &str) -> PResult<i64> {
fn factor(i: &mut &str) -> Result<i64> {
delimited(
multispaces,
alt((digits.try_map(FromStr::from_str), parens)),
Expand All @@ -62,7 +63,7 @@ fn factor(i: &mut &str) -> PResult<i64> {
}

// We parse any expr surrounded by parens, ignoring all whitespace around those
fn parens(i: &mut &str) -> PResult<i64> {
fn parens(i: &mut &str) -> Result<i64> {
delimited('(', expr, ')').parse_next(i)
}

Expand Down
9 changes: 5 additions & 4 deletions examples/arithmetic/parser_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;

use winnow::prelude::*;
use winnow::Result;
use winnow::{
ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
Expand Down Expand Up @@ -49,7 +50,7 @@ impl Display for Expr {
}
}

pub(crate) fn expr(i: &mut &str) -> PResult<Expr> {
pub(crate) fn expr(i: &mut &str) -> Result<Expr> {
let init = term.parse_next(i)?;

repeat(0.., (one_of(['+', '-']), term))
Expand All @@ -66,7 +67,7 @@ pub(crate) fn expr(i: &mut &str) -> PResult<Expr> {
.parse_next(i)
}

fn term(i: &mut &str) -> PResult<Expr> {
fn term(i: &mut &str) -> Result<Expr> {
let init = factor.parse_next(i)?;

repeat(0.., (one_of(['*', '/']), factor))
Expand All @@ -83,7 +84,7 @@ fn term(i: &mut &str) -> PResult<Expr> {
.parse_next(i)
}

fn factor(i: &mut &str) -> PResult<Expr> {
fn factor(i: &mut &str) -> Result<Expr> {
delimited(
multispaces,
alt((digits.try_map(FromStr::from_str).map(Expr::Value), parens)),
Expand All @@ -92,7 +93,7 @@ fn factor(i: &mut &str) -> PResult<Expr> {
.parse_next(i)
}

fn parens(i: &mut &str) -> PResult<Expr> {
fn parens(i: &mut &str) -> Result<Expr> {
delimited("(", expr, ")")
.map(|e| Expr::Paren(Box::new(e)))
.parse_next(i)
Expand Down
15 changes: 8 additions & 7 deletions examples/arithmetic/parser_lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;

use winnow::prelude::*;
use winnow::Result;
use winnow::{
ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
Expand Down Expand Up @@ -98,16 +99,16 @@ impl<const LEN: usize> winnow::stream::ContainsToken<Token> for [Token; LEN] {
}

#[allow(dead_code)]
pub(crate) fn expr2(i: &mut &str) -> PResult<Expr> {
pub(crate) fn expr2(i: &mut &str) -> Result<Expr> {
let tokens = lex.parse_next(i)?;
expr.parse_next(&mut tokens.as_slice())
}

pub(crate) fn lex(i: &mut &str) -> PResult<Vec<Token>> {
pub(crate) fn lex(i: &mut &str) -> Result<Vec<Token>> {
preceded(multispaces, repeat(1.., terminated(token, multispaces))).parse_next(i)
}

fn token(i: &mut &str) -> PResult<Token> {
fn token(i: &mut &str) -> Result<Token> {
dispatch! {peek(any);
'0'..='9' => digits.try_map(FromStr::from_str).map(Token::Value),
'(' => '('.value(Token::OpenParen),
Expand All @@ -121,7 +122,7 @@ fn token(i: &mut &str) -> PResult<Token> {
.parse_next(i)
}

pub(crate) fn expr(i: &mut &[Token]) -> PResult<Expr> {
pub(crate) fn expr(i: &mut &[Token]) -> Result<Expr> {
let init = term.parse_next(i)?;

repeat(
Expand All @@ -144,7 +145,7 @@ pub(crate) fn expr(i: &mut &[Token]) -> PResult<Expr> {
.parse_next(i)
}

fn term(i: &mut &[Token]) -> PResult<Expr> {
fn term(i: &mut &[Token]) -> Result<Expr> {
let init = factor.parse_next(i)?;

repeat(
Expand All @@ -167,7 +168,7 @@ fn term(i: &mut &[Token]) -> PResult<Expr> {
.parse_next(i)
}

fn factor(i: &mut &[Token]) -> PResult<Expr> {
fn factor(i: &mut &[Token]) -> Result<Expr> {
alt((
one_of(|t| matches!(t, Token::Value(_))).map(|t| match t {
Token::Value(v) => Expr::Value(v),
Expand All @@ -178,7 +179,7 @@ fn factor(i: &mut &[Token]) -> PResult<Expr> {
.parse_next(i)
}

fn parens(i: &mut &[Token]) -> PResult<Expr> {
fn parens(i: &mut &[Token]) -> Result<Expr> {
delimited(one_of(Token::OpenParen), expr, one_of(Token::CloseParen))
.map(|e| Expr::Paren(Box::new(e)))
.parse_next(i)
Expand Down
5 changes: 3 additions & 2 deletions examples/css/parser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use winnow::combinator::seq;
use winnow::prelude::*;
use winnow::token::take_while;
use winnow::Result;

#[derive(Debug, Eq, PartialEq)]
pub(crate) struct Color {
Expand All @@ -18,7 +19,7 @@ impl std::str::FromStr for Color {
}
}

pub(crate) fn hex_color(input: &mut &str) -> PResult<Color> {
pub(crate) fn hex_color(input: &mut &str) -> Result<Color> {
seq!(Color {
_: '#',
red: hex_primary,
Expand All @@ -28,7 +29,7 @@ pub(crate) fn hex_color(input: &mut &str) -> PResult<Color> {
.parse_next(input)
}

fn hex_primary(input: &mut &str) -> PResult<u8> {
fn hex_primary(input: &mut &str) -> Result<u8> {
take_while(2, |c: char| c.is_ascii_hexdigit())
.try_map(|input| u8::from_str_radix(input, 16))
.parse_next(input)
Expand Down
8 changes: 7 additions & 1 deletion examples/custom_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ pub enum CustomError<I> {
}

impl<I: Stream + Clone> ParserError<I> for CustomError<I> {
type Inner = Self;

fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
CustomError::Winnow(input.clone(), kind)
}

fn into_inner(self) -> Result<Self::Inner, Self> {
Ok(self)
}
}

impl<C, I: Stream> AddContext<I, C> for CustomError<I> {
Expand Down Expand Up @@ -48,7 +54,7 @@ impl<I: Stream + Clone, E: std::error::Error + Send + Sync + 'static> FromExtern
}
}

pub fn parse<'s>(_input: &mut &'s str) -> PResult<&'s str, CustomError<&'s str>> {
pub fn parse<'s>(_input: &mut &'s str) -> ModalResult<&'s str, CustomError<&'s str>> {
Err(ErrMode::Backtrack(CustomError::MyError))
}

Expand Down
Loading

0 comments on commit 8876c0a

Please sign in to comment.