你的第二个问题很简单,所以我先回答这个问题。更改查询以将结果名称分配给不同的表达式:
query = ( zipcode("zip") | foo("foo") )
现在您可以在返回的结果上调用 getName() :
print t,"->", results, results.getName()
给予:
80517 -> ['80517'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['90001-3234'] zip
! sfs -> ['! sfs'] foo
如果您打算使用结果的 fooness 或 zipness 来调用另一个函数,那么您可以在解析时通过将解析操作附加到您的 foo 和 zipcode 表达式来执行此操作:
# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')
query = ( zipcode("zip") | foo("foo") )
现在给出:
80517 -> ['*80517*'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['*90001-3234*'] zip
! sfs -> ['#! sfs#'] foo
对于您的第一个问题,我不完全知道您的意思是哪种功能。Pyparsing 提供了比 Regex 更多的解析类(例如 Word、Keyword、Literal、CaselessLiteral),您可以通过将它们与 '+'、'|'、'^'、'~'、'@' 和'*' 运算符。例如,如果您想解析美国社会安全号码,但不使用正则表达式,您可以使用:
ssn = Combine(Word(nums,exact=3) + '-' +
Word(nums,exact=2) + '-' + Word(nums,exact=4))
由其构造函数中的给定字符组成的连续“单词”的单词匹配,Combine 将匹配的标记连接成单个标记。
如果您想解析这些数字的潜在列表,由“/”分隔,请使用:
delimitedList(ssn, '/')
或者如果有 1 到 3 个这样的数字,没有分隔符,请使用:
ssn * (1,3)
并且任何表达式都可以附加结果名称或解析操作,以进一步丰富解析结果或解析过程中的功能。您甚至可以使用 Forward 类构建递归解析器,例如嵌套的括号列表、算术表达式等。
当我编写 pyparsing 时,我的意图是这种由基本构建块组成的解析器组合将是创建解析器的主要形式。只是在后来的版本中,我才将正则表达式添加为(我认为是)最终的逃生阀——如果人们无法构建他们的解析器,他们可能会求助于正则表达式的格式,随着时间的推移,这已经证明了它的强大功能。
或者,正如另一张海报所建议的那样,您可以打开 pyparsing 源,并将现有类中的一个子类化,或者按照它们的结构编写自己的类。这是一个匹配配对字符的类:
class PairOf(Token):
"""Token for matching words composed of a pair
of characters in a given set.
"""
def __init__( self, chars ):
super(PairOf,self).__init__()
self.pair_chars = set(chars)
def parseImpl( self, instring, loc, doActions=True ):
if (loc < len(instring)-1 and
instring[loc] in self.pair_chars and
instring[loc+1] == instring[loc]):
return loc+2, instring[loc:loc+2]
else:
raise ParseException(instring, loc, "Not at a pair of characters")
以便:
punc = r"~!@#$%^&*_-+=|\?/"
parser = OneOrMore(Word(alphas) | PairOf(punc))
print parser.parseString("Does ** this match @@@@ %% the parser?")
给出:
['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']
(请注意省略尾随单“?”)