如何在Lisp中实现解析原始字符串的读取器宏
Common Lisp 实现类Python原始字符串读取器宏
实现目标
对齐Python r"c:\data" 原始字符串特性:字符串内的反斜杠直接识别为字面量,无需重复转义,专门用于书写Windows路径,全程保留反斜杠不做正斜杠替换,兼容不识别正斜杠路径的Windows命令。
核心逻辑
- 选用
#r作为宏触发前缀,和Python的r前缀记忆逻辑一致,学习成本低 - 读取到
#r标记后,直接读取后续双引号包裹的所有字符,不对反斜杠做任何转义解析 - 兼容双引号字面量场景:约定连续两个双引号代表字符串内的一个双引号字符,和Python原始字符串规则对齐
完整实现代码
(defun raw-string-reader (stream char arg) (declare (ignore char arg)) ;; 校验#r后必须紧跟双引号 (unless (char= (read-char stream t nil t) #\") (error "语法错误:#r 原始字符串后必须紧跟双引号")) (coerce (loop for c = (read-char stream t nil t) when (char= c #\") do (let ((next (peek-char nil stream t nil t))) (if (char= next #\") ;; 连续双引号:吃掉第二个双引号,保留一个双引号到结果 (read-char stream t nil t) ;; 单个双引号:字符串读取结束 (return))) collect c) 'string)) ;; 注册读取宏到Common Lisp的分派读取宏表 (set-dispatch-macro-character #\# #\r #'raw-string-reader)
使用方法
加载上述代码完成读取宏注册后,即可直接书写无转义的Windows路径:
;; 直接写路径,所有反斜杠自动识别为字面量 CL-USER> #r"C:\Users\Admin\Documents\report.docx" "C:\\Users\\Admin\\Documents\\report.docx" ;; 直接传给Windows系统命令,无需额外转义处理 CL-USER> (uiop:run-program (concatenate 'string "type " #r"d:\logs\app.log"))
注意事项
- 该读取宏仅适合书写Windows路径、正则表达式这类反斜杠为字面量的场景,不要用来写需要
\n/\t等转义序列的普通字符串 - 若需要在原始字符串内包含双引号,连续书写两个双引号即可,例如
#r"note: ""path with space"""会被解析为note: "path with space"
内容的提问来源于stack exchange,提问作者f l
相关产品推荐
相关产品推荐

