askama icon indicating copy to clipboard operation
askama copied to clipboard

More specific parse errors?

Open dbr opened this issue 4 years ago • 3 comments

I was experimenting with switching a small project from using tera to askama. All went smoothly with one small exception:

The tera templates contained some things like {% if name['test'] %} which in askama has a different syntax of {% if name.test %}

Difference is syntax is not a problem, however to narrow down this as the cause of the error was difficult. For example, with this template

Hello, {{ user.name }}!

{% if user['verified'] %}
Bye
{% endif %]}

..I get the following error:

error: proc-macro derive panicked
 --> src/main.rs:3:10
  |
3 | #[derive(Template)]
  |          ^^^^^^^^
  |
  = help: message: unable to parse template:

          "{% if user[\'verified\'] %}\nBye\n{% endif %]}"

error: aborting due to previous error

While the error does narrow down approximately where the error is, it was not immediately clear what the cause was (especially when the quoted line is much longer - was many lines long in my actual template)

It would be nice if there was a clearer error - even if it just narrowed down to the specific statement ({% if ... %}) instead of the entire contents of the block would be a great improvement (since the contents can be potentially very long), but I suspect this might be harder than it sounds!

dbr avatar Apr 04 '20 01:04 dbr

You can actually sort of assume that the specific {% if ... %} block is causing the problem. Due to how parser combinators work (where in some cases the parser relies on trying different potential parsings in order if earlier ones fail), I think it would be pretty hard to do much better here. I agree that this could use improvements, but I'm unlikely be motivated to work on this anytime soon (unless there was an external motivation). Happy to review a design for an improvement and/or a PR, though!

djc avatar Apr 04 '20 11:04 djc

The error location could be better determined by introducing cuts. E.g.

opt(tag("-")),
ws(tag("for")),
ws(alt((target_single, target_tuple))),
ws(tag("in")),
ws(expr_any),
opt(tag("-")),
|i| tag_block_end(i, s),
|i| parse_template(i, s),
|i| tag_block_start(i, s),
opt(tag("-")),
ws(tag("endfor")),
opt(tag("-")),

opt(tag("-")),
ws(tag("for")),
cut(tuple((
    ws(alt((target_single, target_tuple))),
    ws(tag("in")),
    ws(expr_any),
    opt(tag("-")),
    |i| tag_block_end(i, s),
    cut(tuple((
        |i| parse_template(i, s),
        cut(tuple((
            |i| tag_block_start(i, s),
            opt(tag("-")),
            ws(tag("endfor")),
            opt(tag("-")),
        )))
    )))
)))

Kijewski avatar Jul 01 '21 21:07 Kijewski

@Kijewski sounds interesting. Can you give an example before/after error?

djc avatar Jul 02 '21 15:07 djc

Was fixed in #513.

Kijewski avatar Sep 26 '22 12:09 Kijewski