【问题标题】:Error using python and the Ply parser generator使用 python 和 Ply 解析器生成器时出错
【发布时间】:2014-11-03 13:32:01
【问题描述】:

我正在使用 Ply 进行教学,我非常喜欢它。 我虽然使用装饰器来避免在某些函数中重复我想要的一些代码。 所以,我尝试使用以下代码:

import ply.yacc as yacc
from functools import wraps
from CLexer import Lexico


def producciones(function):
    """
    Decorator for each of the functions which represents
    grammatical rules.
    """
    variable = function.__doc__.split(':')[0].strip()
    @wraps(function)
    def wrapper(*args,**kargs):
        result = []
        for e in args[1][1:]:
            tmp = Node()
            if isinstance(e,Node):
                tmp = e 
            else:
                tmp.type = str(e)
            result.append(tmp)
        tmp = Node(result)
        tmp.type = variable
        args[1][0] = tmp
        function(*args, **kargs)
        return wrapper


class Sintaxis:

    tokens = Lexico.tokens
    start = 'programa'
    @producciones
    def p_program(self, p):
        """
        program : ABREPAREN program CIERRAPAREN program
        | 
        """



    def p_error(self, p):
        print("Syntax error at '%s'" % p.value)

    def run(self, s):
        lexico = Lexico()
        lexico.build()
        global tokens
        self.parser = yacc.yacc(debug = True, module= self)
        result =self.parser.parse(s,lexico)
        return  result




if __name__ == '__main__':
    with open("prueba.txt") as f:
        texto=f.read()
    parser = Sintaxis()
    result = parser.run(texto)

我的问题是尝试使用装饰器时,出现以下错误:

ERROR: new.py:15: Rule 'p_program' requires an argument

我在文档中没有发现这个错误,p_program 方法似乎接受了两个参数...有什么线索吗? 感谢您的帮助。

【问题讨论】:

  • return wrapper 可能缩进不正确。

标签: python parser-generator ply


【解决方案1】:

让我们将您的问题作为追踪错误来源的教程来解决。首先让我们列举一下您的示例代码和documentation for PLY 之间的差异数量:

  1. 您在语法规则函数中使用了装饰器
  2. 您在语法规则函数中使用了两个参数
  3. 您已使用空行开始语法规则
  4. 您使用了python的"""字符串表示法-手册中未使用
  5. 您以手册中不推荐使用的方式使用了空生产
  6. 您指定了不存在的programa 启动规则

这可以通过编写示例程序来解决,这些示例程序分别测试每个程序并显示它们是否有效,然后通过排除我们可以推断出您有错误的原因。

幸运的是,PLY 发行版包含几个工作示例,可以作为手册的附件进行参考,还有一些 linked from the PLY homepageOne of those examples 显示使用 """ 语法指定的规则,并且还为语法规则函数使用两个参数;这消除了原因 2 和 4:

def p_declaration(self, p):
        """ declaration : decl_body SEMI
        """
        p[0] = p[1]

如果我们检查更多PLY distribution 提供的示例,我们可以找到example\classcalc\calc.py,它具有以空行开头并使用""" 语法的规则,并且还有两个参数,排除了原因2, 3 & 4:

def p_expression_binop(self, p):
        """
        expression : expression PLUS expression
                  | expression MINUS expression
                  | expression TIMES expression
                  | expression DIVIDE expression
                  | expression EXP expression
        """

我们需要消除空生产符号问题。在分发中的所有示例程序上使用grep 揭示了一个使用盲生成的程序。这是 BASIC 解释器。这里(在文件examples\BASIC\basparse.py)我们有规则:

def p_optstep(p):
    '''optstep : STEP expr
               | empty'''
    if len(p) == 3:
       p[0] = p[2]
    else:
       p[0] = None

此规则显示了指定盲制作的推荐方式,但手册确实说:

注意:您可以在任何地方编写空规则,只需指定一个空的右侧。不过,我个人觉得写一个“empty”规则并用“empty”来表示一个空产生式更容易阅读,也更清楚地表达了你的意图。

如果我们重写这条规则以匹配你的风格,我们可以检验假设:

def p_optstep(p):
    '''optstep : STEP expr
               | '''
    if len(p) == 3:
       p[0] = p[2]
    else:
       p[0] = None

实验表明上述代码仍然有效,因此消除了原因 5。我们现在只剩下原因 1 和 6。原因 6 很容易在您的代码中消除,我们只剩下原因 1。进一步,grep 用于所有可用的工作 PLY 示例中的装饰器没有显示任何内容。这意味着没有人,即使是专家,也没有按照您的代码中显示的方式使用装饰器。我怀疑这是有原因的。他们不工作。 PLY 中装饰器的唯一用途是使用具有复杂正则表达式的标记。

结论

  1. 停止使用装饰器
  2. 修复开始符号programa
  3. Supply the necessary information when asking for help


[*] lexicoCLexer 在哪里,prueba.txt 在哪里?我是否必须定义自己的标记并编写自己的词法分析器并猜测要解析的文本? ,你应该帮我解决这个问题。

【讨论】:

  • 将问题标记为 MCVE 可能是明智的,但在标记 > 250 个类似问题并且标记超时后,关闭问题的最佳方法是实际回答!
  • 非常感谢,我不能投票给你回答,但它真的很有帮助。我是新手,但是,从现在开始,我会听从您的建议,并在发布之前三思而后行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
相关资源
最近更新 更多