背景: 作为冬季休假的一个简短项目,我正在尝试使用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,但无法理解它是如何运作的。
任何帮助或提示都将不胜感激。
答案 0 :(得分:6)
“递归执行”不适合goto
。要使goto
起作用,您需要一台PC,一个“程序计数器”,程序中的每个语句都必须具有不同的地址。执行时,每个语句的地址都分配给PC。遇到goto
时,goto(它的参数)的目标地址被放入PC并从那里恢复执行。
使用基于堆栈的递归方法几乎不可能实现这一点。您有两种选择:
将您的AST压缩成一个序列,您可以为每个语句指定一个不同的地址
向解释器添加“跳过”模式。遇到goto
时,抛出一个GotoException
,它会突破所有堆栈帧并返回到根目录。流程语句(跳过它们而不执行),直到达到目标地址。
我认为你可以想象goto
的这种实现不是很有效,而且可能很难实现。
答案 1 :(得分:2)
我考虑过将树转换成平面阵列......但这似乎缺乏一定的优雅感,几乎感觉就像倒退一样(尽管我可能错了)。
你错了。机器代码始终是扁平的。像C这样的语言被展平以创建机器代码。
计算器(与其他简单机器一样)是平的。
然而。展平AX语法树并非完全必要。
您只需将编程源标签应用于树中的每个节点。
然后“GOTO”只是在树上搜索该标签并继续在该标签处执行。
答案 2 :(得分:0)
您还可以将AST展平为有向图(控制流图)。可以找到如何执行此操作以生成可由解释程序遍历的networkx
图表的示例here。请注意,您必须为此目的编写一些AST类。