diff options
| author | Teddy Wing | 2018-11-03 00:03:40 +0100 |
|---|---|---|
| committer | Teddy Wing | 2018-11-03 00:03:40 +0100 |
| commit | 7776832ec11ee7d4e62cfd2a6ad7735f323ab5bc (patch) | |
| tree | d647d2e64bef898c23fe86ddd8644444e21e6ea8 /src/lib.rs | |
| parent | 75d52e385fa66d6e151c9baa2cf22c2223c39ff0 (diff) | |
| download | dome-key-map-7776832ec11ee7d4e62cfd2a6ad7735f323ab5bc.tar.bz2 | |
parser: Parse `Action::Map`s at the same time as everything else
Was having a hell of a time trying to return a `Result` from
`MapAction::parse()` in 75d52e385fa66d6e151c9baa2cf22c2223c39ff0. After
struggling with it, I started to think if there was a different way to
go about this. Previously I had tried and failed to parse map actions in
the main parser. If I could get that working, then this whole
`MapAction::parse()` method would be obsolete. No need to muss with
`Result`s and borrowed strings at all.
When I originally wrote the parser code, I thought in terms of: "How do
I get the parsed result of the `map()` parser into the `action()` parser
so that it can conditionally parse one way for the `map` keyword, and
another for the `cmd` keyword?". In hindsight, this was incredibly
idiotic, but I guess I was too close to the code and too deep in the
details.
Obviously the answer to parsing differently depending on `map` or `cmd`
is not to get the parsed result of `map()` into `action()`. These are
parser combinators. _Of course_ we can just make two map definition
parsers, one for `map` and another for `cmd`. Can't believe I never
thought of that last time. Who knows how much time I wasted trying and
failing, then writing a sub-optimal solution.
Oh well, I guess I should just be thankful that a niggling logging
problem (in `MapAction::parse()`) that turned into a maddening journey
to a giant brick wall in search of a `Result` return value with correct
borrows finally enlightened me to the fact that I was doing the wrong
thing all along.
* Comment out double-parsing code related to `MapAction::parse()`
because we want to parse in a single go. No more two-pass parsing.
* Split the `map_kind()` parser into two separate parsers for `map` and
`cmd`. Similarly, split the `map()` parser into `map_map()` and
`map_cmd()` for the same reason. Our new parser tree looks like this:
map(): map definition line
-> map_map(): `map` definitions
-> map_kind_map(): `map`
-> map_cmd(): `cmd` definitions
-> map_kind_cmd(): `cmd`
* Up the `recursion_limit` to 256 from 128 because I was getting stack
size errors randomly when I was updating the tests for this code
change.
* Update `action_character()` to not parse `\n` newlines. Otherwise the
newline gets included as a real `Character` in the
`KeyboardKeyWithModifiers` vector.
* The `map_collection_fails_without_terminating_newline()` test fails as
a result of the `action_character()` parser change. Previously it
relied on `map` lines parsing to `Action::String`s, which fail if
there's no terminating newline. Now that `map`s parse to
`Action::Map`s, the newline isn't checked by the map line parser
(`map_map()`). Because the newline doesn't matter for `map`
definitions, the parser would return `Ok`, failing this test even
though the behaviour was correct. Change the map line to a `cmd` to
have the test check the behaviour it was previously testing.
* Update the tests to use parsed `Action::Map` instead of
`Action::String`s where appropriate. Used this program to convert the
strings into the correct source code:
# action_string_to_action_map.py
#!/usr/bin/env python3
import sys
action_string = sys.argv[1]
action = ''
action += 'action: Action::Map(vec![\n'
for c in action_string:
action += ' KeyboardKeyWithModifiers::new(\n'
action += " KeyboardKey::Character(Character::new('{}')),\n".format(c)
action += ' vec![],\n'
action += ' ),\n'
action += ']),'
print(action)
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -1,4 +1,4 @@ -#![recursion_limit="128"] +#![recursion_limit="256"] extern crate autopilot; extern crate chrono; |
