5

我正在将通常的完全重启标记器(从原始语言解析器移植,语言在这里无关紧要)转换为更高级的增量标记器。这意味着以下内容:

a) 必须快,非常快;

b) 在每次文本更新(无论是插入还是删除)时,它都必须找到损坏的令牌并相应地修复令牌列表。

原始标记器版本只是在使用正则表达式遍历缓冲区文本时构建标记列表;列表中的每个标记都是 4 个元素的向量 (['TOKENTYPE "token-lexeme" linum charnum])。Linum/charnum 是在 lexing 完成时指定缓冲区中标记位置的纯数字。容易的馅饼。

现在,说到重点。每当(嗯..不是每次,但经常)用户添加或删除一个字符(或字符串)时,新的标记器必须找到一个使用更改位置的文本构建的标记,并且可能是以后的依赖标记删除/更新。

这里有两个问题:

a) 标记位置应该是动态的(即,如果用户在缓冲区的开头添加一些文本 -> 我们不应该费心在缓冲区末端固定标记);

b) 一种获取损坏代币(或很多代币)的方法。

现在我正在尝试使用叠加层来完成任务,因为叠加层有一个适合我需要的漂亮界面:overlays-at/overlays-in 功能有助于搜索;并以适当的方式覆盖开始/结束移动。

对于较小的文件,我可以很高兴地做到这一点。但事实证明(我不得不承认文档警告我)该解决方案无法扩展:即使是平均 1K LOC 文件也可以有 CONST * LOC 覆盖,这对于 Emacs 来说太多了。

那是我的第一次尝试,但并不成功。我正在考虑替代方案,例如:

1) 使用纯数字管理手写令牌搜索树;

2) 相同的树,但使用标记;

3)某种混合方法,包括普通数字和标记。

上述方法的任何替代方法?或者也许有更好的方法来处理大量的覆盖?

4

2 回答 2

5

像 Lindydancer 一样,我建议您使用文本属性而不是叠加层。覆盖像 O(N^2) 一样缩放,而文本属性像 O(N log N) 一样缩放,所以效果更好。我不会对任何一个使用 font-lock 。

当然,另一种解决方案是修复覆盖:可以将 C 代码更改为 O(N log N)。我已经知道如何做到这一点已有一段时间了,但还没有找到时间(在任何可预见的将来都不太可能找到时间),所以如果有人感兴趣,我很乐意帮助他做到这一点。

于 2014-09-19T01:26:49.713 回答
3

覆盖的替代方法是文本属性,它们以覆盖所没有的方式附加到文本,因此它们更有效。

大量使用文本属性的包是font-lock。通常,它用于突出显示缓冲区,但没有什么可以阻止您为自己的目的捎带它。这样,您将获得整个系统来检测用户是否免费修改了缓冲区的内容。

在您的情况下,您可以将 font-lock 关键字中的正则表达式替换为将使用搜索限制调用的函数。您需要做的就是扫描相对较短的部分,设置您自己的文本属性,然后您就完成了。(此外,您必须使用 . 通知 font-lock 您正在设置哪个属性font-lock-extra-managed-props。)

于 2014-09-18T15:05:46.410 回答