Python Parsley:解析简单的源代码

时间:2014-04-26 13:40:34

标签: python parsing python-parsley

我有遗留代码,我们仍在使用。通过Python的欧芹和提供的教程,我还没有找到解析源代码的好例子。作为我的代码的一个例子:

{ comment

still part of the comment above

oh ya more commenting

}

ACTION_1 [file_name.ex1]
ACTION_2 [file_name.ex2] ; some comment
{ some comment} ACTION_3 [file_name.ex3]
ACTION_4 {wow another comment } [file_name.ex4]
;ACTION_5 [file_name.ex5] <-- commented out line
ACTION_6 [file_name.ex6]

所以我开始创建语法,

x = parsley.grammar = r"""
text = (anything:x ?(x not in '{}') -> x)+:d -> tex.text("".join(d))
comment = ';' (anything:x ?(x not in '\n'))+ '\n' -> ''
file_name = (anything:x ?(x in '{}') -> x)+:d -> text.text("".join(d))
"""

我试图用欧芹作为dict ={'ACTION_x': 'file_name.exx', ... }来解析这个问题。如何创建正确的语法来解析此文件?

1 个答案:

答案 0 :(得分:2)

当我希望结果是某种AST时,我在创建语法时会经历三个步骤。第一步是确定主要的非终结产品并进行构建。不要先担心减少,只需要完成基本的制作,并确保它们可以匹配您的源文件。如果您的语言已经有现有的语法规范,请使用它;它几乎肯定比你对语言结构的看法更准确。

实际上,重复一遍:如果您的语言已经有现有的语法规范,请使用它。我之前已经成功地将PEG和CFG(BNF)语言描述修改为欧芹语法

multilineComment = '{' (~'}' anything)* '}'

这应与您的多行注释语法相匹配。请注意我是如何使用PEG式(负)前瞻断言而不是语义断言的;这通常会更紧凑,更有用地表达你想要解析的东西。大声朗读:&#34;多行注释是一个开头括号,后面是零或多个没有关闭括号的任何东西,后面是一个右括号。&#34;

单行注释比较棘手,因为您的语言似乎是空格敏感的。这意味着每个使用换行符的规则必须同意新换行消费的发生时间和地点。

lineComment = ';' (~'\n' anything)* '\n'

有趣的故事:我实际上写了until规则来帮助解决这些问题&#34;这样做直到那个&#34;各种各样的规则,但事实证明它让事情变得更加混乱!生活和学习。

第二步是编写测试。从您对IRC的评论中,我猜测您已经知道如何为Parsley代码编写测试,所以我不会在这里介绍它;简而言之,编写一小段代码,并通过Parsley运行它们,断言它们成功或失败。您将返回并更改后续测试,以断言在第三步中将代码段解析为有效树。

第三步是将缩减注释(绑定,缩减)添加到规则中。这会将你的语法从目标语言的识别器转变为解析器。

记住以前的文件名规则吗?

fileName = '[' (~']' anything)+ ']'

让我们继续添加一个绑定和减少它;我们想要捕获括号的内容并将其作为字符串返回。

fileName = '[' (~']' anything)+::cs ']' -> "".join(cs)

Parsley还有一种方法可以从输入迭代中切片,如果您正在解析字符串并想要捕获字符串,这非常有效。

fileName = '[' <(~']' anything)+>:s ']' -> s

我在这里使用过单字母变量,因为我被困在Haskell Land中,但你可以随意使用你喜欢的任何名字进行绑定。

希望这有帮助! ~C。