parsing - 在没有所有可用包或加载所有内容的情况下从 lisp 读取/解析常见的 lisp 文件

标签 parsing lisp common-lisp reader

我正在做一个涉及解析 common lisp repos 历史的项目。我需要将它们解析为列表列表或类似的东西。理想情况下,我想以某种方式尽可能多地保留原始源文件语法。例如,在文本 #+sbcl <something> 的情况下,我认为这意味着“如果我们当前的 lisp 是 sbcl,请阅读 <something> ,否则跳过它”,我想得到类似 (#+ 'sbcl <something>) 的东西.

我最初用 Python 编写了一个 LALR 解析器,它可以工作,但由于很多原因它并不理想。我很难获得正确的输出,而且我有很多特殊情况要添加。

我认为我真正应该做的是使用 lisp 本身,因为它已经内置了一个 lisp 解析器。如果我可以将文件读入 sexps,我可以将它转储到某些东西中(cl-json 可以)用于进一步处理。

不幸的是,当我尝试阅读 https://github.com/fukamachi/woo/blob/master/src/woo.lisp 时, 我得到错误

There is no package with the name WOO.EV.TCP

这当然来自该文件的第 80 行,因为该包是在 src/ev/tcp.lisp 中定义的,我们还没有读过。

基本上,是否可以只将文件读入 sexps 而无需关心包是否已定义或它们是否包含相关符号?如果是这样,如何?我已经尝试查看 hyperspec 阅读器文档,但我没有看到任何听起来相关的内容。

我没有实际编写通用 lisp 的实践,但似乎可能通过创建一个具有该名称的空白包并处理 no 来处理未定义的包条件来解决这个问题- 包中那个名称的符号条件,只需驻留给定的符号即可。我认为。我不知道如何真正做到这一点,我不知道它是否行得通,我不知道会涉及多少特殊情况。副手,第一个条件称为 no-such-package , 但第二个(至少在 sbcl 中)称为 simple-error ,所以我什至不知道如何确定这个特定的 simple-error是 no-such-symbol-in-that-package 错误,更不用说如何从条件中提取相关名称、修复它并重新启动了。我真的很想听一位普通的 lisp 专家说,在我尝试这样做之前,这是在这里做的正确的事情,因为它需要大量的学习。

我还想到,我可以通过在读取文件之前对文件执行 sed 来解决这个问题。例如。车削 woo.ev.tcp:start-listening-socket比如说,woo.ev.tcp===start-listening-socket .我不是特别喜欢这个解决方案,也不清楚我是否会遇到更多丑陋的特殊情况,但如果没有更好的答案,它可能会奏效。

最佳答案

我几乎可以肯定,出于多种原因,没有简单的可移植方法来执行此操作。

(暂时只限于不存在的包问题。)

首先,没有可移植的访问读取器的位,读取器决定 token 将成为符号,然后查找包标记 &c:这只是根据 2.3 中的规则发生的。 .所以你不能轻易干预。

其次,在读者可能发出信号以能够处理它们的任何类型的条件下,都没有足够的可移植信息。

有几种可能的方法可以解决这个问题。

如果你觉得自己足够英勇,你也许可以告诉读者所有的 token 起始字符实际上都是你控制的东西,然后编写一个 token 阅读器,通过返回一些对象以某种方式处理整个包的事情不是一个符号。但要做到这一点,您需要处理数字,如果您认为这很简单,那么事实并非如此。

如果你觉得不那么英勇,你可以编写一个更原始的 token 阅读器,它甚至不尝试处理任何事情,除了获取所有需要的字符并返回某种包装字符串的对象。这将以丢失大量信息为代价避免整数问题。

如果您不关心可移植性,请找到一个实现,了解它的读者是如何实现的,然后随意使用它。开源或源代码可用的实现比我容易数的多(也许我不是很擅长数),所以这是一个很好的方法。这当然是我会做的。


但这只是问题的开始。 CL 阅读器是毛茸茸的,在其标准配置中(用于诸如 compile-file 之类的配置,除非人们另有安排)可以在读取时运行完全任意的代码,包括修改读者本身,其中一些可能以依赖于实现的方式这样做。人们使用它:Lisp 被称为“可编程编程语言”是有原因的,因为人们会对其进行编程。

关于parsing - 在没有所有可用包或加载所有内容的情况下从 lisp 读取/解析常见的 lisp 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56202844/

相关文章:

random - 生成随机 ASCII 字符

loops - 如何比较 lisp 中长度或结构不完全相同的两个列表?

common-lisp - 用不同的lambda列表重新定义泛型函数

sql - 将 DSL 转换为 SQL 的正确工具?

html - net/html 解析文档,无论如何返回 nil *html.Node

java - 将 Java 属性文件转换为 JSON 字符串

Clojure:为什么我不能在不调用它们的情况下引用类方法?

emacs - 通过 cl 函数传递回调

lisp - "Cons"在 Lisp 中如何工作?

java - 在 java jsoup 的 html 页面中搜索和查找变量值