1

我使用 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

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

4

1 回答 1

1

所以,如果我理解正确,你想解析任何以“变量”(忽略大小写)开头并且不在块内的行。

我们需要担心的第一件事是我们需要了解多少我们想要跳过的位。例如,我们可以跳过 和 之间的所有内容define_blockend_block但是如果文本“end_block”恰好出现在某个字符串中怎么办?也许为了处理这种情况,我们还需要注意字符串?或评论?这些担忧是为什么通常不像您想象的那样简单地跳过文本 - 事实证明,要理解我们可以跳过的内容,我们实际上需要解析数据。

但也许在这种情况下我们没问题。看起来你既没有多行字符串也没有多行注释,define_block而且end_block总是出现在一行的开头。这给了我们足够的保证(我认为)能够删除块而不用担心字符串或注释(因为字符串或注释将以//"或类似开头,因此会产生误导 //define_block"define_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

或作为内部的正则表达式:

block = Regexp(r'(?ims)^\s*define_block.*?^\s*end_block[^$]*')

所以你的最终解决方案将是一些东西

variable = ...
other_line = Regexp(r'^.*$')
parser = (variable | block | other_line)[:]

希望有帮助。

最后,全面披露,我还应该指出我今天发布的https://groups.google.com/group/lepl/browse_thread/thread/e305b5b559d93e9e (对不起)。

于 2012-06-02T22:15:37.090 回答