2010-05-29 64 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元组。