Skip to content

Commit f25e6a2

Browse files
committed
refactor(path): Port to winnow
1 parent 8db5d3e commit f25e6a2

File tree

4 files changed

+59
-86
lines changed

4 files changed

+59
-86
lines changed

Cargo.lock

Lines changed: 3 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ async = ["async-trait"]
122122

123123
[dependencies]
124124
serde = "1.0"
125-
nom = "7"
126125

127126
async-trait = { version = "0.1", optional = true }
128127
toml = { version = "0.8", optional = true }
@@ -134,6 +133,7 @@ json5_rs = { version = "0.4", optional = true, package = "json5" }
134133
indexmap = { version = "2.2", features = ["serde"], optional = true }
135134
convert_case = { version = "0.6", optional = true }
136135
pathdiff = "0.2"
136+
winnow = "0.6.20"
137137

138138
[dev-dependencies]
139139
serde_derive = "1.0"

src/path/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ impl FromStr for Expression {
2727
struct ParseError(String);
2828

2929
impl ParseError {
30-
fn new(inner: nom::error::ErrorKind) -> Self {
31-
Self(inner.description().to_owned())
30+
fn new(inner: winnow::error::ContextError) -> Self {
31+
Self(inner.to_string())
3232
}
3333
}
3434

src/path/parser.rs

Lines changed: 53 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,72 @@
11
use std::str::FromStr;
22

3-
use nom::{
4-
branch::alt,
5-
bytes::complete::{is_a, tag},
6-
character::complete::{char, digit1, space0},
7-
combinator::{map, map_res, opt, recognize},
8-
error::ErrorKind,
9-
sequence::{delimited, pair, preceded},
10-
Err, IResult,
11-
};
3+
use winnow::ascii::digit1;
4+
use winnow::ascii::space0;
5+
use winnow::combinator::dispatch;
6+
use winnow::combinator::eof;
7+
use winnow::combinator::fail;
8+
use winnow::combinator::opt;
9+
use winnow::combinator::repeat;
10+
use winnow::combinator::seq;
11+
use winnow::error::ContextError;
12+
use winnow::prelude::*;
13+
use winnow::token::any;
14+
use winnow::token::take_while;
1215

1316
use crate::path::Expression;
1417

15-
pub(crate) fn from_str(input: &str) -> Result<Expression, ErrorKind> {
16-
match ident(input) {
17-
Ok((mut rem, mut expr)) => {
18-
while !rem.is_empty() {
19-
match postfix(expr)(rem) {
20-
Ok((rem_, expr_)) => {
21-
rem = rem_;
22-
expr = expr_;
23-
}
24-
25-
// Forward Incomplete and Error
26-
result => {
27-
return result.map(|(_, o)| o).map_err(to_error_kind);
28-
}
29-
}
30-
}
31-
32-
Ok(expr)
33-
}
34-
35-
// Forward Incomplete and Error
36-
result => result.map(|(_, o)| o).map_err(to_error_kind),
37-
}
18+
pub(crate) fn from_str(mut input: &str) -> Result<Expression, ContextError> {
19+
let input = &mut input;
20+
path(input).map_err(|e| e.into_inner().unwrap())
3821
}
3922

40-
fn ident(i: &str) -> IResult<&str, Expression> {
41-
map(raw_ident, Expression::Identifier)(i)
23+
fn path(i: &mut &str) -> PResult<Expression> {
24+
let root = ident.parse_next(i)?;
25+
let expr = repeat(0.., postfix)
26+
.fold(
27+
|| root.clone(),
28+
|prev, cur| match cur {
29+
Child::Key(k) => Expression::Child(Box::new(prev), k),
30+
Child::Index(k) => Expression::Subscript(Box::new(prev), k),
31+
},
32+
)
33+
.parse_next(i)?;
34+
eof.parse_next(i)?;
35+
Ok(expr)
4236
}
4337

44-
fn postfix<'a>(expr: Expression) -> impl FnMut(&'a str) -> IResult<&'a str, Expression> {
45-
let e2 = expr.clone();
46-
let child = map(preceded(tag("."), raw_ident), move |id| {
47-
Expression::Child(Box::new(expr.clone()), id)
48-
});
49-
50-
let subscript = map(delimited(char('['), integer, char(']')), move |num| {
51-
Expression::Subscript(Box::new(e2.clone()), num)
52-
});
38+
fn ident(i: &mut &str) -> PResult<Expression> {
39+
raw_ident.map(Expression::Identifier).parse_next(i)
40+
}
5341

54-
alt((child, subscript))
42+
fn postfix(i: &mut &str) -> PResult<Child> {
43+
dispatch! {any;
44+
'[' => seq!(integer.map(Child::Index), _: ']').map(|(i,)| i),
45+
'.' => raw_ident.map(Child::Key),
46+
_ => fail,
47+
}
48+
.parse_next(i)
5549
}
5650

57-
fn raw_ident(i: &str) -> IResult<&str, String> {
58-
map(
59-
is_a(
60-
"abcdefghijklmnopqrstuvwxyz \
61-
ABCDEFGHIJKLMNOPQRSTUVWXYZ \
62-
0123456789 \
63-
_-",
64-
),
65-
ToString::to_string,
66-
)(i)
51+
enum Child {
52+
Key(String),
53+
Index(isize),
6754
}
6855

69-
fn integer(i: &str) -> IResult<&str, isize> {
70-
map_res(
71-
delimited(space0, recognize(pair(opt(tag("-")), digit1)), space0),
72-
FromStr::from_str,
73-
)(i)
56+
fn raw_ident(i: &mut &str) -> PResult<String> {
57+
take_while(1.., ('a'..='z', 'A'..='Z', '0'..='9', '_', '-'))
58+
.map(ToString::to_string)
59+
.parse_next(i)
7460
}
7561

76-
fn to_error_kind(e: Err<nom::error::Error<&str>>) -> ErrorKind {
77-
match e {
78-
Err::Incomplete(_) => ErrorKind::Complete,
79-
Err::Failure(e) | Err::Error(e) => e.code,
80-
}
62+
fn integer(i: &mut &str) -> PResult<isize> {
63+
seq!(
64+
_: space0,
65+
(opt('-'), digit1).take().try_map(FromStr::from_str),
66+
_: space0
67+
)
68+
.map(|(i,)| i)
69+
.parse_next(i)
8170
}
8271

8372
#[cfg(test)]

0 commit comments

Comments
 (0)