summaryrefslogtreecommitdiff
path: root/pyparsing/core.py
diff options
context:
space:
mode:
authorptmcg <ptmcg@austin.rr.com>2022-12-11 10:56:32 -0600
committerptmcg <ptmcg@austin.rr.com>2022-12-11 10:56:32 -0600
commitbcaeea1fa924a66a5b13c67cd830621e4eff4214 (patch)
tree405ee5a30ffb7ec292242e3828957dfbca430aec /pyparsing/core.py
parent8c72861e1ca49507f5cc201295c061d0e49e1bfa (diff)
downloadpyparsing-git-bcaeea1fa924a66a5b13c67cd830621e4eff4214.tar.gz
Added DelimitedList class, for better handling of naming and diagramming (replaces delimited_list function)
Diffstat (limited to 'pyparsing/core.py')
-rw-r--r--pyparsing/core.py65
1 files changed, 65 insertions, 0 deletions
diff --git a/pyparsing/core.py b/pyparsing/core.py
index 320d882..5c845ae 100644
--- a/pyparsing/core.py
+++ b/pyparsing/core.py
@@ -5049,6 +5049,71 @@ class ZeroOrMore(_MultipleMatch):
return "[" + str(self.expr) + "]..."
+class DelimitedList(ParseElementEnhance):
+ def __init__(
+ self,
+ expr: Union[str, ParserElement],
+ delim: Union[str, ParserElement] = ",",
+ combine: bool = False,
+ min: typing.Optional[int] = None,
+ max: typing.Optional[int] = None,
+ *,
+ allow_trailing_delim: bool = False,
+ ):
+ """Helper to define a delimited list of expressions - the delimiter
+ defaults to ','. By default, the list elements and delimiters can
+ have intervening whitespace, and comments, but this can be
+ overridden by passing ``combine=True`` in the constructor. If
+ ``combine`` is set to ``True``, the matching tokens are
+ returned as a single token string, with the delimiters included;
+ otherwise, the matching tokens are returned as a list of tokens,
+ with the delimiters suppressed.
+
+ If ``allow_trailing_delim`` is set to True, then the list may end with
+ a delimiter.
+
+ Example::
+
+ DelimitedList(Word(alphas)).parse_string("aa,bb,cc") # -> ['aa', 'bb', 'cc']
+ DelimitedList(Word(hexnums), delim=':', combine=True).parse_string("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
+ """
+ if isinstance(expr, str_type):
+ expr = ParserElement._literalStringClass(expr)
+ expr = typing.cast(ParserElement, expr)
+
+ if min is not None:
+ if min < 1:
+ raise ValueError("min must be greater than 0")
+ if max is not None:
+ if min is not None and max < min:
+ raise ValueError("max must be greater than, or equal to min")
+
+ self.content = expr
+ self.raw_delim = str(delim)
+ self.delim = delim
+ self.combine = combine
+ if not combine:
+ self.delim = Suppress(delim)
+ self.min = min or 1
+ self.max = max
+ self.allow_trailing_delim = allow_trailing_delim
+
+ delim_list_expr = self.content + (self.delim + self.content) * (
+ self.min - 1,
+ None if self.max is None else self.max - 1,
+ )
+ if self.allow_trailing_delim:
+ delim_list_expr += Opt(self.delim)
+
+ if self.combine:
+ delim_list_expr = Combine(delim_list_expr)
+
+ super().__init__(delim_list_expr, savelist=True)
+
+ def _generateDefaultName(self) -> str:
+ return "{0} [{1} {0}]...".format(self.content.streamline(), self.raw_delim)
+
+
class _NullToken:
def __bool__(self):
return False