使用python和Ply解析器生成器时出错

时间:2014-11-03 13:32:01

标签: python parser-generator ply

我正在使用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似乎接受了两个参数......任何线索? 谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

让我们解决您的问题,作为追踪错误来源的教程。首先,我们列举您的示例代码与documentation for PLY

之间的差异数量
  1. 您在语法规则函数
  2. 上使用了装饰器
  3. 您使用了两个语法规则函数参数
  4. 您已使用空行启动语法规则
  5. 您使用了python的"""字符串表示法 - 未在手册中使用
  6. 您已使用手册中弃用的方式使用空白生产
  7. 您已指定programa的起始规则
  8. 这可以通过编写示例程序来解决,这些程序单独测试每个程序并显示它们是否有效,然后通过消除我们可以推断出你有错误的原因。

    幸运的是,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
    

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

      

    注意:只需指定一个空的右侧,您就可以在任何地方编写空规则。但是,我个人发现写一个“空”规则并使用“空”来表示空白生产更容易阅读,更清楚地表明你的意图。

    如果我们重写此规则以匹配您的风格,我们可以测试该假设:

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

    实验表明上述代码仍然有效,从而消除了原因5.我们现在留下原因1& 6.原因6很容易在代码中消除,我们留下了理由1.此外,所有可用工作PLY示例中的装饰器的grep都没有显示。这意味着没有人,即使是专家,也没有按照代码中显示的方式使用装饰器。我怀疑是有原因的。它们不起作用。 PLY中唯一使用装饰器的是具有复杂正则表达式的标记。

    结论

    1. 停止使用装饰器
    2. 修复开始符号programa
    3. Supply the necessary information when asking for help
    4. <小时/> [*] lexicoCLexer在哪里,prueba.txt在哪里?我是否必须定义自己的令牌并编写自己的词法分析器并猜测要解析的文本? ,你应该帮助我。