`parse!` does not support inline `map`, `map_err` or `bind` for named actions
Closed this issue · 3 comments
Problem
The parse!
macro does not allow anything but a standard function call as a named action in its grammar:
NAMED_ACTION = $ident '(' ($expr ',')* ','? ')'
It is desirable to be able to write code like this:
fn make_it_cool(n: u32) -> u32 { n + 2 }
fn validate_number<I>(i: Input<I>, n: u32) -> ParseResult<I, u32, NumberError> {
if n == 10 { i.ret(n) } else { i.err(NumberError) }
}
parse!{i;
let x = decimal().map(make_it_cool);
let y = decimal().bind(validate_number);
ret x + y
}
Possible solutions
Explicitly add bind
, map
and map_err
to the grammar
This will enable the syntax above, but only for bind
, map
and map_err
it will not enable any method to be called on the return value of the called function. This comes at the price of a much more complex macro for the actions part because of the explicit parts of the grammar.
Do nothing and instruct people to use the inline-action form
// using the same functions from above
parse!{i;
let x = i -> decimal(i).map(make_it_cool);
let x = i -> decimal(i).bind(validate_number);
ret x + y
}
Drawbacks:
- The
Input<I>
type gets exposed needlessly inside of the macro - More characters to write for the user
TODO: Any more possible solutions?
I ran into this several times too.
Ah... so that's how the inline action works. I saw documentation of the syntax, but nothing about how it works. Did I miss some documentation?
Adding support for bind
, map
and map_err
will cause needless complexity in the parse!
macro as it looks right now. map
can be implemented by using let x = ...; ret ...
for simple cases.