从文件流创建字符串流的简便方法

时间:2017-10-26 13:06:02

标签: parsing stream common-lisp

我想尝试meta-sexp套餐。它是类似PEG的解析器库。现在,它有一个方法create-parser-context,只能采用stringstring-stream。 (这是解析内容的来源。)但是,open和朋友创建file-stream

我已查看flexi-streams库,但无法找到直接转发的方式(我可以使用octets-to-string创建缓冲区,将其提供给双向流等...但它有很多管道)。我觉得我错过了一些明显的东西,它应该像调用一些flexi-stream包装函数一样简单。

1 个答案:

答案 0 :(得分:0)

我认为您确实需要使用从系统m​​eta-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

的重要课程