繁体   English   中英

Python:YACC遇到麻烦

Python: Trouble with YACC

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在使用PLY来解析句子,如:

“CS 2310或同等经验”

所需的输出:

[[("CS", 2310)], ["equivalent experience"]]

YACC tokenizer符号:

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

有没有办法看到解析器在失败时尝试了哪​​条规则? 或者其他一些方法来使解析器打印规则它的尝试?

UPDATE token_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 个回复

我无法重现您的错误,而是在“或”上出现语法错误。 您没有包含使用or_phrase的规则。 当我包含一个时,我没有错误。

我不认为这是一个优先问题。 如果您应该设置日志记录,这将有所帮助,以便您可以看到PLY正在采取的步骤,并将其与您想要发生的事情进行比较。 为此,将debug=1传递给解析函数(您可能还必须将其传递给yacc )。 如果无法进行调试,请查看PLY的yacc.py

发生减少/减少冲突是因为它是否应该将MISC_TEXT MISC_TEXT减少到text_aggregate MISC_TEXT或者是否应该将MISC_TEXT MISC_TEXT减少MISC_TEXT MISC_TEXT是不text_aggregate

无法重现问题,我最好的猜测是什么能解决你的错误是将p_misc_text规则更改为:

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

我想你也可以删除precedence元组。

3 在python中遇到乘法麻烦

我最近在用python练习时,每次运行此命令时都会遇到一个与乘法有关的小问题: 输入以下内容后,我得到此答案,例如5: 任何对解决问题有任何想法的人。 谢谢。 ...

2015-06-10 22:07:31 1 23   python
4 在python列表中遇到麻烦

函数satisfiesF()将字符串列表L作为参数。 函数f将字符串作为参数返回true或false。 函数satisfiesF()将L修改为仅包含f(s)返回true的那些字符串。 我有两个旨在产生相同输出的不同程序。 但是我得到了不同的输出。 第一个程序: 输出: ...

5 在Python中使用openssl遇到麻烦

首先,我不能使用任何第三方模块,并且由于这是一个大型企业环境,因此我的代码必须与Python 2.4配合使用,并且该工具必须在没有第三方模块的原始2.4 python安装环境下使用。 我正在为openssl写一个包装器,该包装器将用于检索/存储加密的数据,主要是用户名/密码和其他身份验证类 ...

6 我遇到python语法错误的麻烦

在观看有关如何解决cicada3301难题的视频时,我需要帮助。 其中一个,我忘记了哪一个,我说过python可以用来找到两个素数,当相乘时,将得出该数。 我尝试自己复制代码并在python中进行测试,但是我对应该如何运行它以及为什么会出现语法错误感到困惑。 代码如下所示: ...

10 在Python中循环浏览时遇到麻烦

我已经问过我周围的人,并无数次地尝试获取此修复程序。 该程序应该能够根据需要多次添加用户的网站和密码,并显示他们选择的网站和密码。 现在,当您回答时would you like to add another website? 是的,它并不需要输入新的网站名称和密码,只是重复了would ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM