Skip to content

Commit 586306f

Browse files
committed
feat(path): Improve error messages for path parser
1 parent 6e4d39d commit 586306f

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

src/path/parser.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ use std::str::FromStr;
22

33
use winnow::ascii::digit1;
44
use winnow::ascii::space0;
5+
use winnow::combinator::cut_err;
56
use winnow::combinator::dispatch;
6-
use winnow::combinator::eof;
77
use winnow::combinator::fail;
88
use winnow::combinator::opt;
99
use winnow::combinator::repeat;
1010
use winnow::combinator::seq;
1111
use winnow::error::ContextError;
12+
use winnow::error::StrContext;
13+
use winnow::error::StrContextValue;
1214
use winnow::prelude::*;
1315
use winnow::token::any;
1416
use winnow::token::take_while;
@@ -17,7 +19,7 @@ use crate::path::Expression;
1719

1820
pub(crate) fn from_str(mut input: &str) -> Result<Expression, ContextError> {
1921
let input = &mut input;
20-
path(input).map_err(|e| e.into_inner().unwrap())
22+
path.parse(input).map_err(|e| e.into_inner())
2123
}
2224

2325
fn path(i: &mut &str) -> PResult<Expression> {
@@ -31,7 +33,6 @@ fn path(i: &mut &str) -> PResult<Expression> {
3133
},
3234
)
3335
.parse_next(i)?;
34-
eof.parse_next(i)?;
3536
Ok(expr)
3637
}
3738

@@ -41,9 +42,21 @@ fn ident(i: &mut &str) -> PResult<Expression> {
4142

4243
fn postfix(i: &mut &str) -> PResult<Child> {
4344
dispatch! {any;
44-
'[' => seq!(integer.map(Child::Index), _: ']').map(|(i,)| i),
45-
'.' => raw_ident.map(Child::Key),
46-
_ => fail,
45+
'[' => cut_err(
46+
seq!(
47+
integer.map(Child::Index),
48+
_: ']'.context(StrContext::Expected(StrContextValue::CharLiteral(']'))),
49+
)
50+
.map(|(i,)| i)
51+
.context(StrContext::Label("subscript"))
52+
),
53+
'.' => cut_err(raw_ident.map(Child::Key)),
54+
_ => cut_err(
55+
fail
56+
.context(StrContext::Label("postfix"))
57+
.context(StrContext::Expected(StrContextValue::CharLiteral('[')))
58+
.context(StrContext::Expected(StrContextValue::CharLiteral('.')))
59+
),
4760
}
4861
.parse_next(i)
4962
}
@@ -56,6 +69,12 @@ enum Child {
5669
fn raw_ident(i: &mut &str) -> PResult<String> {
5770
take_while(1.., ('a'..='z', 'A'..='Z', '0'..='9', '_', '-'))
5871
.map(ToString::to_string)
72+
.context(StrContext::Label("identifier"))
73+
.context(StrContext::Expected(StrContextValue::Description(
74+
"ASCII alphanumeric",
75+
)))
76+
.context(StrContext::Expected(StrContextValue::CharLiteral('_')))
77+
.context(StrContext::Expected(StrContextValue::CharLiteral('-')))
5978
.parse_next(i)
6079
}
6180

@@ -65,6 +84,9 @@ fn integer(i: &mut &str) -> PResult<isize> {
6584
(opt('-'), digit1).take().try_map(FromStr::from_str),
6685
_: space0
6786
)
87+
.context(StrContext::Expected(StrContextValue::Description(
88+
"integer",
89+
)))
6890
.map(|(i,)| i)
6991
.parse_next(i)
7092
}
@@ -121,30 +143,36 @@ mod test {
121143
#[test]
122144
fn test_invalid_identifier() {
123145
let err = from_str("!").unwrap_err();
124-
assert_eq!("", err.to_string());
146+
assert_eq!(
147+
"invalid identifier\nexpected ASCII alphanumeric, `_`, `-`",
148+
err.to_string()
149+
);
125150
}
126151

127152
#[test]
128153
fn test_invalid_child() {
129154
let err = from_str("a..").unwrap_err();
130-
assert_eq!("", err.to_string());
155+
assert_eq!(
156+
"invalid identifier\nexpected ASCII alphanumeric, `_`, `-`",
157+
err.to_string()
158+
);
131159
}
132160

133161
#[test]
134162
fn test_invalid_subscript() {
135163
let err = from_str("a[b]").unwrap_err();
136-
assert_eq!("", err.to_string());
164+
assert_eq!("invalid subscript\nexpected integer", err.to_string());
137165
}
138166

139167
#[test]
140168
fn test_incomplete_subscript() {
141169
let err = from_str("a[0").unwrap_err();
142-
assert_eq!("", err.to_string());
170+
assert_eq!("invalid subscript\nexpected `]`", err.to_string());
143171
}
144172

145173
#[test]
146174
fn test_invalid_postfix() {
147175
let err = from_str("a!b").unwrap_err();
148-
assert_eq!("", err.to_string());
176+
assert_eq!("invalid postfix\nexpected `[`, `.`", err.to_string());
149177
}
150178
}

0 commit comments

Comments
 (0)