summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES58
-rw-r--r--pyparsing.py2
-rw-r--r--unitTests.py15
3 files changed, 74 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index c6fb9b7..45774b9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -39,6 +39,64 @@ Version 2.3.0 - TBD
Reported by seron in Issue #22, nice catch!
+- POSSIBLE API CHANGE: Fixed a related bug where a results name
+ erroneously created a second level of hierarchy in the returned
+ ParseResults. The intent for accumulating results names into ParseResults
+ is that, in the absence of Group'ing, all names get merged into a
+ common namespace. This allows us to write:
+
+ key_value_expr = (Word(alphas)("key") + '=' + Word(nums)("value"))
+ result = key_value_expr.parseString("a = 100")
+
+ and have result structured as {"key": "a", "value": "100"}
+ instead of [{"key": "a"}, {"value": "100"}].
+
+ However, if a named expression is used in a higher-level non-Group
+ expression that *also* has a name, a false sub-level would be created
+ in the namespace:
+
+ num = pp.Word(pp.nums)
+ num_pair = ("[" + (num("A") + num("B"))("values") + "]")
+ U = num_pair.parseString("[ 10 20 ]")
+ print(U.dump())
+
+ Since there is no grouping, "A", "B", and "values" should all appear
+ at the same level in the results, as:
+
+ ['[', '10', '20', ']']
+ - A: '10'
+ - B: '20'
+ - values: ['10', '20']
+
+ Instead, an extra level of "A" and "B" show up under "values":
+
+ ['[', '10', '20', ']']
+ - A: '10'
+ - B: '20'
+ - values: ['10', '20']
+ - A: '10'
+ - B: '20'
+
+ This bug has been fixed. Now, if this hierarchy is desired, then a
+ Group should be added:
+
+ num_pair = ("[" + pp.Group(num("A") + num("B"))("values") + "]")
+
+ Giving:
+
+ ['[', ['10', '20'], ']']
+ - values: ['10', '20']
+ - A: '10'
+ - B: '20'
+
+ But in no case should "A" and "B" appear in multiple levels. This bug-fix
+ fixes that.
+
+ If you have current code which relies on this behavior, then add or remove
+ Groups as necessary to get your intended results structure.
+
+ Reported by Athanasios Anastasiou.
+
- IndexError's raised in parse actions will get explicitly reraised
as ParseExceptions that wrap the original IndexError. Since
IndexError sometimes occurs as part of pyparsing's normal parsing
diff --git a/pyparsing.py b/pyparsing.py
index a4a7546..9279d34 100644
--- a/pyparsing.py
+++ b/pyparsing.py
@@ -398,7 +398,7 @@ class ParseResults(object):
toklist = [ toklist ]
if asList:
if isinstance(toklist,ParseResults):
- self[name] = _ParseResultsWithOffset(toklist.copy(),0)
+ self[name] = _ParseResultsWithOffset(ParseResults(toklist.__toklist), 0)
else:
self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0)
self[name].__name = name
diff --git a/unitTests.py b/unitTests.py
index 9ebf02b..9a78bf5 100644
--- a/unitTests.py
+++ b/unitTests.py
@@ -3572,6 +3572,21 @@ class ParseActionNestingTest(ParseTestCase):
print("result1.dump():\n" + result1.dump() + "\n")
assert before_pa_dict == after_pa_dict, "noop parse action changed ParseResults structure"
+class ParseResultsNameBelowUngroupedNameTest(ParseTestCase):
+ def runTest(self):
+ import pyparsing as pp
+
+ rule_num = pp.Regex("[0-9]+")("LIT_NUM*")
+ list_num = pp.Group(pp.Literal("[")("START_LIST")
+ + pp.delimitedList(rule_num)("LIST_VALUES")
+ + pp.Literal("]")("END_LIST"))("LIST")
+
+ test_string = "[ 1,2,3,4,5,6 ]"
+ list_num.runTests(test_string)
+
+ U = list_num.parseString(test_string)
+ assert "LIT_NUM" not in U.LIST.LIST_VALUES, "results name retained as sub in ungrouped named result"
+
class FollowedByTest(ParseTestCase):
def runTest(self):