语法分析问题

2024-04-23 09:09:09 发布

您现在位置:Python中文网/ 问答频道 /正文

此代码起作用:

^{1}$

我被两个问题困住了:

1-如何使用自定义函数分析令牌。例如,如果我想使用一些自定义逻辑而不是正则表达式来确定一个数字是否是zipcode。 而不是:

^{pr2}$

或许:

zipcode = MyFunc()

2-如何确定字符串的解析结果。“80001”解析为“zipcode”,但是如何使用pyparsing来确定这一点?我不是分析字符串的内容,而是确定它是什么类型的查询。在


Tags: 函数字符串代码类型内容数字逻辑pyparsing
3条回答

你的第二个问题很简单,所以我先回答。更改查询以将结果名称分配给不同的表达式:

query = ( zipcode("zip") | foo("foo") ) 

现在可以对返回的结果调用getName():

^{pr2}$

给予:

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调用另一个函数,那么可以在解析时通过将parse操作附加到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、caselessteral),您可以通过将它们与“+”、“|”、“^”、“~”、“@”和“*”运算符组合来组成解析器。例如,如果要解析美国社会保险号,但不使用正则表达式,则可以使用:

ssn = Combine(Word(nums,exact=3) + '-' + 
        Word(nums,exact=2) + '-' + Word(nums,exact=4))

单词匹配在构造器中由给定字符组成的连续“单词”,Combine将匹配的标记连接到单个标记中。在

如果要分析这些数字的潜在列表(以“/”分隔),请使用:

delimitedList(ssn, '/')

或者,如果有1到3个这样的数字,没有限制,使用:

ssn * (1,3)

任何表达式都可以有结果名称或附加的解析操作,以进一步丰富解析的结果或解析过程中的功能。您甚至可以使用Forward类构建递归解析器,例如嵌套的括号列表、算术表达式等。在

我在编写pyparsing时的意图是,这种由基本构建块组成的解析器将成为创建解析器的主要形式。只是在后来的版本中,我才添加了Regex作为(我认为是)最终的逃逸阀——如果人们不能构建他们的解析器,他们可以使用Regex的格式,这肯定证明了它的强大功能。在

或者,正如另一张海报所建议的那样,您可以打开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']

(注意省略了尾随的单个“?”)在

我没有pyparsing模块,但是Regex必须是类,而不是函数。在

你可以做的是从它的子类和重写方法,以定制行为,然后使用你的子类。在

可以分别使用zipcode和foo,这样就可以知道字符串匹配哪一个。在

zipresults = zipcode.parseString( t )
fooresults = foo.parseString( t )

相关问题 更多 >