pyparsing:多个元素的setResultsName合并

时间:2016-05-19 16:39:12

标签: python pyparsing

以下是我正在解析的文字:

x ~ normal(mu, 1)
y ~ normal(mu2, 1)

解析器使用以下命令匹配这些行:

model_definition = Group(identifier.setResultsName('random_variable_name') + '~' + expression).setResultsName('model_definition')

// end of line: .setResultsName('model_definition')

问题是当有两个模型定义时,它们不会在ParseResults对象中单独命名:

enter image description here

看起来第一个被第二个覆盖了。我命名它们的原因是让线条更容易执行 - 这样我(希望)不必弄清楚评估时发生了什么 - 解析器已经标记了所有内容。如何才能将两个model_definition标记为?如果model_definition保存了找到的每个模型定义的列表,那就太好了。

以防万一,这里有一些我的代码:

model_definition = Group(identifier.setResultsName('random_variable_name') + '~' + expression).setResultsName('model_definition')
expression << Or([function_application, number, identifier, list_literal, probability_expression])
statement = Optional(newline) + Or([model_definition, assignment, function_application]) + Optional(newline)
line = OneOrMore('\n').suppress()
comment = Group('#' + SkipTo(newline)).suppress()
program = OneOrMore(Or([line, statement, comment]))
ast = program.parseString(input_string)
return ast

2 个答案:

答案 0 :(得分:3)

我没有记录,但我在pyparsing.py找到了一些内容:enter image description here

我将.setResultsName('model_definition')更改为.setResultsName('model_definition*')并且列出正确!

enter image description here

编辑:已记录,但它是您传递给setResultsName的标志:

  

setResultsName(string, listAllMatches = False ) - 赋予与元素匹配的标记的名称;如果重复组中的多个标记(例如ZeroOrMore或delimitedList)默认只返回最后一个匹配标记 - 如果listAllMatches设置为True,则返回匹配标记列表

答案 1 :(得分:1)

这里有足够的代码可以让事情发挥作用:

from pyparsing import *

# fake in the bare minimum to parse the given test strings
identifier = Word(alphas, alphanums)
integer = Word(nums)
function_call = identifier + '(' + Optional(delimitedList(identifier | integer)) + ')'
expression = function_call

model_definition = Group(identifier.setResultsName('random_variable_name') + '~' + expression)

sample = """
x ~ normal(mu, 1)
y ~ normal(mu2, 1)
"""

'*'的结尾setResultsName适用于使用setResultsNameexpr("name*") vs expr.setResultsName("name", listAllMatches=True)的缩写形式的情况。如果您更喜欢调用setResultsName,那么我不会使用'*'表示法,而是会传递listAllMatches参数。

如果您获得相互衔接的名称,则可能需要添加一个级别的分组。以下是使用listAllMatches=True的解决方案,凭借尾随的'*'符号:

model_definition1 = model_definition('model_definition*')
print OneOrMore(model_definition1).parseString(sample).dump()

它返回此解析结果:

[['x', '~', 'normal', '(', 'mu', '1', ')'], ['y', '~', 'normal', '(', 'mu2', '1', ')']]
- model_definition: [['x', '~', 'normal', '(', 'mu', '1', ')'], ['y', '~', 'normal', '(', 'mu2', '1', ')']]
  [0]:
    ['x', '~', 'normal', '(', 'mu', '1', ')']
    - random_variable_name: x
  [1]:
    ['y', '~', 'normal', '(', 'mu2', '1', ')']

以下是不使用listAllMatches的变体,但添加了另一个级别的组:

model_definition2 = model_definition('model_definition')
print OneOrMore(Group(model_definition2)).parseString(sample).dump()

给出:

[[['x', '~', 'normal', '(', 'mu', '1', ')']], [['y', '~', 'normal', '(', 'mu2', '1', ')']]]
[0]:
  [['x', '~', 'normal', '(', 'mu', '1', ')']]
  - model_definition: ['x', '~', 'normal', '(', 'mu', '1', ')']
    - random_variable_name: x
[1]:
  [['y', '~', 'normal', '(', 'mu2', '1', ')']]
  - model_definition: ['y', '~', 'normal', '(', 'mu2', '1', ')']
    - random_variable_name: y

在这两种情况下,我都会看到返回的完整内容,所以我不会理解你的意思是“如果你返回多个,它就不能分割出每个孩子。”