summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyparsing/core.py12
-rw-r--r--pyparsing/helpers.py11
-rw-r--r--tests/test_unit.py18
3 files changed, 25 insertions, 16 deletions
diff --git a/pyparsing/core.py b/pyparsing/core.py
index a8d1f32..17428bf 100644
--- a/pyparsing/core.py
+++ b/pyparsing/core.py
@@ -1386,7 +1386,7 @@ class ParserElement(ABC):
"second tuple value must be greater or equal to first tuple value"
)
if minElements == optElements == 0:
- raise ValueError("cannot multiply ParserElement by 0 or (0, 0)")
+ return And([])
if optElements:
@@ -3629,10 +3629,12 @@ class And(ParseExpression):
exprs[:] = tmp
super().__init__(exprs, savelist)
self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
- self.set_whitespace_chars(
- self.exprs[0].whiteChars, copy_defaults=self.exprs[0].copyDefaultWhiteChars
- )
- self.skipWhitespace = self.exprs[0].skipWhitespace
+ if self.exprs:
+ self.set_whitespace_chars(
+ self.exprs[0].whiteChars,
+ copy_defaults=self.exprs[0].copyDefaultWhiteChars,
+ )
+ self.skipWhitespace = self.exprs[0].skipWhitespace
self.callPreparse = True
def streamline(self):
diff --git a/pyparsing/helpers.py b/pyparsing/helpers.py
index 42510b8..251092a 100644
--- a/pyparsing/helpers.py
+++ b/pyparsing/helpers.py
@@ -92,11 +92,12 @@ def counted_array(
# - type: 'bool'
"""
intExpr = intExpr or int_expr
- arrayExpr = Forward()
+ array_expr = Forward()
- def countFieldParseAction(s, l, t):
+ def count_field_parse_action(s, l, t):
+ nonlocal array_expr
n = t[0]
- arrayExpr << (And([expr] * n) if n else empty)
+ array_expr <<= (expr * n) if n else Empty()
# clear list contents, but keep any named results
del t[:]
@@ -105,8 +106,8 @@ def counted_array(
else:
intExpr = intExpr.copy()
intExpr.set_name("arrayLen")
- intExpr.add_parse_action(countFieldParseAction, callDuringTry=True)
- return (intExpr + arrayExpr).set_name("(len) " + str(expr) + "...")
+ intExpr.add_parse_action(count_field_parse_action, call_during_try=True)
+ return (intExpr + array_expr).set_name("(len) " + str(expr) + "...")
def match_previous_literal(expr: ParserElement) -> ParserElement:
diff --git a/tests/test_unit.py b/tests/test_unit.py
index 6df6002..1ad8f82 100644
--- a/tests/test_unit.py
+++ b/tests/test_unit.py
@@ -2477,12 +2477,6 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
def testParserElementMulOperatorWithTuples(self):
"""test ParserElement "*" with various tuples"""
- # ParserElement * (0, 0)
- with self.assertRaises(
- ValueError, msg="ParserElement * (0,0) should raise error"
- ):
- expr = pp.Word(pp.alphas)("first") + pp.Word(pp.nums)("second*") * (0, 0)
-
# ParserElement * (None, n)
expr = pp.Word(pp.alphas)("first") + pp.Word(pp.nums)("second*") * (None, 3)
@@ -2556,6 +2550,18 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
):
expr = pp.Word(pp.alphas)("first") + pp.Word(pp.nums)("second") * ("2", "3")
+ def testParserElementMulByZero(self):
+ alpwd = pp.Word(pp.alphas)
+ numwd = pp.Word(pp.nums)
+
+ test_string = "abd def ghi jkl"
+
+ parser = alpwd * 2 + numwd * 0 + alpwd * 2
+ self.assertParseAndCheckList(parser, test_string, expected_list=test_string.split())
+
+ parser = alpwd * 2 + numwd * (0, 0) + alpwd * 2
+ self.assertParseAndCheckList(parser, test_string, expected_list=test_string.split())
+
def testParserElementMulOperatorWithOtherTypes(self):
"""test the overridden "*" operator with other data types"""