Skip to content

Commit

Permalink
parser: simplify ErrorContext construction
Browse files Browse the repository at this point in the history
  • Loading branch information
djc committed May 21, 2024
1 parent c3582f5 commit 627d58b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 73 deletions.
21 changes: 8 additions & 13 deletions askama_parser/src/expr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::str;

Expand Down Expand Up @@ -111,12 +110,10 @@ impl<'a> Expr<'a> {
move |i| Self::parse(i, level),
))(i)?;
if has_named_arguments && !matches!(expr, Self::NamedArgument(_, _)) {
Err(nom::Err::Failure(ErrorContext {
input: start,
message: Some(Cow::Borrowed(
"named arguments must always be passed last",
)),
}))
Err(nom::Err::Failure(ErrorContext::new(
"named arguments must always be passed last",
start,
)))
} else {
Ok((i, expr))
}
Expand Down Expand Up @@ -146,12 +143,10 @@ impl<'a> Expr<'a> {
if named_arguments.insert(argument) {
Ok((i, Self::NamedArgument(argument, Box::new(value))))
} else {
Err(nom::Err::Failure(ErrorContext {
input: start,
message: Some(Cow::Owned(format!(
"named argument `{argument}` was passed more than once"
))),
}))
Err(nom::Err::Failure(ErrorContext::new(
format!("named argument `{argument}` was passed more than once"),
start,
)))
}
}

Expand Down
38 changes: 19 additions & 19 deletions askama_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,13 @@ pub(crate) struct ErrorContext<'a> {

impl<'a> ErrorContext<'a> {
fn unclosed(kind: &str, tag: &str, i: &'a str) -> Self {
Self::new(format!("unclosed {kind}, missing {tag:?}"), i)
}

fn new(message: impl Into<Cow<'static, str>>, input: &'a str) -> Self {
Self {
input: i,
message: Some(Cow::Owned(format!("unclosed {kind}, missing {tag:?}"))),
input,
message: Some(message.into()),
}
}

Expand Down Expand Up @@ -373,19 +377,20 @@ fn char_lit(i: &str) -> ParseResult<'_> {
opt(escaped(is_not("\\\'"), '\\', anychar)),
char('\''),
)(i)?;

let Some(s) = s else {
return Err(nom::Err::Failure(ErrorContext {
input: start,
// Same error as rustc.
message: Some(Cow::Borrowed("empty character literal")),
}));
return Err(nom::Err::Failure(ErrorContext::new(
"empty character literal",
start,
)));
};
let Ok(("", c)) = Char::parse(s) else {
return Err(nom::Err::Failure(ErrorContext {
input: start,
message: Some(Cow::Borrowed("invalid character")),
}));
return Err(nom::Err::Failure(ErrorContext::new(
"invalid character",
start,
)));
};

let (nb, max_value, err1, err2) = match c {
Char::Literal | Char::Escaped => return Ok((i, s)),
Char::AsciiEscape(nb) => (
Expand All @@ -405,17 +410,12 @@ fn char_lit(i: &str) -> ParseResult<'_> {
};

let Ok(nb) = u32::from_str_radix(nb, 16) else {
return Err(nom::Err::Failure(ErrorContext {
input: start,
message: Some(Cow::Borrowed(err1)),
}));
return Err(nom::Err::Failure(ErrorContext::new(err1, start)));
};
if nb > max_value {
return Err(nom::Err::Failure(ErrorContext {
input: start,
message: Some(Cow::Borrowed(err2)),
}));
return Err(nom::Err::Failure(ErrorContext::new(err2, start)));
}

Ok((i, s))
}

Expand Down
76 changes: 35 additions & 41 deletions askama_parser/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::borrow::Cow;
use std::str;

use nom::branch::alt;
Expand Down Expand Up @@ -113,10 +112,10 @@ impl<'a> Node<'a> {
));
let (j, (pws, _, nws)) = p(i)?;
if !s.is_in_loop() {
return Err(nom::Err::Failure(ErrorContext {
input: i,
message: Some(Cow::Borrowed("you can only `break` inside a `for` loop")),
}));
return Err(nom::Err::Failure(ErrorContext::new(
"you can only `break` inside a `for` loop",
i,
)));
}
Ok((j, Self::Break(Ws(pws, nws))))
}
Expand All @@ -129,10 +128,10 @@ impl<'a> Node<'a> {
));
let (j, (pws, _, nws)) = p(i)?;
if !s.is_in_loop() {
return Err(nom::Err::Failure(ErrorContext {
input: i,
message: Some(Cow::Borrowed("you can only `continue` inside a `for` loop")),
}));
return Err(nom::Err::Failure(ErrorContext::new(
"you can only `continue` inside a `for` loop",
i,
)));
}
Ok((j, Self::Continue(Ws(pws, nws))))
}
Expand Down Expand Up @@ -297,10 +296,10 @@ impl<'a> Target<'a> {

fn verify_name(input: &'a str, name: &'a str) -> Result<Self, nom::Err<ErrorContext<'a>>> {
match name {
"self" | "writer" => Err(nom::Err::Failure(ErrorContext {
"self" | "writer" => Err(nom::Err::Failure(ErrorContext::new(
format!("cannot use `{name}` as a name"),
input,
message: Some(Cow::Owned(format!("Cannot use `{name}` as a name"))),
})),
))),
_ => Ok(Self::Name(name)),
}
}
Expand Down Expand Up @@ -375,12 +374,10 @@ impl<'a> Cond<'a> {
opt(Whitespace::parse),
ws(alt((keyword("else"), |i| {
let _ = keyword("elif")(i)?;
Err(nom::Err::Failure(ErrorContext {
input: i,
message: Some(Cow::Borrowed(
"unknown `elif` keyword; did you mean `else if`?",
)),
}))
Err(nom::Err::Failure(ErrorContext::new(
"unknown `elif` keyword; did you mean `else if`?",
i,
)))
}))),
cut(tuple((
opt(|i| CondTest::parse(i, s)),
Expand Down Expand Up @@ -559,10 +556,10 @@ impl<'a> Macro<'a> {
));
let (j, (pws1, _, (name, params, nws1, _))) = start(i)?;
if name == "super" {
return Err(nom::Err::Failure(ErrorContext {
input: i,
message: Some(Cow::Borrowed("'super' is not a valid name for a macro")),
}));
return Err(nom::Err::Failure(ErrorContext::new(
"'super' is not a valid name for a macro",
i,
)));
}

let mut end = cut(tuple((
Expand Down Expand Up @@ -831,15 +828,14 @@ fn check_end_name<'a>(
if name == end_name {
return Ok((after, end_name));
}
let message = if name.is_empty() && !end_name.is_empty() {
format!("unexpected name `{end_name}` in `end{kind}` tag for unnamed `{kind}`")
} else {
format!("expected name `{name}` in `end{kind}` tag, found `{end_name}`")
};
Err(nom::Err::Failure(ErrorContext {
input: before,
message: Some(Cow::Owned(message)),
}))

Err(nom::Err::Failure(ErrorContext::new(
match name.is_empty() && !end_name.is_empty() {
true => format!("unexpected name `{end_name}` in `end{kind}` tag for unnamed `{kind}`"),
false => format!("expected name `{name}` in `end{kind}` tag, found `{end_name}`"),
},
before,
)))
}

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -1036,12 +1032,10 @@ impl<'a> Extends<'a> {
))(i)?;
match (pws, nws) {
(None, None) => Ok((i, Self { path })),
(_, _) => Err(nom::Err::Failure(ErrorContext {
input: start,
message: Some(Cow::Borrowed(
"whitespace control is not allowed on `extends`",
)),
})),
(_, _) => Err(nom::Err::Failure(ErrorContext::new(
"whitespace control is not allowed on `extends`",
start,
))),
}
}
}
Expand Down Expand Up @@ -1078,10 +1072,10 @@ impl<'a> Comment<'a> {
Tag::Open => match depth.checked_add(1) {
Some(new_depth) => depth = new_depth,
None => {
return Err(nom::Err::Failure(ErrorContext {
input: i,
message: Some(Cow::Borrowed("too deeply nested comments")),
}))
return Err(nom::Err::Failure(ErrorContext::new(
"too deeply nested comments",
i,
)));
}
},
Tag::Close => match depth.checked_sub(1) {
Expand Down

0 comments on commit 627d58b

Please sign in to comment.