我正在将通常的完全重启标记器(从原始语言解析器移植,语言在这里无关紧要)转换为更高级的增量标记器。这意味着以下内容:
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)某种混合方法,包括普通数字和标记。
上述方法的任何替代方法?或者也许有更好的方法来处理大量的覆盖?