Created
December 5, 2017 04:51
-
-
Save tungd/cee66782c7a2bcb8846fff58e07c108c to your computer and use it in GitHub Desktop.
Parser combinator to skip error.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from parsy import Parser, Result | |
class Text(object): | |
'''Structure to contain all the parts that the parser does not understand. | |
A better name would be Whitespace | |
''' | |
def __init__(self, text=''): | |
self.text = text | |
def __repr__(self): | |
return "Text(text='{}')".format(self.text) | |
def __eq__(self, other): | |
return self.text.strip() == getattr(other, 'text', '').strip() | |
def many_skip_error(parser, skip=lambda t, i: i + 1, until=None): | |
'''Repeat the original `parser`, aggregate result into `values` | |
and error in `Text`. | |
''' | |
@Parser | |
def _parser(stream, index): | |
values, result = [], None | |
while index < len(stream): | |
result = parser(stream, index) | |
# Original parser success | |
if result.status: | |
values.append(result.value) | |
index = result.index | |
# Check for end condition, effectively `manyTill` in Parsec | |
elif until is not None and until(stream, index).status: | |
break | |
# Aggregate skipped text into last `Text` value, or create a new one | |
else: | |
if len(values) > 0 and isinstance(values[-1], Text): | |
values[-1].text += stream[index] | |
else: | |
values.append(Text(stream[index])) | |
index = skip(stream, index) | |
return Result.success(index, values).aggregate(result) | |
return _parser | |
# Example usage | |
skip_error_parser = many_skip_error(original_parser) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment