根据以前的结果选择解析器

时间:2015-07-22 08:16:53

标签: python haskell pyparsing parsec

我解析了几个输出,这些文件有两个不同的标题:

header1 = " MO EIGENVALUES, MO OCCUPATION NUMBERS, AND CARTESIAN MO EIGENVECTORS AFTER SCF STEP -1"

header2 =  "MO EIGENVALUES, MO OCCUPATION NUMBERS, AND SPHERICAL MO EIGENVECTORS AFTER SCF STEP -1"

基于结果在 CARTESIAN SPHERICAL 坐标中的语句,我想应用相应的解析器。

在Haskell中,我可以编写一个解析器,根据以前的结果决定下一步做什么,

myparser = do
    xs <- someParser
    if xs == "foo"
       then parser1
       else parser2

如何使用pyparsing在python中创建相同的函数?

注意:如果输出是笛卡尔坐标或球坐标,我就不知道先验

2 个答案:

答案 0 :(得分:2)

以下是应该有效的解决方案的概要。我们的想法是实现一个新的解析器类,它运行一个解析器,并根据返回的标记在两个备选项之间进行选择。

# modeled after class And in pyparsing.py
class IfThenElse(ParseExpression):

  def __init__(self, exprs, savelist = True):
    super(IfThenElse,self).__init__(exprs, savelist)
    self.parserIf = exprs[1]     # maybe exprs[0]?
    self.parserThen = exprs[2]
    self.parserElse = exprs[3]
    self.mayReturnEmpty = all(e.mayReturnEmpty for e in exprs[2:])
    self.setWhitespaceChars( ... )
    self.skipWhitespace = self.exprs[0].skipWhitespace

  def parseImpl(self, instring, loc, doActions = True):
    loc, toks = self.parserIf._parse(instring, loc, doActions)

    if ...toks...:
      loc, toks2 = self.parserThen._parse(instring, loc, doActions)
    else:
      loc, toks2 = self.parserElse._parse(instring, loc, doActions)

    return loc, toks2   # maybe combine toks and toks2?

def __str__(self):
  return "blah"         # for now

if ...toks...是放置切换逻辑的地方。

您还需要实施__str__方法,可能还需要checkRecursion方法。

有一些细节要弄明白......可能exprs[0]是“if”解析器而不是exprs[1]

使用IfThenElse(p, q, r)实例化此解析器 - 应具有与And解析器相同的语法。

答案 1 :(得分:1)

我认为在pyparsing中会写一个:

oneParserToRuleThemAll = header1 + parser1 | header2 + parser2

如果标题行与'header1'匹配,则pyparsing将继续,并使用parser1进行其余的解析。否则它将尝试匹配'header2',如果匹配,将使用parser2。

使用动态解析器​​元素和解析操作绝对可以获得更多异国情调。这看起来像这样:

foo_parser = ...
bar_parser = ...

variable_parser = Forward()
switch_parser = Literal("foo") | Literal("bar")
def select_variable_parser(tokens):
    if tokens[0] == "foo":
        variable_parser <<= foo_parser
    if tokens[0] == "bar":
        varaible_parser <<= bar_parser
switch_parser.setParseAction(select_variable_parser)
parser = switch_parser + variable_parser

注意使用“shift-into”运算符&lt;&lt; =通过插入先前定义的Forward()来定义解析器的可变部分。

但我认为这更容易理解:

parser = "foo" + foo_parser | "bar" + bar_parser