결국 나는 연구 시간을 다 쓰고 오히려 수동 건너 뛰기로 해결해야합니다. 기본적으로 파서가 실패 할 때마다 우리는 커서를 한 문자 앞당기 고 반복하려고합니다. 공백/주석/구문 오류와 상관없이 프로세스가 건너 뛴 부분은 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)
기타 참고로, 여기서 실제 문제는 올바른 두 단계의 구문 분석 프로세스 대신 파서 연결자 라이브러리를 사용하고 있다는 것입니다. 전통적인 구문 분석에서 tokenizer는 공백/주석/구문 오류를 유지/건너 뛰는 작업을 처리하여 모든 공백을 효율적으로 만들고 파서가 볼 수 없도록합니다.