-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathparser.lisp
More file actions
96 lines (89 loc) · 3.12 KB
/
Copy pathparser.lisp
File metadata and controls
96 lines (89 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
(defpackage #:paras/parser
(:use #:cl
#:paras/types)
(:shadowing-import-from #:paras/special
#:quote
#:lambda)
(:shadowing-import-from #:paras/errors
#:parser-error
#:end-of-file
#:undefined-function)
(:import-from #:paras/user
#:%
#:%1
#:%2
#:%3
#:%4
#:%5)
(:import-from #:named-readtables
#:defreadtable
#:find-readtable)
(:export #:parse-string
#:parse))
(in-package #:paras/parser)
(defun quote-reader (stream char)
`(quote ,(read stream t nil t)))
(defun maptree (fn tree)
(labels ((rec (tree)
(etypecase tree
(atom (funcall fn tree))
(cons (cons (rec (car tree))
(if (cdr tree)
(rec (cdr tree))
nil))))))
(if (null tree)
nil
(rec tree))))
(defvar *in-lambda-reader* nil)
(defun lambda-reader (stream char)
(when *in-lambda-reader*
(error "Nested ~A()s are not allowed" char))
(let ((form (let ((*in-lambda-reader* t))(read stream t nil t)))
(args (make-array 5 :element-type 'bit :initial-element 0))
(restargs (gensym))
(%-used nil))
(flet ((add-arg (n)
(setf (aref args (1- n)) 1)))
(let ((form
(maptree (lambda (x)
(case x
(%
(add-arg 1)
(setf %-used t))
((%1 %2 %3 %4 %5)
(add-arg
(parse-integer (subseq (string x) 1)))))
x)
form))
(lambda-list '())
(ignored-args '()))
(dotimes (i (1+ (or (position 1 args :from-end t)
-1)))
(when (zerop (aref args i))
(push (intern (format nil "%~D" (1+ i))) ignored-args))
(push (intern (format nil "%~D" (1+ i))) lambda-list))
`(lambda (,@(nreverse lambda-list) &rest ,restargs ,@(and %-used '(&aux (% %1))))
(declare (ignore ,restargs ,@(nreverse ignored-args)))
,form)))))
(defreadtable paras
(:macro-char #\( (get-macro-character #\())
(:macro-char #\) (get-macro-character #\)))
(:macro-char #\" (get-macro-character #\"))
(:macro-char #\' #'quote-reader)
(:macro-char #\^ #'lambda-reader))
(defun parse (&optional (stream *standard-input*))
(let ((*readtable* (find-readtable 'paras))
(*package* (find-package '#:paras-user)))
(let ((code
(handler-case
(read stream)
(cl:end-of-file ()
(error 'end-of-file))
(error (e)
(error 'parser-error :error e)))))
(unless (typep code 'paras-type)
(error 'type-not-allowed :value code))
code)))
(defun parse-string (code)
(with-input-from-string (stream code)
(parse stream)))