在ast中实现goto

时间:2011-12-27 07:58:49

标签: python interpreter goto abstract-syntax-tree ply

背景: 作为冬季休假的一个简短项目,我正在尝试使用Python和PLY实现一种名为Axe(专为图形计算器设计)的编程语言。简要说明:该语言仅允许全局变量,并大量使用指针。

我正在尝试用这种语言实现goto,但不知道该怎么做。

我的一般方法是首先使用PLY将代码解析为ast,然后在我执行时执行它。

例如,声明

If 3
    Disp 4
    Disp 6
End

......会变成......

['PROGRAM', 
  ['BLOCK', 
    ['IF', 
      ['CONDITION', 3], 
      ['BLOCK', 
        ['DISP', 4], 
        ['DISP', 6]
      ]
    ]
  ]
]

...我将以递归方式执行(为了便于阅读,我添加了缩进)。

因为ast是一棵树,我不知道如何在不同节点之间跳转。我考虑过将树转换为平面数组['IF', ['CONDITION', 3], ['DISP', 4], ['DISP', 6]],这样我就可以使用flat-ish数组的索引转到代码中的特定行,但这似乎缺乏一定的优雅和几乎感觉像是退步(虽然我可能是错的)。

我看过this,但无法理解它是如何运作的。

任何帮助或提示都将不胜感激。

3 个答案:

答案 0 :(得分:6)

“递归执行”不适合goto。要使goto起作用,您需要一台PC,一个“程序计数器”,程序中的每个语句都必须具有不同的地址。执行时,每个语句的地址都分配给PC。遇到goto时,goto(它的参数)的目标地址被放入PC并从那里恢复执行。

使用基于堆栈的递归方法几乎不可能实现这一点。您有两种选择:

  • 将您的AST压缩成一个序列,您可以为每个语句指定一个不同的地址

  • 向解释器添加“跳过”模式。遇到goto时,抛出一个GotoException,它会突破所有堆栈帧并返回到根目录。流程语句(跳过它们而不执行),直到达到目标地址。

我认为你可以想象goto的这种实现不是很有效,而且可能很难实现。

答案 1 :(得分:2)

  

我考虑过将树转换成平面阵列......但这似乎缺乏一定的优雅感,几乎感觉就像倒退一样(尽管我可能错了)。

你错了。机器代码始终是扁平的。像C这样的语言被展平以创建机器代码。

计算器(与其他简单机器一样)是平的。

然而。展平AX语法树并非完全必要

您只需将编程源标签应用于树中的每个节点。

然后“GOTO”只是在树上搜索该标签并继续在该标签处执行。

答案 2 :(得分:0)

您还可以将AST展平为有向图(控制流图)。可以找到如何执行此操作以生成可由解释程序遍历的networkx图表的示例here。请注意,您必须为此目的编写一些AST类。