在Emacs Lisp中保存大量位置对的最佳方法

时间:2014-09-18 14:48:00

标签: emacs elisp tokenize overlays

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

a)它必须快速,非常快;

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

原始的tokenizer版本只是在使用regexps浏览缓冲区文本时构建一个令牌列表;列表中的每个标记都是4个元素的向量([' TOKENTYPE" token-lexeme" linum charnum])。 Linum / charnum是简单的数字,指定lexing完成时缓冲区中的标记位置。简单派。

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

这里有两个问题:

a)令牌位置应该是动态的(即,如果用户在缓冲区的开头添加了一些文本 - >我们不应该在缓冲区结束时修复令牌);

b)获取损坏令牌(或一般许多令牌)的方法。

现在我正在尝试使用叠加层来完成任务,因为叠加层有一个很好的界面,可以满足我的需求:叠加/叠加功能有助于搜索;和覆盖开始/结束以适当的方式移动。

我很乐意为较小的文件做到这一点。但事实证明(并且我不得不承认我被文档警告)该解决方案无法扩展:即使平均1K LOC文件也可以具有CONST * LOC叠加,这对于Emacs而言太过分了。

这是我的第一次尝试,并不是一次成功的尝试。我正在考虑其他替代方案:

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

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

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

上述方法的任何替代方案?或者可能有更好的方法来处理大量的叠加层?

2 个答案:

答案 0 :(得分:5)

与Lindydancer一样,我建议您使用文本属性而不是叠加层。叠加比例为O(N ^ 2),而文本属性比例为O(N log N),因此效果更好。我不会对其中的任何一个使用font-lock,等等。

当然,另一种解决方案是修复叠加层:可以更改C代码使其为O(N log N)。我现在已经知道如何做到这一点,但是没有找到时间(而且在任何可预见的未来都不太可能找到时间),所以如果有人对我感兴趣,我会我很乐意帮助他做到这一点。

答案 1 :(得分:3)

叠加层的替代方法是文字属性,它们以叠加方式附加到文本中,因此效率更高。

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

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