我想尝试meta-sexp
套餐。它是类似PEG的解析器库。现在,它有一个方法create-parser-context
,只能采用string
或string-stream
。 (这是解析内容的来源。)但是,open
和朋友创建file-stream
。
我已查看flexi-streams
库,但无法找到直接转发的方式(我可以使用octets-to-string
创建缓冲区,将其提供给双向流等...但它有很多管道)。我觉得我错过了一些明显的东西,它应该像调用一些flexi-stream
包装函数一样简单。
答案 0 :(得分:0)
我认为您确实需要使用从系统meta-sexp自述文件转换流的方式:
meta-sexp使用内存中的字符串向量,而不是常用的 溪流,有效地前进和后退 输入
因此meta-sexp通常使用字符和字符串,它实现了一些类型的检查器:
CL-USER> (ql:quickload :meta-sexp)
To load "meta-sexp":
Install 1 Quicklisp release:
meta-sexp
Downloading http://beta.quicklisp.org/archive/meta-sexp/2010-10-06/meta-sexp-0.1.6.tgz
##########################################################################
; Loading "meta-sexp"
[package meta-sexp]......
(:META-SEXP)
CL-USER> (use-package :meta-sexp)
T
CL-USER> (alpha? #\c)
T
CL-USER> (alpha? #\3)
NIL
CL-USER> (digit? #\3)
3 (2 bits, #x3, #o3, #b11)
然后,您可以使用此定义规则来处理自述文件中的示例:
CL-USER> (defrule integer? (&aux (sign 1) d (num 0)) ()
(:? (:or (:and "-" (:assign sign -1))
"+"))
(:+ (:assign d (:type digit?))
(:assign num (+ (* num 10)
(- (char-code d) #.(char-code #\0)))))
(:return (* sign num)))
CL-USER> (defrule integer? (&aux (sign 1) d (num 0)) ()
(:? (:or (:and "-" (:assign sign -1))
"+"))
(:+ (:assign d (:type digit?))
(:assign num (+ (* num 10)
(- (char-code d) #.(char-code #\0)))))
(:return (* sign num)))
现在让我们假设我们有这个文件
parser-test.txt:
patata
123
calimero
34
32
我们可以阅读如下(read-line返回一个字符串):
CL-USER> (with-open-file (stream "parser-test.txt")
(loop for line = (read-line stream nil)
while line
do (print line)))
"patata"
"123"
"calimero"
"34"
"32"
NIL
然后应用解析器:
CL-USER>
; No values
CL-USER> (with-open-file (stream "parser-test.txt")
(loop for line = (read-line stream nil)
while line
do (print (integer? (create-parser-context line)))))
NIL
123
NIL
34
32
NIL
你可以按字符,按行读取文件......,看看hypersec函数read;最后,我会推荐这篇不错的帖子,上面有一篇关于lisp Lisp: It's Not About Macros, It's About Read
的重要课程