【发布时间】:2016-04-07 10:14:41
【问题描述】:
我正在编写一个我打算在 Lisp 读取过程中实现的语法,即从可变的输入源一次读取一个表达式。大部分语法和 Lisp 一样,但有两个相关的变化是:
空白被读取并且是结果语法的一部分。连续的空白被分组在一起,就像连续的非空白字符被分组为标识符一样,读取这样一个字符串的结果是一个“空白对象”,它存储读取的字符的确切序列。当空白对象出现在列表中时,求值器会忽略它们(换句话说,如果 foo 是空白对象,则 (eval '(+ 3 foo 4)) 等效于 (eval '(+ 3 4))),如果要求它直接求值,它就是自求值。
其次,如果除空白标记之外的多个标记出现在同一行,这些标记将被收集到一个列表中,该列表就是读取的结果。
例如,
+ 3 4 5
(+ 3 4 5)
+ 3 4 (+ 1 4)
(+ 3 4 (+ 1 4))
都产生值 12。
是否可以将此阅读器实现为遵循读取过程的典型期望的 Lisp 读取过程?如果是这样,怎么做? (我很茫然。)
编辑:澄清空白:
如果我们说“空白对象”只是一个字符串并被读取,那么reading 以下段:
(foo bar baz)
产生一个语法对象,如:
'(foo " " bar " " baz)
换句话说,记号之间的空格存储在生成的语法对象中。
假设我写了一个名为 -> 的宏,它接受一个语法对象(方案风格的宏),而whitespace? 是一个识别空格语法对象的谓词
(define-macro (-> stx)
(let* ((stxl (syntax-object->list stx))
(obj (car stxl))
(let proc ((res empty))
(lst (cdr stxl)))
(let ((method (car lst)))
(if (whitespace? method)
; skip whitespace, recur immediately
(proc res (cdr lst))
; Insert obj as the second element in method
(let ((modified-method (cons (car method)
(cons obj (cdr method)))))
; recur
(proc (cons res modified-method) (cdr lst))))))))
【问题讨论】:
-
我不确定您所说的“空白已被读取并且是结果语法的一部分”是什么意思。你能提供一个例子来说明这方面吗?
-
我想你在这里要求一些不同的东西。我认为,词法分析/解析部分相对简单。您只需要编写一个词法分析器来生成您要查找的标记,然后编写将它们组合成结果的解析器。你后来关于基于行的输入的事情听起来像是一个不同的函数,你会在其中执行 read-line 然后从行中读取所有表达式,如果有多个表达式,或者只有一个,但请注意列表,您会将结果放入列表中。但是,您的评估者需要是一个真正的新事物。
-
我添加了一个示例。空白对象类似于符号,不同之处在于它仅包含空白字符,并且评估器会忽略它而不是查找符号。
-
关于评估器,您提到评估期间会忽略“空白对象”。
'(<whitespace object>)之类的会发生什么?那是空列表吗?是函数调用吗?现在,突然之间,你的表情中出现了一些奇怪的东西。(eval '<whitespace-object>)返回什么?(eval '(list <whitespace-object>))怎么样? -
是的,我知道我能做到,我的问题是它是否可以按照 lisp 读取过程的典型约定来完成(即从可变输入流中一次读取一个表达式)?