1

「CS 2110 or INFO 3300」のような文を解析しています。次のような形式で出力したいと思います。

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

これを行うには、 を使用できると思いsetParseAction()ました。ただし、次のprintステートメントはstatementParse()、最後のトークンのみが実際に渡されることを示唆しています。

>>> 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 コードは次のとおりです。

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()
4

2 に答える 2

2

と の両方 で解析アクションを設定すると、よりうまく機能します(! でのみ設定していました):courseOptionalOptional

>>> 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)]})
于 2010-05-31T00:29:16.053 に答える
2

「CS 2110」および「INFO 3300」からのトークン ビットを保持するために、もちろんグループで定義をラップすることをお勧めします。

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

また、「x and y or 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 バージョンをダウンロードする必要がある場合があります。)

于 2010-05-31T01:02:44.970 に答える