Whole file
erikrose/parsimonious
The author described this change as “Fix multiple terms as part of `/` expressions (#250)”. It counts as a record because the check below fails on the code as it stood at 0d3f5f93c and passes on 7d67c8231, with nothing else changed between the two runs.
Projecterikrose/parsimonious
Fix saved2025-01-02
Sharing licenceMIT · LICENSE
Change size+13 −6
What the code was meant to do, written into the code itself as a save note
Fix multiple terms as part of `/` expressions (#250)
The change
| 197 | 197 | term.members = (not_term,) + term.members | |
| 198 | 198 | ||
| 199 | 199 | sequence = Sequence(term, OneOrMore(term), name='sequence') | |
| 200 | - | or_term = Sequence(Literal('/'), _, term, name='or_term') | |
| 201 | - | ored = Sequence(term, OneOrMore(or_term), name='ored') | |
| 200 | + | or_term = Sequence(Literal('/'), _, OneOrMore(term), name='or_term') | |
| 201 | + | ored = Sequence(OneOrMore(term), OneOrMore(or_term), name='ored') | |
| 202 | 202 | expression = OneOf(ored, sequence, term, name='expression') | |
| 203 | 203 | rule = Sequence(label, equals, expression, name='rule') | |
| 204 | 204 | rules = Sequence(_, OneOrMore(rule), name='rules') | |
| ⋯ | |||
| 231 | 231 | ~"u?r?b?'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'"is | |
| 232 | 232 | ||
| 233 | 233 | expression = ored / sequence / term | |
| 234 | - | or_term = "/" _ term | |
| 235 | - | ored = term or_term+ | |
| 234 | + | or_term = "/" _ term+ | |
| 235 | + | ored = term+ or_term+ | |
| 236 | 236 | sequence = term term+ | |
| 237 | 237 | not_term = "!" term _ | |
| 238 | 238 | lookahead_term = "&" term _ | |
| ⋯ | |||
| 367 | 367 | ||
| 368 | 368 | def visit_ored(self, node, ored): | |
| 369 | 369 | first_term, other_terms = ored | |
| 370 | + | if len(first_term) == 1: | |
| 371 | + | first_term = first_term[0] | |
| 372 | + | else: | |
| 373 | + | first_term = Sequence(*first_term) | |
| 370 | 374 | return OneOf(first_term, *other_terms) | |
| 371 | 375 | ||
| 372 | 376 | def visit_or_term(self, node, or_term): | |
| ⋯ | |||
| 375 | 379 | We already know it's going to be ored, from the containing ``ored``. | |
| 376 | 380 | ||
| 377 | 381 | """ | |
| 378 | - | slash, _, term = or_term | |
| 379 | - | return term | |
| 382 | + | slash, _, terms = or_term | |
| 383 | + | if len(terms) == 1: | |
| 384 | + | return terms[0] | |
| 385 | + | else: | |
| 386 | + | return Sequence(*terms) | |
| 380 | 387 | ||
| 381 | 388 | def visit_label(self, node, label): | |
| 382 | 389 | """Turn a label into a unicode string.""" | |
The check that tells the two apart
fail→pass·parsimonious/tests/test_grammar.py::GrammarTests::test_sequence_choice_bug
Check file parsimonious/tests/test_grammar.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before it0d3f5f93c98ae55707f0958366900275d1ce094f
Broken version dated2024-08-02
Moduleparsimonious.grammar
Units changedBootstrappingGrammar, RuleVisitor
Fingerprint4e210790188a0356
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.