我使用PLY解析喜歡的句子:的Python:麻煩與YACC
「CS 2310或同等經驗」
所需的輸出:
[[("CS", 2310)], ["equivalent experience"]]
YACC標記生成器符號:
tokens = [
'DEPT_CODE',
'COURSE_NUMBER',
'OR_CONJ',
'MISC_TEXT',
]
t_DEPT_CODE = r'[A-Z]{2,}'
t_COURSE_NUMBER = r'[0-9]{4}'
t_OR_CONJ = r'or'
t_ignore = ' \t'
terms = {'DEPT_CODE': t_DEPT_CODE,
'COURSE_NUMBER': t_COURSE_NUMBER,
'OR_CONJ': t_OR_CONJ}
for name, regex in terms.items():
terms[name] = "^%s$" % regex
def t_MISC_TEXT(t):
r'\S+'
for name, regex in terms.items():
# print "trying to match %s with regex %s" % (t.value, regex)
if re.match(regex, t.value):
t.type = name
return t
return t
(MISC_TEXT是爲了匹配任何不被其他方面已經趕上。)
相關的一些規則,從解析器:
precedence = (
('left', 'MISC_TEXT'),
)
def p_statement_course_data(p):
'statement : course_data'
p[0] = p[1]
def p_course_data(p):
'course_data : course'
p[0] = p[1]
def p_course(p):
'course : DEPT_CODE COURSE_NUMBER'
p[0] = make_course(p[1], int(p[2]))
def p_or_phrase(p):
'or_phrase : statement OR_CONJ statement'
p[0] = [[p[1]], [p[3]]]
def p_misc_text(p):
'''text_aggregate : MISC_TEXT MISC_TEXT
| MISC_TEXT text_aggregate
| text_aggregate MISC_TEXT '''
p[0] = "%s %s" % (p[0], [1])
def p_text_aggregate_statement(p):
'statement : text_aggregate'
p[0] = p[1]
不幸的是,這種失敗:
# works as it should
>>> token_list("CS 2110 or equivalent experience")
[LexToken(DEPT_CODE,'CS',1,0), LexToken(COURSE_NUMBER,'2110',1,3), LexToken(OR_CONJ,'or',1,8), LexToken(MISC_TEXT,'equivalent',1,11), LexToken(MISC_TEXT,'experience',1,22)]
# fails. bummer.
>>> parser.parse("CS 2110 or equivalent experience")
Syntax error in input: LexToken(MISC_TEXT,'equivalent',1,11)
我在做什麼錯誤?我不完全瞭解如何設置優先規則。
此外,這是我的錯誤功能:
def p_error(p):
print "Syntax error in input: %s" % p
有沒有辦法,看看哪個統治解析器試圖當它失敗了嗎?或者讓解析器打印哪個規則來嘗試其他方式?
UPDATEtoken_list()
只是一個輔助功能:
def token_list(string):
lexer.input(string)
result = []
for tok in lexer:
result.append(tok)
return result
更新2:這裏是我希望發生解析:
Symbol Stack Input Tokens Action
DEPT_CODE COURSE_NUMBER OR_CONJ MISC_TEXT MISC_TEXT
DEPT_CODE COURSE_NUMBER OR_CONJ MISC_TEXT MISC_TEXT Shift DEPT_CODE
DEPT_CODE COURSE_NUMBER OR_CONJ MISC_TEXT MISC_TEXT Shift COURSE_NUMBER
course OR_CONJ MISC_TEXT MISC_TEXT Reduce course : DEPT_CODE COURSE_NUMBER
course_data OR_CONJ MISC_TEXT MISC_TEXT Reduce course_data : course
statement OR_CONJ MISC_TEXT MISC_TEXT Reduce statement : course_data
statement OR_CONJ MISC_TEXT MISC_TEXT Shift OR_CONJ
statement OR_CONJ MISC_TEXT MISC_TEXT Shift MISC_TEXT
statement OR_CONJ text_aggregate MISC_TEXT Reduce text_aggregate : MISC_TEXT
statement OR_CONJ text_aggregate MISC_TEXT Shift MISC_TEXT
statement OR_CONJ text_aggergate Reduce text_aggregate : text_aggregate MISC_TEXT
statement OR_CONJ statement Reduce statement : TEXT_AGGREGATE
or_phrase Reduce or_phrase : statement OR_CONJ statement
statement Reduce statement : or_phrase
我加入這個分析動作:
def p_misc_text_singleton(p):
'text_aggregate : MISC_TEXT'
p[0] = p[1]
當我嘗試建立解析器,我得到這樣的輸出:
Generating LALR tables
WARNING: 2 shift/reduce conflicts
WARNING: 3 reduce/reduce conflicts
WARNING: reduce/reduce conflict in state 8 resolved using rule (text_aggregate -> MISC_TEXT MISC_TEXT)
WARNING: rejected rule (text_aggregate -> MISC_TEXT) in state 8
解析仍不能上一個語法錯誤,如上面。
以防萬一你碰巧有選擇:看看http://pyparsing.wikispaces.com/ – miku 2010-05-29 18:26:46
讓我來看看 - 看看Pyparsing。 – Escualo 2010-05-29 18:54:15
如果我想,我可以切換到PyParsing。我看着它,但當時YACC似乎更直觀。 – 2010-05-29 19:03:38