Python 句法分析问题

Python 句法分析问题,python,parsing,text-parsing,pyparsing,Python,Parsing,Text Parsing,Pyparsing,此代码适用于: from pyparsing import * zipRE = "\d{5}(?:[-\s]\d{4})?" fooRE = "^\!\s+.*" zipcode = Regex( zipRE ) foo = Regex( fooRE ) query = ( zipcode | foo ) tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ] for t in tests: try: re

此代码适用于:

from pyparsing import *

zipRE = "\d{5}(?:[-\s]\d{4})?" 
fooRE = "^\!\s+.*"

zipcode = Regex( zipRE )
foo = Regex( fooRE )

query = ( zipcode | foo )



tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ]

for t in tests:
    try:
        results = query.parseString( t )
        print t,"->", results
    except ParseException, pe:
        print pe
我被困在两个问题上:

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

zipcode = Regex( zipRE )
也许:

zipcode = MyFunc()

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

您可以分别使用zipcode和foo,以便知道字符串匹配的是哪一个

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

您可以分别使用zipcode和foo,以便知道字符串匹配哪一个

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

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


您可以做的是从中创建子类,并根据需要重写方法以自定义行为,然后改用子类。

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


您可以做的是从中创建子类,并根据需要重写方法以自定义行为,然后使用您的子类。

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

query = ( zipcode("zip") | foo("foo") ) 
# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

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表达式:

query = ( zipcode("zip") | foo("foo") ) 
# 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))
构造器中由给定字符组成的连续“单词”的单词匹配将匹配的标记连接到单个标记中

如果要分析以“/”分隔的此类数字的潜在列表,请使用:

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")
给出:

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

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

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

query = ( zipcode("zip") | foo("foo") ) 
# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

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表达式:

query = ( zipcode("zip") | foo("foo") ) 
# 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))
构造器中由给定字符组成的连续“单词”的单词匹配将匹配的标记连接到单个标记中

如果要分析以“/”分隔的此类数字的潜在列表,请使用:

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")
给出:

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

(注意省略了尾随单曲“?”)

感谢您如此周到的回复。我昨晚真的梦到了这个。我想我有一个例子来说明我想做什么。pyparsing示例之一是解析街道地址。如果我想扩展这段代码来解析一个城市和州,该怎么办。我可以使用stateEncryption=oneOf(““”AA AE AK AL…(如您所提供的)。但是,如果我想通过调用另一段代码中的函数来解析一个城市,可能是isStringPlacenmae(),或者可能是一个Web服务,它会告诉我给定的字符串是否是地名……更多信息:我正在编写一个解析程序来cate