如何编写*可中断*递归(?)下降解析器

时间:2014-04-17 10:50:30

标签: parsing recursive-descent interruption non-recursive

我有一个非常标准的递归下降解析器。该算法很简单:每个函数从stream读取字符并返回FAIL或调用后续的解析函数(由相应的语法规则指定):

function parseFoo() {
  var ret = parseBar(stream);
  if (ret == FAIL) {
    ret = parseQuax(stream);
    ...
  }
  ...
  return ret;
}

我想解决一下我没有完整stream的情况 - 我异步得到它的碎片。因此我需要的是“可中断性”的特性 - 我必须能够保存解析器的状态,然后从那时起继续。

可悲的是,这是嵌套函数调用无法做到的一件事,因为解析器的所有状态都“存储”在调用堆栈中(按函数和局部变量的顺序)。

所以我必须以不同的方式构建parse*函数。

我使用的语言是 JavaScript

有人可以指出任何想法如何继续吗?

编辑:

  • 我觉得我需要某种状态机。我无法将头围绕在发电机或延续通道式上,它在我看来,在保存状态和恢复中存在很多故障。对我来说,我能想到的最明确的途径是将嵌套调用转换为某种堆栈,将局部变量重写为存储在堆栈项中的某些散列映射,并以不同的线性方式构造解析代码,以便我可以轻松地“转到” “到某个州。

  • 我看到的一个子问题可能是这样的:因为我没有完整的stream我必须尝试多个路径并存储所有部分解析的尝试。例如,如果语法显示a = b | c,那么b可能会很长,以至于它不完全在stream中。所以我不能在解析b时“挂起”,我必须尝试两者并保存部分计算。我是对的吗?

1 个答案:

答案 0 :(得分:1)

这取决于所使用的编程语言。

你基本上需要continuations的一些支持(你可以理解为调用堆栈的抽象)。换句话说,您可能希望使用continuation passing style(CPS)进行编码。

如果使用C编码,您可能会对CPC感兴趣。

如果使用Javascript编码,您可能需要在CPS中手动编码。另请参阅thisthisthis questionthis页等....