根据以前的结果选择解析器
choose parser based on previous results
我正在解析多个输出,这些文件有两个不同的 headers:
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 中创建相同的函数?
注意:我不知道 先验 输出是笛卡尔坐标还是球坐标。
这里是一个应该可行的解决方案的概要。这个想法是实现一个新的解析器class,它运行一个解析器并根据返回的标记在两个备选方案之间进行选择。
# 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
解析器相同的语法。
我认为在 pyparsing 中会写:
oneParserToRuleThemAll = header1 + parser1 | header2 + parser2
如果 header 行匹配 '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" 运算符 <<= 通过插入 previously-defined Forward() 来定义解析器的变量部分。
但我认为这样更容易理解:
parser = "foo" + foo_parser | "bar" + bar_parser
我正在解析多个输出,这些文件有两个不同的 headers:
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 中创建相同的函数?
注意:我不知道 先验 输出是笛卡尔坐标还是球坐标。
这里是一个应该可行的解决方案的概要。这个想法是实现一个新的解析器class,它运行一个解析器并根据返回的标记在两个备选方案之间进行选择。
# 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
解析器相同的语法。
我认为在 pyparsing 中会写:
oneParserToRuleThemAll = header1 + parser1 | header2 + parser2
如果 header 行匹配 '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" 运算符 <<= 通过插入 previously-defined Forward() 来定义解析器的变量部分。
但我认为这样更容易理解:
parser = "foo" + foo_parser | "bar" + bar_parser