如何使用Lisp将数字列表转换为分隔字符串?
给定以下代码:如何使用Lisp将数字列表转换为分隔字符串?,lisp,common-lisp,s-expression,Lisp,Common Lisp,S Expression,给定以下代码: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Copyright (C) 2014 Wojciech Siewierski ;; ;; ;; ;; This progra
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Copyright (C) 2014 Wojciech Siewierski ;;
;; ;;
;; This program is free software: you can redistribute it and/or modify ;;
;; it under the terms of the GNU General Public License as published by ;;
;; the Free Software Foundation, either version 3 of the License, or ;;
;; (at your option) any later version. ;;
;; ;;
;; This program is distributed in the hope that it will be useful, ;;
;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;
;; GNU General Public License for more details. ;;
;; ;;
;; You should have received a copy of the GNU General Public License ;;
;; along with this program. If not, see <http://www.gnu.org/licenses/>. ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar *output*)
(defvar *indent*)
(defun format-tag (symbol &optional arg)
(cond
((equal arg 'begin)
(format nil "~{~a~}<~(~a~)" *indent* symbol))
((equal arg 'end)
(format nil "~{~a~}<~(/~a~)>~%" *indent* symbol))
(t
(format nil "~{~a~}~a~%" *indent* symbol))))
(defun sexp-to-xml--inside-tag (sexp)
(if sexp
(if (listp (car sexp))
(progn
(sexp-to-xml--new-tag (car sexp))
(sexp-to-xml--inside-tag (cdr sexp)))
(progn
(push (format-tag
(string (car sexp)))
*output*)
(sexp-to-xml--inside-tag (cdr sexp))))))
(defun sexp-to-xml--attrs (plist)
(when plist
(push (format nil " ~(~a~)=~s"
(car plist)
(cadr plist))
*output*)
(sexp-to-xml--attrs (cddr plist))))
(defun sexp-to-xml--new-tag (sexp)
(if (listp (car sexp))
(progn
(push (format-tag (caar sexp) 'begin)
*output*)
(sexp-to-xml--attrs (cdar sexp)))
(push (format-tag (car sexp) 'begin)
*output*))
(unless (cdr sexp)
(push (format nil " /")
*output*))
(push (format nil ">~%")
*output*)
(let ((*indent* (cons " " *indent*)))
(sexp-to-xml--inside-tag (cdr sexp)))
(when (cdr sexp)
(push (format-tag (if (listp (car sexp))
(caar sexp)
(car sexp))
'end)
*output*)))
(defun sexp-to-xml-unquoted (&rest sexps)
(apply #'concatenate 'string
(apply #'concatenate 'list
(loop for sexp in sexps collecting
(let ((*output* nil)
(*indent* nil))
(reverse (sexp-to-xml--new-tag sexp)))))))
(defmacro sexp-to-xml (&rest sexps)
`(format *standard-output* "~a"
(sexp-to-xml-unquoted ,@(loop for sexp in sexps collecting
`(quote ,sexp)))))
(defun file-get-contents (filename)
(with-open-file (stream filename)
(let ((contents (make-string (file-length stream))))
(read-sequence contents stream)
contents)))
(defun file-get-lines (filename)
(with-open-file (stream filename)
(loop for line = (read-line stream nil)
while line
collect line)))
(defun list-to-string (lst)
(format nil "~{~A~}" lst))
(defun test1()
(let((input (file-get-contents "sample2.sexp")))
(format t (sexp-to-xml-unquoted (read-from-string "(head (title \"my-site\"))")))
)
)
(defun test2()
(let((input (file-get-lines "sample2.sexp")))
(loop for sexp in input do (print (write-to-string sexp)))
)
)
(defun test3()
(let((input (file-get-lines "sample2.sexp")))
(format t (list-to-string input))
)
)
(defun :str->lst (str / i lst)
(repeat (setq i (strlen str))
(setq lst (cons (substr str (1+ (setq i (1- i))) 1) lst))))
(defun print-elements-recursively (list)
(when list ; do-again-test
(print (car list)) ; body
(print-elements-recursively ; recursive call
(cdr list)))) ; next-step-expression
(defun tokenize( str )(read-from-string (concatenate 'string "(" str
")")))
(defun test4()
(let((input (file-get-contents "sample2.sexp")))
(print-elements-recursively (tokenize input) )
)
)
(defun test5()
(let((input (file-get-contents "sample2.sexp")))
(print (sexp-to-xml-unquoted (tokenize input)))
)
)
(defun test6()
(let((input (file-get-contents "sample2.sexp")))
(loop for sexp in (tokenize input) do (
with-input-from-string (s (write-to-string sexp) )
(print ( sexp-to-xml-unquoted (read s)) )
)
)
)
)
(defun test7()
(let((input (file-get-contents "sample2.sexp")))
(loop for sexp in (tokenize input) do (
print sexp
)
)
)
)
(defun test8()
(let((input (file-get-contents "sample2.sexp")))
(format t (sexp-to-xml-unquoted (read-from-string input)))
)
)
但使用test8会产生一个错误:
7 is not a string designator.
这让我写了一个这样的文件:
(supertux瓷砖)
(tilegroup
(名称(“雪”))
(瓷砖
"7"
)
)
)
然后它会很好地编译并生成xml,但我不知道如何将所有整数转换为它们的字符串表示形式,从列表中读取。我尝试解析字符串并使用write-to-string方法,但我认为我遗漏了一些东西
任何帮助都将受到感激
谢谢
--编辑--
将princ字符串更改为coredump建议的字符串可以修复字符串中原始数字的解析计算,但是,当尝试计算t等符号时,会发生以下情况:
没有为#\T定义分派函数
以以下内容为例
(tile
; dupe of tile 70, this one will be removed.
(id 63)
(deprecated #t)
(images
"tilesets/background/backgroundtile1.png"
)
)
不过,看起来,对Lisp之外的变量求值将只通过检查“t”xml标记来保持
这个问题解决了。在谷歌上快速搜索,可以找到以下存储库();链接的代码足以重现错误。请注意,当我从Emacs/Slime内部运行它时,调试器会显示回溯:
0: (STRING 7)
1: (SEXP-TO-XML--INSIDE-TAG (7 8 9 202 13 14 ...))
2: (SEXP-TO-XML--NEW-TAG (TILES 7 8 9 202 13 ...))
3: (SEXP-TO-XML--INSIDE-TAG ((TILES 7 8 9 202 13 ...)))
4: (SEXP-TO-XML--INSIDE-TAG ((NAME (_ "Snow")) (TILES 7 8 9 202 13 ...)))
5: (SEXP-TO-XML--NEW-TAG (TILEGROUP (NAME (_ "Snow")) (TILES 7 8 9 202 13 ...)))
6: (SEXP-TO-XML--INSIDE-TAG ((TILEGROUP (NAME #) (TILES 7 8 9 202 13 ...))))
7: (SEXP-TO-XML--NEW-TAG (SUPERTUX-TILES (TILEGROUP (NAME #) (TILES 7 8 9 202 13 ...))))
8: (SEXP-TO-XML-UNQUOTED (SUPERTUX-TILES (TILEGROUP (NAME #) (TILES 7 8 9 202 13 ...))))
在上面列出的各种堆栈帧上按v键,我可以在调用堆栈中找到代码当前暂停的位置
我没有加载lisp文件,只是在当前Emacs缓冲区中计算了不同的表单,因此没有与函数关联的源文件。但是,AST表单是为了调试而存储的,调试器可以精确定位当前代码执行的位置,并用一个伪(#::***此处***…)
表单包装:
(SB-INT:NAMED-LAMBDA SEXP-TO-XML--INSIDE-TAG
(SEXP)
(BLOCK SEXP-TO-XML--INSIDE-TAG
(IF SEXP
(IF (LISTP (CAR SEXP))
(PROGN
(SEXP-TO-XML--NEW-TAG (CAR SEXP))
(SEXP-TO-XML--INSIDE-TAG (CDR SEXP)))
(PROGN
(PUSH (FORMAT-TAG (#:***HERE*** (STRING (CAR SEXP)))) *OUTPUT*)
(SEXP-TO-XML--INSIDE-TAG (CDR SEXP)))))))
对任意值调用
string
将不起作用,您需要在sexp to xml--inside标记中用princ to string
替换它。然后它就如预期的那样工作了。在谷歌上快速搜索,可以找到以下存储库();链接的代码足以重现错误。请注意,当我从Emacs/Slime内部运行它时,调试器会显示回溯:
0: (STRING 7)
1: (SEXP-TO-XML--INSIDE-TAG (7 8 9 202 13 14 ...))
2: (SEXP-TO-XML--NEW-TAG (TILES 7 8 9 202 13 ...))
3: (SEXP-TO-XML--INSIDE-TAG ((TILES 7 8 9 202 13 ...)))
4: (SEXP-TO-XML--INSIDE-TAG ((NAME (_ "Snow")) (TILES 7 8 9 202 13 ...)))
5: (SEXP-TO-XML--NEW-TAG (TILEGROUP (NAME (_ "Snow")) (TILES 7 8 9 202 13 ...)))
6: (SEXP-TO-XML--INSIDE-TAG ((TILEGROUP (NAME #) (TILES 7 8 9 202 13 ...))))
7: (SEXP-TO-XML--NEW-TAG (SUPERTUX-TILES (TILEGROUP (NAME #) (TILES 7 8 9 202 13 ...))))
8: (SEXP-TO-XML-UNQUOTED (SUPERTUX-TILES (TILEGROUP (NAME #) (TILES 7 8 9 202 13 ...))))
在上面列出的各种堆栈帧上按v键,我可以在调用堆栈中找到代码当前暂停的位置
我没有加载lisp文件,只是在当前Emacs缓冲区中计算了不同的表单,因此没有与函数关联的源文件。但是,AST表单是为了调试而存储的,调试器可以精确定位当前代码执行的位置,并用一个伪(#::***此处***…)
表单包装:
(SB-INT:NAMED-LAMBDA SEXP-TO-XML--INSIDE-TAG
(SEXP)
(BLOCK SEXP-TO-XML--INSIDE-TAG
(IF SEXP
(IF (LISTP (CAR SEXP))
(PROGN
(SEXP-TO-XML--NEW-TAG (CAR SEXP))
(SEXP-TO-XML--INSIDE-TAG (CDR SEXP)))
(PROGN
(PUSH (FORMAT-TAG (#:***HERE*** (STRING (CAR SEXP)))) *OUTPUT*)
(SEXP-TO-XML--INSIDE-TAG (CDR SEXP)))))))
对任意值调用string
将不起作用,您需要在sexp to xml--inside标记中用princ to string
替换它。这完全解决了这个问题,但是,当使用t符号解析sexps时,它抛出以下命令:没有为#\t定义分派函数
#t不是标准的公共Lisp语法,它看起来像Scheme。在您的上下文中,只需编写T就可以解决问题。如果您必须解析现有代码,您可能需要添加一个reader函数。是的,因为我相信它的计算结果是一个可能是布尔值或其他值的现有变量,但只需编写T就可以了。我相信,我们只需要检查属性是否有值,这样读取T就足够了。谢谢这完全解决了问题,但是,当使用t符号解析sexps时,它抛出以下命令:没有为#\t
#定义分派函数,t不是标准的公共Lisp语法,它看起来像Scheme。在您的上下文中,只需编写T就可以解决问题。如果您必须解析现有代码,您可能需要添加一个reader函数。是的,因为我相信它的计算结果是一个可能是布尔值或其他值的现有变量,但只需编写T就可以了。我相信,我们只需要检查属性是否有值,这样读取T就足够了。谢谢