-
Notifications
You must be signed in to change notification settings - Fork 793
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Thread state through nom combinators #1419
Comments
Additional discussion on the Rust Discourse. |
I'm think you are doing it wrong, a parser should not require an external state like that. That doesn't make sense that if a parser fail it mutate the state. You would mutate the state in the top level parser in function of what your subparser return. I'm opposite to this feature, FnMut already allow state and sharing state between parser in alt is bad design. |
Thanks for responding. I'm not sure exactly how to apply your advice. I'm trying to parse text directly into first-order terms whose symbols are identified with integers. Mutating state as I go along to build a map between symbol names and integer IDs seems like a natural approach that avoids multiple passes through the data. How else would you suggest I solve this problem? |
Unfortunately, I didn't understand much, |
could the mutable state be carried through a |
@Geal - That's basically the solution I've landed on for now. I just wanted to bring up the friction point here in case either:
|
Cause it's become very hard to trace side effect, nom changed parser type for FnMut allowing some mutable state, that generally should be avoided cause... side effect should always be avoided if possible. But here you introduce a share side effect over multiple parser. This mean that in some of your parser inside
Some pseudo code: enum App {
Standard(StandardApp),
Binary(BinaryApp),
}
fn application(state: &HashMap<Id, Foo>) -> impl Parser<&'a str, App> {
|input: &'a str|
alt((
map(|x: &'a str| self.standard_app(state)(x), App::Standard),
map(|x: &'a str| self.binary_app(state)(x), App::Binary),
))(input)
}
fn handle_state(input: &'a str) -> IResult<&'a str, HashMap<Id, Foo>> {
let mut state = HashMap::new();
// use fold or while let or whatever and update the state
while let Ok((input, app)) = application(&state)(input) {
match app {
// do thing like state.entry(id).or_insert_with(app);
}
}
} Probably missed thing but the general idea is here, this have pro & con:
|
there is another very good use case for at least to carry read only data through the parser. Variants. Sometimes complex parsers have "well, accept this but not that for compatibility reasons, leads to bunch of alts driven by an if possibly". Completely stateless parsers are cute, like perfect FSMs. practically speaking, most realistic complex code does extended FSM with state or parsers that are nob'ed for behavior |
a possible solution is to actually implement the whole Input trait zoo for something that is (configuration, &[u8]) e.g. which leads quickly into a nice lifetime hell ;-) But in a sense this is the clean solution to parametrize the parser. |
For state
|
unfortunately 0.0 crate and zero doc.
Having had a quick look I basically implemented the pori Stateful stuff
myself now
…On Mon, Oct 30, 2023 at 1:56 PM Ed Page ***@***.***> wrote:
For state
- nom_locate has an extra field
<https://docs.rs/nom_locate/4.2.0/nom_locate/struct.LocatedSpan.html#structfield.extra>
- pori has the Stateful input decorator
<https://docs.rs/pori/latest/pori/struct.Stateful.html>
—
Reply to this email directly, view it on GitHub
<#1419 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANDIC5BCCJGN5SSP7CTEJDYB6PWDAVCNFSM5FBKA6D2U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCNZYGUYTGNRYGI3Q>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Prerequisites
Here are a few things you should provide to help me understand the issue:
rustc 1.55.0 (c8dfcfe04 2021-09-06)
7.0.0
Test case
I'm updating a parser from nom 4 to nom 7. I'm parsing term rewriting systems, which involves parsing a lot of first-order terms. These first-order terms can contain function symbols and constants, collectively called operators, as well as variables. The identity of each operator and variable is maintained by assigning it a numeric id, and these ids are established while parsing. The parser maintains a map between strings and ids.
In nom 4, I created a parser struct and used combinations of the method! and call_m! macros to build up the id map. In nom 7, these macros no longer exist, nor do corresponding functions.
My first attempt was to translate something like:
into
but the compiler helpfully reminds me that this requires simultaneous unique access to self in both closures.
Perhaps nom could provide the option to fold some sort of mutable state type through the combinators so that I could write:
The text was updated successfully, but these errors were encountered: