最終,我跑出來的研究時間,並有相當的手動跳過定居。基本上每次解析器失敗時,我們嘗試將光標前進一個字符並重復。不管空白/評論/語法錯誤,流程中跳過的任何部分都將轉儲到Text
結構中。代碼是可重複使用的,除了你必須將它合併到所有重複結果的地方以及原始解析器可能會失敗的地方。
下面的代碼,如果它可以幫助任何人。它寫爲Parsy。
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)
在其他的說明,我想這裏真正的問題是,我使用的是解析器組合庫,而不是一個適當的兩個階段分析的過程。在傳統的解析中,標記器將處理保留/跳過任何空格/註釋/語法錯誤,使它們全部有效地空白並且對解析器不可見。