如何使用Python Lepl解析特定于域的语言的子集?

如何使用Python Lepl解析特定于域的语言的子集?,python,parsing,lepl,Python,Parsing,Lepl,我使用Lepl作为解析器,我正在解析的语言非常复杂,我只关心一小部分。我想不出一种方法让Lepl解析我所关心的语法,然后为其他所有内容返回字符串。如果我添加如下规则: everything_else = ~newline & Regexp('.')[:] 然后,它被用来代替我关心的东西。我认为这是因为这是一场比我的其他规则更长的比赛。Lepl中是否有配置设置或其他东西,这样我就可以拥有一个不完善的解析器 更新 应要求添加一些详细信息。我只想解析出等于一个数字的顶级变量定义。那些依赖于他

我使用Lepl作为解析器,我正在解析的语言非常复杂,我只关心一小部分。我想不出一种方法让Lepl解析我所关心的语法,然后为其他所有内容返回字符串。如果我添加如下规则:

everything_else = ~newline & Regexp('.')[:]
然后,它被用来代替我关心的东西。我认为这是因为这是一场比我的其他规则更长的比赛。Lepl中是否有配置设置或其他东西,这样我就可以拥有一个不完善的解析器

更新 应要求添加一些详细信息。我只想解析出等于一个数字的顶级变量定义。那些依赖于他人或是我想忽略的数学表达式。我还想忽略块定义中的内容,语言中还有许多其他构造我想忽略。下面是一个例子:

from lepl import *

class Variable(List): pass
import string

def parse_it(a_string):

    # Parser:  TODO: incomplete
    s = ~Space()[:] # zero or more spaces
    s1 = ~Space()[1:]  # 1 or more spaces
    newline = Newline() & s
    number_squote = ~Optional(Literal("'")) & s & Real() & s & ~Optional(Literal("'"))
    number_dquote = ~Optional(Literal('"')) & s & Real() & s & ~Optional(Literal('"'))
    number = number_squote | number_dquote | Real() >> float
    var_keyword = ~newline & ~Regexp(r'(?i)variable')
    var_name = Word() >> string.lower
    var_assignment = s1 & var_name & s & ~Literal('=') & s & number > Variable
    vars = var_keyword & var_assignment[1:]
    parser = vars[1:]
    return parser.parse(a_string)

input="""
VARIABLE abc=5 bbb='7' ddd='abc*bbb'
variable ccccc=7  // comment
block(1,2,3,4) of_type=cleaner abc=4 d=5 c=string('hi')

define_block block2 (3,4,5,6,7,a,b) var1=35 var2=36
variable ignore_this=5
block3(3,4,5,6) x='var1*ignore_this' y=var2
block4(4,5,6,7,a,b) x='var1*2' y="var2*3"
end_block

block2(1,2,3,4,5,6,3) abc=ccccc d=abc 

create_blocks  // comment: initialize memory
connect_blocks // connect blocks together
simulate // 

"""
for i in parse_it(input):
    print i

所以我只关心块定义之外定义的文件中的
变量Word()=Real()
信息。我希望将其余部分保留为字符串,以便构建AST并修改变量值,然后再次写出控制文件。

因此,如果我理解正确,您希望解析任何以“variable”(忽略大小写)开头且不在块内的行

我们需要担心的第一件事是我们需要了解多少我们想要跳过的部分。例如,我们可以跳过
define_block
end_block
之间的所有内容,但是如果文本“end_block”恰好出现在某个字符串中,该怎么办?也许为了处理这种情况,我们还需要注意字符串?还是评论?这些担心就是为什么跳过文本往往不像你想象的那么容易——事实证明,要理解我们可以跳过什么,我们实际上需要解析数据

但也许在这种情况下,我们还可以。看起来既没有多行字符串也没有多行注释,
define_block
end_block
总是出现在行的开头。这给了我们足够的保证(我认为)我们能够在不担心字符串或注释的情况下删除块(因为字符串或注释将以
//
或类似开头,因此误导性的
//define\u block
“define\u block”
不会在行的开头)

我们可以在lepl之外做到这一点:

block = re.compile(r'^\s*define_block.*?^\s*end_block[^$]*', re.I | re.M | re.S)
input = block.sub('', input)
for line in input.split('\n'):
    if line.lower().startswith('variable'):
        print line
或作为内部的regexp:

block = Regexp(r'(?ims)^\s*define_block.*?^\s*end_block[^$]*')
所以你的最终解决方案将是一条直线

variable = ...
other_line = Regexp(r'^.*$')
parser = (variable | block | other_line)[:]
希望有帮助


最后,完全公开,我还应该指出我今天发布的内容(抱歉)。

因此,如果我理解正确,您希望解析任何以“variable”(忽略大小写)开头的行,并且该行不在块内

我们需要担心的第一件事是我们需要了解多少我们想要跳过的位。例如,我们可以跳过
define_block
end_block
之间的所有内容,但是如果文本“end_block”会怎么样“碰巧出现在某个字符串中?也许为了处理这种情况,我们还需要注意字符串?还是评论?这些担心就是为什么跳过文本往往不像你想象的那么容易——事实证明,要理解我们可以跳过什么,我们实际上需要解析数据

但也许在这种情况下,我们还可以。看起来既没有多行字符串也没有多行注释,
define_block
end_block
总是出现在行的开头。这给了我们足够的保证(我认为)我们能够在不担心字符串或注释的情况下删除块(因为字符串或注释将以
//
或类似开头,因此误导性的
//define\u block
“define\u block”
不会在行的开头)

我们可以在lepl之外做到这一点:

block = re.compile(r'^\s*define_block.*?^\s*end_block[^$]*', re.I | re.M | re.S)
input = block.sub('', input)
for line in input.split('\n'):
    if line.lower().startswith('variable'):
        print line
或作为内部的regexp:

block = Regexp(r'(?ims)^\s*define_block.*?^\s*end_block[^$]*')
所以你的最终解决方案将是一条直线

variable = ...
other_line = Regexp(r'^.*$')
parser = (variable | block | other_line)[:]
希望有帮助


最后,完全公开,我还应该指出我今天发布的内容(对不起)。

您能提供更多详细信息吗?您希望如何找到您关心的部分?您能将其余代码放入pastebin(或在lepl邮件列表上发布)吗?一般来说,lepl会按照给定的顺序进行操作,但是上面的匹配器会在换行后消耗掉所有东西。一个解决方案可能是使用标记器,如果很容易标记您的语言(不幸的是,这通常不容易).由于不再维护lepl,可能需要迁移到pyparsingorder@PhilCooper:我对其他选择持开放态度。我只是认为Lepl是最好的选择。你能提供更多细节吗?你希望如何找到你关心的部分?你能把剩下的代码放在pastebin(或张贴在Lepl邮件列表上)吗?一般来说,lepl会按照给定的顺序进行操作,但是上面的匹配器会在换行后消耗掉所有东西。一个解决方案可能是使用标记器,如果很容易标记您的语言(不幸的是,这通常不容易).由于不再维护lepl,可能需要迁移到pyparsingorder@PhilCooper:我对其他选择持开放态度。我只是认为Lepl是最好的选择。谢谢你的帖子。你回答了我的问题,但让我对使用Lepl感到紧张。从新手的角度来看,它确实是一个很棒的工具。你能推荐一个替代品吗?“python中用于简单解析的标准(最流行的,不是官方的)包是pyparsing但是它有一个比lepl大得多的社区,你会从他们那里得到更多的支持/帮助。对于更复杂的解析,我认为最流行的库是antlr。在看了pyparsing之后,它不是一个递归的像样的解析器……如果你解析一种特定于领域的语言,这有点限制。我对lepl很满意,你的小程序运行得很好。在Lepl can yo