Skip to content

Commit a0c5d9a

Browse files
committed
Make concat also work on lists of bytes.
Unfortunately this requires manually writing out the mapped function into the resulting parser, as the `join` method needs to be bound to the same type as the elements to be joined. Because these elements can be an empty list, this type needs to be inferred from the type of the input stream.
1 parent 294590f commit a0c5d9a

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

src/parsy/__init__.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,23 @@ def combine_dict(self, combine_fn: Callable) -> Parser:
166166

167167
def concat(self) -> Parser:
168168
"""
169-
Returns a parser that concatenates together (as a string) the previously
170-
produced values.
169+
Returns a parser that concatenates together the previously produced values.
170+
171+
This parser will join the values using the type of the input stream, so
172+
when feeding bytes to the parser, the items to be joined must also be bytes.
171173
"""
172-
return self.map("".join)
174+
175+
@Parser
176+
def parser(stream: bytes | str, index: int) -> Result:
177+
joiner = type(stream)()
178+
result = self(stream, index)
179+
if result.status:
180+
next_parser: Parser = success(joiner.join(result.value))
181+
return next_parser(stream, result.index).aggregate(result)
182+
else:
183+
return result
184+
185+
return parser
173186

174187
def then(self, other: Parser) -> Parser:
175188
"""

tests/test_parsy.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,16 @@ def test_combine_dict_skip_underscores(self):
157157
).combine_dict(Pair)
158158
self.assertEqual(parser.parse("ABC 123"), Pair(word="ABC", number=123))
159159

160-
def test_concat(self):
160+
def test_concat_str(self):
161161
parser = letter.many().concat()
162162
self.assertEqual(parser.parse(""), "")
163163
self.assertEqual(parser.parse("abc"), "abc")
164164

165+
def test_concat_bytes(self):
166+
parser = any_char.many().concat()
167+
self.assertEqual(parser.parse(b""), b"")
168+
self.assertEqual(parser.parse(b"abc"), b"abc")
169+
165170
def test_generate(self):
166171
x = y = None
167172

0 commit comments

Comments
 (0)