2010-05-29 85 views
3

我使用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 

解析仍不能上一個語法錯誤,如上面。

+1

以防萬一你碰巧有選擇:看看http://pyparsing.wikispaces.com/ – miku 2010-05-29 18:26:46

+0

讓我來看看 - 看看Pyparsing。 – Escualo 2010-05-29 18:54:15

+0

如果我想,我可以切換到PyParsing。我看着它,但當時YACC似乎更直觀。 – 2010-05-29 19:03:38

回答

1

我無法重現您的錯誤,而是在「或」上出現語法錯誤。您沒有包含使用or_phrase的規則。當我包括一個,我沒有得到任何錯誤。

我不認爲這是一個優先問題。如果您應該設置日誌記錄以便您可以看到PLY正在執行的步驟,並將其與您想要發生的事情進行比較,這將有所幫助。爲此,請將debug=1傳遞給解析函數(您可能還必須將其傳遞給yacc)。如果您無法進行調試工作,請查看PLY的yacc.py

的減少/減少衝突發生,因爲它是不明確的,是否應該減少MISC_TEXT MISC_TEXTtext_aggregate MISC_TEXT,還是應減少MISC_TEXT MISC_TEXTtext_aggregate

而不能重現該問題,在什麼會改正錯誤我最好的猜測是對p_misc_text規則更改爲:

'''text_aggregate : MISC_TEXT | text_aggregate MISC_TEXT'''

我想你也可以刪除precedence元組。