在ast中实现goto

Mic*_*x2a 6 python interpreter goto ply abstract-syntax-tree

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

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

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

例如,声明

If 3
    Disp 4
    Disp 6
End
Run Code Online (Sandbox Code Playgroud)

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

['PROGRAM', 
  ['BLOCK', 
    ['IF', 
      ['CONDITION', 3], 
      ['BLOCK', 
        ['DISP', 4], 
        ['DISP', 6]
      ]
    ]
  ]
]
Run Code Online (Sandbox Code Playgroud)

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

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

我看过这个,但无法理解它是如何工作的.

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

Aar*_*lla 6

"递归执行"不适合goto.为了goto工作,你需要一台PC,一个"程序计数器",程序中的每个语句都必须有一个不同的地址.执行时,每个语句的地址都分配给PC.当goto遇到,goto语句(它的参数)的目标地址放入PC和执行从那里重新开始.

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

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

  • 向解释器添加"跳过"模式.当goto遇到,扔掉GotoException它打破了所有的栈帧,并追溯到根源.进程语句(跳过它们而不执行)直到达到目标地址.

我认为你可以想象这种实现goto方式并不是非常高效,而且可能很难实现.