3

语境:

当我了解解析器时,编译代码(比如 C++)的过程是这样解释的:

  1. 将代码写入文件并保存。
  2. 将文件放入编译器。
  3. 编译器首先将代码解析成抽象语法树,
  4. 然后生成机器码。
  5. 运行代码来测试它。
  6. 重复。

Bret Victor 想要一种在您键入时评估代码的编程环境。( http://worrydream.com/#!/InventingOnPrinciple )

我想他不是第一个,将这个概念转换为 2D 游戏编程之外的通用编程可能存在一些概念问题,而且我知道有些系统已经做了类似的事情:例如 preadsheets(如 Excel),短暂聊天。

这不是我想讨论的。


问题:(有点宽泛,抱歉——主要问题是粗体字

编辑时如何解析文本?我的想法是,每当编辑器发送一个事件,指示文本的某些部分被更改时,只有一部分 AST 会被重新评估,并且受 AST 的这一部分影响的值也会被重新评估。

我考虑编写一个解析器生成器,它像往常一样采用语法,但生成一个解析器来处理文本的增量更改,而不是整个文本。

1. 这是一个合理的概念吗?(对于任何晦涩难懂的编程语言/环境。可能是“功能反应式”的东西。或者只是 html。)

(2.) 它甚至可能使用过吗?

(3.) 解析整个文件的速度是否足以让复杂的方法变得不必要?

(4.) Eclipse 等 IDE 中的语法高亮显示或类型检查器是否像这样工作?它们是如何工作的?我认为它们不如编译器解析器强大,无法让它们工作得足够快,对吗?

(5.) 在 Stackoverflow 中,有样式文本的实时预览。它会在每次击键后解析整个问题吗?它是否有一些“我的”概念可以解决的限制?

4

3 回答 3

4

tab-completion(或“intellisense”)需要与解析非常相似的东西,以便找出合理的完成/跟随可能是什么。您可能在某些 IDE 中对此有一些经验。如果是这样,您也会注意到它的一些限制。

像 SO 的预览功能这样的系统会定期解析输入,但不一定在每次击键时解析。您可能会注意到语法突出显示有点滞后,尤其是在缓冲区已满时。一个典型的策略是让一个进程重复重新解析,直到在解析过程中输入没有改变,然后等待下一次改变。

vim 和 emacs 等文本编辑器在每次击键时都会重新解析,但它们会通过在行尾缓存上下文来优化(通常),因此重新解析只针对几个字符。(当然,他们不做完整的解析,所以更容易。)

已经对抽象语法树的增量解析和就地编辑进行了一些研究,但它变得相当棘手。一种自然适用于这种风格的解析策略是“packrat 解析”(可在此处获得广泛的参考书目)。

众所周知,C++ 很难正确解析。确实,要弄清楚给定<是模板括号还是小于号,这并非易事。一般来说,如果不阅读所有头文件就无法做到这一点,并且在某些情况下,如果不实例化模板就无法弄清楚;交互式地做太多的工作。许多其他语言更容易解析,并且定期重新解析的简单解决方案对于所有实际目的来说都足够快。

希望这能解决你的大部分问题。

于 2013-02-03T01:22:45.673 回答
2

这绝对是一个有趣的问题。我使用的解析器有点类似于您在我的 GoWorks 演示 IDE 中描述的解析器。这是一个显示解析器运行的视频(从 5 分钟开始):

Tunnel Vision Labs 的 GoWorks IDE 简介(预览版 7)

解析器不会每次都解析整个文件,因为必要的解析信息只能来自输入的一个子集。解析比这更多有几个缺点,包括以下主要项目。

  1. 如果您解析文件的不必要部分,并且这些部分包含语法错误(用户正在积极编辑时的常见情况),则解析器可能无法准确地从错误中恢复。
  2. 解析比必要更多的信息,即使速度足够快以使用户看起来“流畅”,也会对移动用户的电池寿命产生重大影响。

据我所知,我们最新的 IDE 是唯一积极使用他们使用的特定样式的解析器(这是您所描述的为在 IDE 中使用而设计的一个非常具体的子集)作为多种语言的通用方法的唯一IDE。

于 2013-02-03T04:28:14.663 回答
1

它主要通过以下两种方式之一完成:

  • 使用一个更简单的原始解析器,它只包含足够的信息来着色。足够快,因为它很简单,可能会绊倒复杂的语言功能。
  • 将位置信息放在 AST 中,然后修复树。如果您保留一些历史记录,则可以避免将当前错误之后的所有内容都标记为错误。

Smalltalk 当然一次只解析一个方法。这使得解决方案更快更简单,错误解释的可能性也更少。打字时的重新分析可能会受到限制。只要标识符未被识别,在它之后重新解析部分就没有多大意义。

很久以前,有一个用于 mac(以及 ac one)的 think pascal 编译器,它运行得非常好。

于 2013-02-04T13:22:35.563 回答