【发布时间】:2019-10-05 18:08:32
【问题描述】:
我正在做一个涉及解析常见 lisp 存储库历史的项目。我需要将它们解析为列表列表或类似的东西。理想情况下,我想以某种方式尽可能多地保留原始源文件语法。例如,对于文本 #+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 -symbol-of-that-name-in-package 条件仅通过实习给定符号。我认为。我不知道如何真正做到这一点,我不知道它是否会起作用,我不知道会涉及多少特殊情况。顺便说一句,第一个条件称为no-such-package,但第二个(至少在sbcl中)称为simple-error,所以我什至不知道如何确定这个特定的simple-error是否是no-such-symbol -in-that-package 错误,更不用说如何从条件中提取相关名称、修复它并重新启动。我真的很想听听一位普通的 lisp 专家说,在我尝试这样做之前,这是正确的做法,因为这需要大量的学习。
我还想到,我可以通过在读取文件之前对文件进行 sed-ing 来解决这个问题。例如。将woo.ev.tcp:start-listening-socket 变成,比如说,woo.ev.tcp===start-listening-socket。我不是特别喜欢这个解决方案,也不清楚我是否会遇到更多丑陋的特殊情况,但如果没有更好的答案,它可能会起作用。
【问题讨论】:
-
我很确定你不能(通常)在不执行 Lisp 的一部分的情况下解析 Lisp,因为你可以在解析时运行任意代码,然后可以修改阅读器,以便解析以下所有代码不同。 (另请参阅:如果不实现完整的 Perl 解释器,解析 Perl 是不可能的,这也是同样的问题。)
-
我知道这一点,但它不必是一个完全通用的解析器。这就是我解释用例的原因。
-
这里有两个非常相似的问题:stackoverflow.com/questions/52405865/reading-qualified-symbolsstackoverflow.com/questions/53127961/…我很犹豫是否将它们标记为重复,因为意图似乎不同。
-
我敢打赌,有专门的阅读器实现可以做到这一点。普通的 CL 阅读器不支持它。在 CL 中,需要先定义一个包,然后才能读取带有包前缀的符号。
-
@Svante 这正是我正在寻找的 w/r/t 包装符号,尽管我还有其他问题。我想这有点重复。
标签: parsing lisp common-lisp reader