Coverage report: /home/ellis/comp/core/lib/parse/lex.lisp
Kind | Covered | All | % |
expression | 78 | 220 | 35.5 |
branch | 4 | 28 | 14.3 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; lib/parse/lex.lisp --- Lexer Tools
3
;; https://github.com/Shinmera/plump/blob/master/lexer.lisp
7
;; TODO: make less dynamic, compile lexer functions for compatibility
11
(in-package :parse/lex)
12
(declaim (optimize (speed 3) (safety 1)))
16
(defvar *matchers* (make-hash-table))
17
(declaim (fixnum *length* *index*)
18
(simple-string *string*)
19
(hash-table *matchers*))
21
(defmacro with-lexer-environment ((string) &body body)
22
`(let* ((*string* ,string)
23
(*string* (etypecase *string*
24
(simple-string *string*)
25
(string (copy-seq *string*))))
26
(*length* (length *string*))
28
(handler-bind ((error #'(lambda (err)
29
(declare (ignore err))
30
(format T "Error during lexing at index ~a~%" *index*))))
33
(declaim (ftype (function () (or character null)) consume)
36
(declare (optimize (speed 3) (safety 0)))
37
(when (< *index* *length*)
38
(prog1 (aref *string* *index*)
39
#+debug (format T "~a +~%" *index*)
42
(declaim (ftype (function () (or fixnum null)) advance)
45
(declare (optimize (speed 3) (safety 0)))
46
(when (< *index* *length*)
47
#+debug (format T "~a +~%" *index*)
50
(declaim (ftype (function () fixnum) unread)
53
(declare (optimize (speed 3) (safety 0)))
55
#+debug (format T "~a -~%" *index*)
59
(declaim (ftype (function () (or character null)) peek)
62
(declare (optimize (speed 3) (safety 0)))
63
(when (< *index* *length*)
64
#+debug (format T "~a ?~%" *index*)
65
(aref *string* *index*)))
67
(declaim (ftype (function (fixnum) fixnum) advance-n)
70
(declare (optimize (speed 3) (safety 0)))
72
#+debug (format T "~a +~d~%" *index* n)
74
(when (<= *length* *index*)
75
(setf *index* *length*))
78
(declaim (ftype (function (fixnum) fixnum) unread-n)
81
(declare (optimize (speed 3) (safety 0)))
83
#+debug (format T "~a -~d~%" *index* n)
89
(declaim (ftype (function (function) string) consume-until))
90
(defun consume-until (matcher)
91
(declare (function matcher))
92
(loop with start = *index*
93
until (funcall matcher)
95
finally (return (subseq *string* start *index*))))
97
(declaim (ftype (function (character) function) matcher-character))
98
(defun matcher-character (character)
102
(char= char character)))))
104
(declaim (ftype (function (simple-string) function) matcher-string))
105
(defun matcher-string (string)
106
(declare (simple-string string))
107
(let ((len (length string)))
109
(let ((len (+ *index* len)))
110
(and (<= len *length*)
111
(string= string *string* :start2 *index* :end2 len))))))
113
(declaim (ftype (function ((or fixnum character string) (or fixnum character string)) function) matcher-range))
114
(defun matcher-range (from to)
115
(flet ((normalize (in) (etypecase in
117
(character (char-code in))
118
(simple-string (char-code (char in 0))))))
119
(let ((from (normalize from))
124
(<= from (char-code char) to)))))))
126
(declaim (ftype (function (list) function) matcher-find))
127
(defun matcher-find (list)
130
(and char (member char list :test #'char=)))))
132
(declaim (ftype (function (&rest function) function) matcher-or))
133
(defun matcher-or (&rest matchers)
135
(loop for matcher of-type function in matchers
136
thereis (funcall matcher))))
138
(declaim (ftype (function (&rest function) function) matcher-and))
139
(defun matcher-and (&rest matchers)
141
(loop for matcher of-type function in matchers
142
always (funcall matcher))))
144
(declaim (ftype (function (function) function) matcher-not))
145
(defun matcher-not (matcher)
146
(declare (function matcher))
148
(not (funcall matcher))))
150
(declaim (ftype (function (function) function) matcher-next))
151
(defun matcher-next (matcher)
153
(let ((*index* (1+ *index*)))
154
(when (< *index* *length*)
155
(funcall matcher)))))
157
(declaim (ftype (function (function) function) matcher-prev))
158
(defun matcher-prev (matcher)
160
(let ((*index* (1- *index*)))
162
(funcall matcher)))))
164
(defmacro matcher-any (&rest is)
165
`(matcher-or ,@(loop for i in is
166
collect `(,(typecase i
167
(string 'matcher-string)
168
(character 'matcher-character)
169
(T 'matcher-string)) ,i))))
171
(defmacro make-matcher (form)
172
(labels ((transform (form)
175
`(gethash ',form *matchers*))
179
(case (find-symbol (string (car form)) "PARSE/LEX")
183
(is (typecase (second form)
184
(string 'matcher-string)
185
(character 'matcher-character)
186
(T 'matcher-string)))
193
(mapcar #'transform (cdr form)))))))
196
(defmacro define-matcher (name form)
197
`(setf (gethash ,(intern (string name) "KEYWORD") *matchers*) (make-matcher ,form)))