使用两个不同的函数后,全局变量不会保持其状态

时间:2016-03-12 20:02:26

标签: python compiler-construction global-variables yacc

所以我好几天都遇到了麻烦。基本上,我正在使用python创建一种语言的编译器。我们得到了sintax和lexic部分,现在正在创建目录过程和变量表(符号表)。在我的Yacc文件中,我有:

Yacc.py

import ply.yacc as yacc
import sys

tokens = Lex.tokens
#Global variables
procs = { }
current_fid = ""

# add new value to the procedure directory
def add_procs_to_dict(fid, ftipo, fparams, fdict):
    proc_dict = {}
    proc_dict[fid] = {
        'Tipo' : ftipo,
        'Params' : fparams,
        'Var_dict' : fdict
    }
    return proc_dict

# add new variable value to the procedure directory
def add_vars_to_dict(vid, vtipo, vparams):
    var_dict = {
        'Nombre' : vid,
        'Tipo' : vtipo,
        'Params' : vparams
        }
    print(current_fid)
    print(procs)    
    return proc_dict


# Parsing Rules    
def p_juego(p):
    '''Juego : JUEGO ID DOSP JuegoA JuegoB MainProgram'''
    current_fid = p[2]
    procs = add_procs_to_dict( p[2], p[1], 'void', {})

def p_vars(p):
    '''Vars : VAR ID COR_I Exp COR_D VarSizeA Vars2 DOSP Tipo PCOMA'''
    add_vars_to_dict( p[2], p[9], p[4])

这里需要注意的重要一点是,我创建了一个保存当前ID的变量(名为current_fid,它是插入字典中的最后一个过程的名称)和一个字典变量(作为全局范围命名为procs的过程/函数目录。

当解析器输入解析规则p_juego(p):时(假设它被提供的代码是正确的,并且我已经单独运行它),它假设设置为变量(current_fid和{ {1}})它在解析器进程中找到的值。它确实设置了值。我可以在函数内打印变量并返回预期的值。

一旦解析器退出函数procs并进入另一个函数,如p_juego(p)(此函数在字典上写入插入全局目录的最后一个过程/函数的符号表)全局变量(p_vars(p)current_fid)在其中没有任何价值。 procs中有2个打印件,它们始终对变量显示为空。

我对python相对较新,也许我对这种语言缺失了一些东西。我的意图是如果我在所有事物(在代码的顶部)之前定义变量,那些使用那些变量的函数" global"变量将更新它们的值,并且即使另一个函数试图访问它们也始终保持它们。 我尝试在名为Semantics.py的新python文件中添加过程,但变量的值在先前设置该值的函数之外始终为null。

我在这里缺少什么?

3 个答案:

答案 0 :(得分:2)

为了避免这样的范围问题并且更明确,我建议你使用一个类。然后你可以使用self.variable来保存类方法调用之间的信息。

答案 1 :(得分:1)

[编辑] 您的代码中存在很多问题。

首先:

你的函数 add_vars_to_dict ,定义并分配一个你永远不会使用的字典( var_dict )并尝试返回函数作用域中不存在的东西(< EM> proc_dict )。

第二

函数 p_juego ,每次被调用时,都会重新显示dict的值,这会让你失去 procs 的先例值

procs = add_procs_to_dict( p[2], p[1], 'void', {})

但是,正如majodi所建议的那样,一般来说,您可以使用类来解决全局变量问题,在该类中使用实例变量而不是全局变量

类似的东西:

class ClassTest(object):

    def __init__(self):
        self.procs = {}
        self.current_fid = ""

    # add new value to the procedure directory
    def add_procs_to_dict(self, fid, ftipo, fparams, fdict):
        # do something

    # add new variable value to the procedure directory
    def add_vars_to_dict(self, vid, vtipo, vparams):
        # do something

    # Parsing Rules
    def p_juego(self, p):
        # do something

    def p_vars(self, p):
        # do something

答案 2 :(得分:0)

感谢大家的快速回复。我确实按照大多数人的建议创建了另一个类,但我没有保留全局值的原因是因为函数是按照我不期望的顺序调用的。 PLY库使用自下而上的过程来导航sintax树。实际上,在设置之前读取值时会调用函数。

我感谢所有人的回复,因为这是我在SO的第一篇文章,每个回复答案的人都鼓励我,我问了一个问题,甚至纠正了我的帖子以继续使用网站。

再次感谢。