我尝试使用pyparsing来解析键:值对从文档中的注释。键从一行的开头开始,后面跟着一个值。值可以在以空格开头的多行上继续。在
import pyparsing as pp
instring = """
-- This is (a) #%^& comment
/*
name1: val
name2: val2 with $*&#@) junk
name3: val3: with @)(*% multi-
line: content
*/
"""
comment1 = pp.Literal("--") + pp.originalTextFor(pp.SkipTo(pp.LineEnd())).setDebug()
identifier = pp.Word(pp.alphanums + "_").setDebug()
meta1 = pp.LineStart() + identifier + pp.Literal(":") + pp.SkipTo(pp.LineEnd())
meta2 = pp.LineStart() + pp.White() + pp.SkipTo(pp.LineEnd())
metaval = meta1 + pp.ZeroOrMore(meta2)
metalist = pp.ZeroOrMore(comment1) + pp.Literal("/*") + pp.OneOrMore(metaval) + pp.Literal("*/")
if __name__ == "__main__":
p = metalist.parseString(instring)
print(p)
失败原因:
^{pr2}$pyparsing whitespace match issues的答案是
LineStart has always been difficult to work with, but ...
如果解析器位于第4行第1列(第一列键:值对),那为什么它找不到线的起点呢?正确的pyparsing语法是什么来识别以无空格开头的行和以空格开头的行?在
我想我对}没有单独的字符。所以在
LineStart
的困惑是,对于LineEnd
,我可以寻找'\n'
字符,但是{LineStart
中,我查看当前的解析器位置是否正好位于'\n'
之后;或者如果它当前位于a'\n'
上,请移过它并继续。不幸的是,我在一个混乱了报告位置的地方实现了这个,所以你会得到一些奇怪的错误,比如“在第X列1行找不到一个行的开始”,这听起来确实像是一个成功匹配的行开头。另外,我想我需要重新讨论这种隐式的换行符跳过,或者,对于LineStart
来说,所有的空白都会跳过。在现在,我已经通过稍微扩展行首表达式使您的代码正常工作,如下所示:
并用LS替换meta1和meta2中的LineStart引用:
^{pr2}$如果
^{3}$LineStart
的这种情况让您感到不舒服,那么您可以尝试另一种策略:使用解析时间条件只接受从第1列开始的标识符:这段代码完全删除了
LineStart
,而我只想知道我希望这个特定的令牌做什么。我还必须修改ZeroOrMore
中的ZeroOrMore
重复,这样*/
就不会被意外地处理为连续的评论内容。在感谢您对此的耐心等待-我不希望很快给出一个修补的
LineStart
更改,然后发现我忽略了其他兼容性或其他边缘情况,这些情况使我重新回到了这个类的当前不太好的状态。但在发布2.1.10之前,我会花一些精力来澄清这种行为。在相关问题 更多 >
编程相关推荐