2010-05-30 39 views
1

我正在解析像「CS 2110或INFO 3300」這樣的句子。我想輸出像格式:PyParsing:並非所有的令牌傳遞給setParseAction()

[[("CS" 2110)], [("INFO", 3300)]] 

要做到這一點,我想我可以用setParseAction()。然而,在statementParse()print陳述表明,只有最後一個令牌實際傳遞:

>>> statement.parseString("CS 2110 or INFO 3300") 
Match [{Suppress:("or") Re:('[A-Z]{2,}') Re:('[0-9]{4}')}] at loc 7(1,8) 
string CS 2110 or INFO 3300 
loc: 7 
tokens: ['INFO', 3300] 
Matched [{Suppress:("or") Re:('[A-Z]{2,}') Re:('[0-9]{4}')}] -> ['INFO', 3300] 
(['CS', 2110, 'INFO', 3300], {'Course': [(2110, 1), (3300, 3)], 'DeptCode': [('CS', 0), ('INFO', 2)]}) 

我希望所有的令牌傳遞,但它只是['INFO', 3300]。難道我做錯了什麼?還是有另一種方法可以產生所需的輸出?

這裏是pyparsing代碼:(!你只在Optional設置)

from pyparsing import * 

def statementParse(str, location, tokens): 
    print "string %s" % str 
    print "loc: %s " % location 
    print "tokens: %s" % tokens 

DEPT_CODE = Regex(r'[A-Z]{2,}').setResultsName("DeptCode") 
COURSE_NUMBER = Regex(r'[0-9]{4}').setResultsName("CourseNumber") 

OR_CONJ = Suppress("or") 

COURSE_NUMBER.setParseAction(lambda s, l, toks : int(toks[0])) 

course = DEPT_CODE + COURSE_NUMBER.setResultsName("Course") 

statement = course + Optional(OR_CONJ + course).setParseAction(statementParse).setDebug() 

回答

2

爲了從「CS 2110」和「信息保持令牌位3300" ,我建議你換你的課程的定義組:

course = Group(DEPT_CODE + COURSE_NUMBER).setResultsName("Course") 

它也像你是在解析出某種搜索表達式的充電頭,喜歡‘X和Y或Z’。這個問題有一些微妙之處,我建議你在pyparsing wiki上查看一些關於如何構建這些表達式的例子。否則,你會以Optional("or" + this)ZeroOrMore( "and" + that)塊的燕窩結束。作爲最後一搏,你甚至可以只使用一些與operatorPrecedence,如:

DEPT_CODE = Regex(r'[A-Z]{2,}').setResultsName("DeptCode")   
COURSE_NUMBER = Regex(r'[0-9]{4}').setResultsName("CourseNumber") 
course = Group(DEPT_CODE + COURSE_NUMBER) 

courseSearch = operatorPrecedence(course, 
    [ 
    ("not", 1, opAssoc.RIGHT), 
    ("and", 2, opAssoc.LEFT), 
    ("or", 2, opAssoc.LEFT), 
    ]) 

(您可能需要下載從SourceForge的SVN最新的1.5.3版本,這個工作)

+0

呀,「正面充電」是描述我在做什麼的一種很好的方式。感謝指向維基上的例子的指針。 – 2010-05-31 01:28:11

2

作品更好,如果你設置course解析動作和Optional

>>> statement = (course + Optional(OR_CONJ + course)).setParseAction(statementParse).setDebug() 
>>> statement.parseString("CS 2110 or INFO 3300")  

給出

Match {Re:('[A-Z]{2,}') Re:('[0-9]{4}') [{Suppress:("or") Re:('[A-Z]{2,}') Re:('[0-9]{4}')}]} at loc 0(1,1) 
string CS 2110 or INFO 3300 
loc: 0 
tokens: ['CS', 2110, 'INFO', 3300] 
Matched {Re:('[A-Z]{2,}') Re:('[0-9]{4}') [{Suppress:("or") Re:('[A-Z]{2,}') Re:('[0-9]{4}')}]} -> ['CS', 2110, 'INFO', 3300] 
(['CS', 2110, 'INFO', 3300], {'Course': [(2110, 1), (3300, 3)], 'DeptCode': [('CS', 0), ('INFO', 2)]}) 

雖然我懷疑你真正想要的是設置解析動作上的每個當然,而不是在聲明

>>> statement = course + Optional(OR_CONJ + course) 
>>> statement.parseString("CS 2110 or INFO 3300")        Match {Re:('[A-Z]{2,}') Re:('[0-9]{4}')} at loc 0(1,1) 
string CS 2110 or INFO 3300 
loc: 0 
tokens: ['CS', 2110] 
Matched {Re:('[A-Z]{2,}') Re:('[0-9]{4}')} -> ['CS', 2110] 
Match {Re:('[A-Z]{2,}') Re:('[0-9]{4}')} at loc 10(1,11) 
string CS 2110 or INFO 3300 
loc: 10 
tokens: ['INFO', 3300] 
Matched {Re:('[A-Z]{2,}') Re:('[0-9]{4}')} -> ['INFO', 3300] 
(['CS', 2110, 'INFO', 3300], {'Course': [(2110, 1), (3300, 3)], 'DeptCode': [('CS', 0), ('INFO', 2)]})