Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何解析非唯一位置模式?_Python_Python 3.x_Pyparsing - Fatal编程技术网

Python 如何解析非唯一位置模式?

Python 如何解析非唯一位置模式?,python,python-3.x,pyparsing,Python,Python 3.x,Pyparsing,我有两个问题与解析一个令人讨厌的模式有关。以下是一些无意义的例子: color ::= word composed of alphas colors ::= (color | '(' color ')' )... comments ::= '(' structure ';' ... ')' 示例=[ "", “红绿”, “#1#红绿”, “#1#红绿”, “#1,2#红绿”, “红绿()”, “#1#红绿色(蓝色)”, “#1#红绿色(#5#蓝色)”, “#1#红绿色(#5#蓝色)”, “#

我有两个问题与解析一个令人讨厌的模式有关。以下是一些无意义的例子:

color ::= word composed of alphas
colors ::= (color | '(' color ')' )...

comments ::= '(' structure ';' ... ')'
示例=[
"",
“红绿”,
“#1#红绿”,
“#1#红绿”,
“#1,2#红绿”,
“红绿()”,
“#1#红绿色(蓝色)”,
“#1#红绿色(#5#蓝色)”,
“#1#红绿色(#5#蓝色)”,
“#1,2#红绿#5#蓝(紫)#7#黄”,
“#1,2#红色(栗色)绿色(#5#蓝色(紫色)#7#黄色)”,
]
在这一点上,我应该说我无法控制这些字符串的创建

正如您所看到的,基本上我想要解析的每个模式都是可选的。然后是我想捕捉的不同部分。我将这些示例的结构视为:

[cars] [colors] [comments] [buyers]
其中,
注释
由子结构组成,可以是用分号分隔的倍数

comments: ([cars] [colors] [buyers]; ...)
为了捕获内容,我创建了以下语法:

将pyparsing导入为pp
整数=pp.py\u common.integer
car_ref=“#”+pp.Group(pp.delimitedList(整数))(“cars”)+“#”
买方_ref=“”
我的问题是:

  • 是否有一种聪明的方法(可能通过定位)来区分括号中属于
    颜色
    的内容,而不是
    注释
  • 我在注释中嵌套括号的问题上做了一些工作。我的策略是,我将使用内部字符串,使用
    编码为分隔符并将其拆分。然而,我没有执行这一战略。我尝试的是:
  • sub_注释=(
    pp.可选(车辆参考)+
    pp.Group(pp.ZeroOrMore(pp.Regex(r“[^;#\s]”))(“颜色”)+
    pp.可选(买方参考)
    )
    拆分注释=pp.Optional(pp.delimitedList(
    pp.Group(次级注释)(“注释*”),
    delim=“;”
    ))
    def parse_注释(原始、位置、标记):
    #去掉括号。
    返回split_comments.transformString(原始[tokens[0]+1:tokens[2]-1])
    comments=pp.originalTextFor(pp.nestedExpr()).setParseAction(parse_comments)
    
    当我使用这个字符串时,所有内容都会变成一个连续的字符串,可能是因为外部
    pp.originalTextFor

    res=comments.parseString((#5#蓝色(紫色)#7#黄色),parseAll=True)
    
    编辑:

    以最后一个字符串示例为例,我希望最终得到一个如下所示的对象结构:

    {
      "cars": [1, 2],
      "colors": "red (maroon) green",
      "buyers": [2, 3],
      "comments": [
        {
          "cars": [5],
          "colors": "blue (purple)",
          "buyers": [6]
        },
        {
          "cars": [7],
          "colors": "yellow",
          "buyers": [10]
        }
      ]
    }
    

    因此,
    colors
    部分中的括号应该按照顺序进行维护,就像散文一样。括号介绍了
    注释
    部分,我不关心它们的顺序,也不关心单个注释的顺序。

    我想你已经准备好了大部分内容,你只是在努力处理递归部分,注释本身可以包含子结构,包括更多注释

    您将此作为您的BNF:

    structure ::= [cars] [colors] [comments] [buyers]
    cars ::= '#' integer, ... '#'
    buyers ::= '<' integer, ... '>'
    
    我接受了你对汽车和买家的定义,并为评论添加了颜色和递归定义。然后进行了从BNF到pyparsing表达式的相当机械的转换:

    integer = pp.pyparsing_common.integer
    
    car_ref = "#" + pp.Group(pp.delimitedList(integer))("cars") + "#"
    buyer_ref = "<" + pp.Group(pp.delimitedList(integer))("buyers") + ">"
    
    # not sure if this will be sufficient for color, but it works for the given examples
    color = pp.Word(pp.alphas)
    colors = pp.originalTextFor(pp.OneOrMore(color | '(' + color + ')'))("colors")
    
    # define comment placeholder so it can be used in definition of structure
    comment = pp.Forward()
    
    structure = pp.Group(pp.Optional(car_ref)
                         + pp.Optional(colors)
                         + pp.Optional(comment)("comments")
                         + pp.Optional(buyer_ref))
    
    # now insert the definition of a comment as a delimited list of structures; this takes care of
    # any nesting of comments within comments
    LPAREN, RPAREN = map(pp.Suppress, "()")
    comment <<= pp.Group(LPAREN + pp.Optional(pp.delimitedList(structure, delim=';')) + RPAREN)
    
    如果使用
    asDict()
    将所有解析结果转换为常规Python dict,则会得到:

    structure.runTests(examples, comment=None,
                       postParse=lambda test, results: results[0].asDict()
                       )
    
    red green
    {'colors': 'red green'}
    
    #1# red green
    {'cars': [1], 'colors': 'red green'}
    
    #1# red green <2>
    {'colors': 'red green', 'cars': [1], 'buyers': [2]}
    
    #1,2# red green <2,3>
    {'colors': 'red green', 'cars': [1, 2], 'buyers': [2, 3]}
    
    red green ()
    {'comments': [[]], 'colors': 'red green'}
    
    #1# red green (blue)
    {'cars': [1], 'colors': 'red green (blue)'}
    
    #1# red green (#5# blue) <2>
    {'colors': 'red green', 'cars': [1], 'comments': [{'cars': [5], 'colors': 'blue'}], 'buyers': [2]}
    
    #1# red green (#5# blue <6>) <2>
    {'colors': 'red green', 'cars': [1], 'comments': [{'colors': 'blue', 'cars': [5], 'buyers': [6]}], 'buyers': [2]}
    
    #1,2# red green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
    {'colors': 'red green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}
    
    #1,2# red (maroon) green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
    {'colors': 'red (maroon) green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}
    
    structure.runTests(示例,注释=None,
    postParse=lambda测试,结果:结果[0]。asDict()
    )
    红绿
    {'colors':'red green'}
    #1#红绿
    {'cars':[1],'colors':'red-green'}
    #1#红绿
    {'colors':'red green','cars':[1],'bullers':[2]}
    #1,2#红绿色
    {'colors':'red green','cars':[1,2],'bullers':[2,3]}
    红绿()
    {'comments':[[]],'colors':'red-green'}
    #1#红绿色(蓝色)
    {'cars':[1],'colors':'red-green(blue)}
    #1#红绿(#5#蓝)
    {'colors':'red-green','cars':[1],'comments':[{'cars':[5],'colors':'blue'}],'bullers':[2]}
    #1#红绿(#5#蓝)
    {'colors':'red-green','cars':[1],'comments':[{'colors':'blue','cars':[5],'bullers':[6]}],'bullers':[2]}
    #1,2#红绿#5#蓝(紫)#7#黄#
    {'colors':'red green','cars':[1,2],'comments':[{'colors':'blue(purple)','cars':[5],'businers':[6]},{'colors':'yellow','cars':[7],'businers':[10],'businers':[2,3]}
    #1,2#红色(栗色)绿色(#5#蓝色(紫色)#7#黄色)
    {'colors':'red(褐红色)green','cars':[1,2],'comments':[{'colors':'blue(紫色)','cars':[5],'bullers':[6],{'colors':'yellow','cars':[7],'bullers':[10],'bullers':[2,3]}
    
    nested_expr
    是一条捷径,当你真的不想解析内容时,你只想跳过它们,但你必须考虑嵌套的打开器和关闭器。尝试将注释定义为Forward(),然后使用“当遇到注释时,它是否必须在周围元素中保持其顺序?”?或者你可以简单地报告“在这个级别上,有这些颜色和这些评论”?或者它与前面或下面的元素有关联吗?谢谢你再次回答:)所以这不是一个很好的讨论媒介。我可以在gitter.im上给你写信,或者在pyrepo上发布一个问题吗?或者你更喜欢子reddit?来回答你关于关联性的问题:不幸的是,括号有一个双重功能。它们可以引入注释部分,也可以用作散文中的普通括号。请参阅我的编辑以获得进一步的澄清。如果您想进一步了解,让我们尝试使用sub-reddit。这完美地解析了示例。谢谢你详尽的答复。
    structure.runTests(examples, comment=None,
                       postParse=lambda test, results: results[0].asDict()
                       )
    
    red green
    {'colors': 'red green'}
    
    #1# red green
    {'cars': [1], 'colors': 'red green'}
    
    #1# red green <2>
    {'colors': 'red green', 'cars': [1], 'buyers': [2]}
    
    #1,2# red green <2,3>
    {'colors': 'red green', 'cars': [1, 2], 'buyers': [2, 3]}
    
    red green ()
    {'comments': [[]], 'colors': 'red green'}
    
    #1# red green (blue)
    {'cars': [1], 'colors': 'red green (blue)'}
    
    #1# red green (#5# blue) <2>
    {'colors': 'red green', 'cars': [1], 'comments': [{'cars': [5], 'colors': 'blue'}], 'buyers': [2]}
    
    #1# red green (#5# blue <6>) <2>
    {'colors': 'red green', 'cars': [1], 'comments': [{'colors': 'blue', 'cars': [5], 'buyers': [6]}], 'buyers': [2]}
    
    #1,2# red green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
    {'colors': 'red green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}
    
    #1,2# red (maroon) green (#5# blue (purple) <6>;#7# yellow <10>) <2,3>
    {'colors': 'red (maroon) green', 'cars': [1, 2], 'comments': [{'colors': 'blue (purple)', 'cars': [5], 'buyers': [6]}, {'colors': 'yellow', 'cars': [7], 'buyers': [10]}], 'buyers': [2, 3]}