解析器保留注释并从错误中恢复
我正在开发一个适合配置格式的GUI编辑器。基本上,编辑器将解析配置文件,显示对象属性,以便用户可以从GUI进行编辑,然后将对象写回文件。解析器保留注释并从错误中恢复
我已经得到了解析 - 编辑 - 写部分完成,除了:
- 解析的数据结构只包括对象属性的信息,所以评论和空格被上写
- 丢失,如果有任何语法错误,文件的其余部分被跳过
你会如何解决这些问题?这个问题的常用方法是什么?我正在使用Python和Parsec模块https://pythonhosted.org/parsec/documentation.html,但是,我们感谢他们提供帮助和大致方向。
我也试过Pylens(https://pythonhosted.org/pylens/),这是非常接近我所需要的只是它不能跳过语法错误。
最终,我跑出来的研究时间,并有相当的手动跳过定居。基本上每次解析器失败时,我们尝试将光标前进一个字符并重复。不管空白/评论/语法错误,流程中跳过的任何部分都将转储到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)
在其他的说明,我想这里真正的问题是,我使用的是解析器组合库,而不是一个适当的两个阶段分析的过程。在传统的解析中,标记器将处理保留/跳过任何空格/注释/语法错误,使它们全部有效地空白并且对解析器不可见。
你问到典型的方法解决这个问题。这里有两个项目可以解决你所描述的类似问题:
sketch-n-sketch:矢量图像的“直接操作”界面,您可以在其中编辑描述图像的源语言,或直接编辑它所表示的图像并查看这些变化反映在源代码中。看看视频演示文稿,它非常酷。
Boomerang:用镜头“聚焦”在一些具体的语法的抽象意义,改变这种抽象模型,然后反映原始来源的变化。
两个项目都取得了几篇论文描述了他们的作者采取了方式。据我所知,Lens方法非常流行,其中解析和打印成为Lens的get
和put
函数,该函数采用一些源代码并专注于该代码描述的抽象概念。