|
8 | 8 |
|
9 | 9 | (in-package :diff-backend/lexer) |
10 | 10 |
|
11 | | -(declaim (optimize safety (debug 3))) |
| 11 | +(declaim (optimize (debug 3))) |
12 | 12 |
|
13 | 13 | (defclass* lexem () |
14 | | - ((line |
15 | | - :accessor lexem-line |
16 | | - :initarg :line |
17 | | - :type integer) |
18 | | - (column |
19 | | - :accessor lexem-column |
20 | | - :initarg :column |
21 | | - :type integer) |
22 | | - (type |
23 | | - :accessor lexem-type |
24 | | - :initarg :type |
25 | | - :type symbol) |
26 | | - (string |
27 | | - :accessor lexem-string |
28 | | - :initarg :string |
29 | | - :type string)) |
30 | | - (:documentation "Lexem info")) |
| 14 | + ((id |
| 15 | + :accessor id |
| 16 | + :initarg :id) |
| 17 | + (line |
| 18 | + :accessor lexem-line |
| 19 | + :initarg :line |
| 20 | + :type integer) |
| 21 | + (column |
| 22 | + :accessor lexem-column |
| 23 | + :initarg :column |
| 24 | + :type integer) |
| 25 | + (type |
| 26 | + :accessor lexem-type |
| 27 | + :initarg :type |
| 28 | + :type symbol) |
| 29 | + (string |
| 30 | + :accessor lexem-string |
| 31 | + :initarg :string |
| 32 | + :type string)) |
| 33 | + (:documentation "Lexem info")) |
| 34 | + |
| 35 | +(defclass* lexem-error () |
| 36 | + ((error-text |
| 37 | + :accessor error-text |
| 38 | + :initarg :error-text) |
| 39 | + (error-lex-id |
| 40 | + :accessor error-lex-id |
| 41 | + :initarg :error-lex-id))) |
31 | 42 |
|
32 | 43 | (defmethod print-object ((lex lexem) stream) |
33 | 44 | (with-slots (line column string) lex |
|
38 | 49 | (with-slots ((line1 line) |
39 | 50 | (column1 column) |
40 | 51 | (type1 type) |
41 | | - (string1 string)) |
| 52 | + (string1 string) |
| 53 | + (id1 id)) |
42 | 54 | lex1 |
43 | 55 | (with-slots ((line2 line) |
44 | 56 | (column2 column) |
45 | 57 | (type2 type) |
46 | | - (string2 string)) |
| 58 | + (string2 string) |
| 59 | + (id2 id)) |
47 | 60 | lex2 |
48 | 61 | (and (= line1 line2) |
49 | 62 | (= column1 column2) |
50 | 63 | (eq type1 type2) |
51 | | - (string= string1 string2))))) |
| 64 | + (string= string1 string2) |
| 65 | + (or (= id1 -1) |
| 66 | + (= id2 -1) |
| 67 | + (= id1 id2)))))) |
52 | 68 |
|
53 | | -(defun make-lexem (string line column type) |
| 69 | +(defun make-lexem (string line column type &key (id -1)) |
54 | 70 | (make-instance 'lexem |
55 | 71 | :string string |
56 | 72 | :line line |
57 | 73 | :column column |
58 | | - :type type)) |
| 74 | + :type type |
| 75 | + :id id)) |
59 | 76 |
|
60 | 77 | (defun is-lexem-symbol?= (lexem symbol-string) |
61 | 78 | (when (eq (lexem-type lexem) :symbol) |
|
92 | 109 | (when char1 |
93 | 110 | (char= char1 char2))) |
94 | 111 |
|
| 112 | +(defparameter *cur-id* 0) |
| 113 | + |
95 | 114 | (defun lexer (file-str) |
96 | | - (let ((stream (make-string-input-stream file-str)) |
| 115 | + (let ((*cur-id* 0) |
| 116 | + (stream (make-string-input-stream file-str)) |
97 | 117 | (lexems) |
98 | 118 | (comments-table (make-hash-table)) |
99 | 119 | (lex-errors) |
|
122 | 142 | ((ch= cur-char #\;) (go COMMENT)) |
123 | 143 | ((is-whitespace? cur-char) (go WHITESPACE)) |
124 | 144 | ((null cur-char) (go END)) |
125 | | - (t (error "Incorrect char ~s~%" cur-char))) |
| 145 | + (t (go ERROR_LEXEM))) |
126 | 146 | INTEGER |
127 | 147 | (incf column) |
128 | 148 | (push cur-char lexem-l) |
|
138 | 158 | (push (make-lexem (coerce (reverse lexem-l) 'string) |
139 | 159 | cur-lexem-line |
140 | 160 | cur-lexem-column |
141 | | - :integer) |
| 161 | + :integer |
| 162 | + :id (incf *cur-id*)) |
142 | 163 | lexems) |
143 | 164 | (setf lexem-l nil) |
144 | 165 | (go COMMON) |
|
154 | 175 | (push (make-lexem (coerce (reverse lexem-l) 'string) |
155 | 176 | line |
156 | 177 | cur-lexem-column |
157 | | - :symbol) |
| 178 | + :symbol |
| 179 | + :id (incf *cur-id*)) |
158 | 180 | lexems) |
159 | 181 | (setf lexem-l nil) |
160 | 182 | (go COMMON) |
161 | 183 | OUT_LEFT_PARENT |
162 | 184 | (push (make-lexem "(" |
163 | 185 | line |
164 | 186 | cur-lexem-column |
165 | | - :left-parent) |
| 187 | + :left-parent |
| 188 | + :id (incf *cur-id*)) |
166 | 189 | lexems) |
167 | 190 | (setf cur-char (read-char stream nil)) |
168 | 191 | (incf column) |
|
171 | 194 | (push (make-lexem ")" |
172 | 195 | line |
173 | 196 | cur-lexem-column |
174 | | - :right-parent) |
| 197 | + :right-parent |
| 198 | + :id (incf *cur-id*)) |
175 | 199 | lexems) |
176 | 200 | (setf cur-char (read-char stream nil)) |
177 | 201 | (incf column) |
|
188 | 212 | (push (make-lexem "'" |
189 | 213 | line |
190 | 214 | cur-lexem-column |
191 | | - :quote) |
| 215 | + :quote |
| 216 | + :id (incf *cur-id*)) |
192 | 217 | lexems) |
193 | 218 | (incf column) |
194 | 219 | (setf cur-char (read-char stream nil)) |
|
205 | 230 | ((ch= cur-char #\") |
206 | 231 | (push cur-char lexem-l) |
207 | 232 | (go OUT_STRING)) |
| 233 | + ((null cur-char) |
| 234 | + (go ERROR_LEXEM_OUT)) |
208 | 235 | (t (go STRING))) |
209 | 236 | STRING_ESCAPE_SYMBOL |
210 | 237 | (incf column) |
|
215 | 242 | (push (make-lexem (coerce (reverse lexem-l) 'string) |
216 | 243 | cur-lexem-line |
217 | 244 | cur-lexem-column |
218 | | - :string) |
| 245 | + :string |
| 246 | + :id (incf *cur-id*)) |
219 | 247 | lexems) |
220 | 248 | (setf lexem-l nil) |
221 | 249 | (setf cur-char (read-char stream nil)) |
|
236 | 264 | :column ,cur-lexem-column)) |
237 | 265 | (setf lexem-l nil) |
238 | 266 | (go COMMON) |
| 267 | + ERROR_LEXEM |
| 268 | + (incf column) |
| 269 | + (push cur-char lexem-l) |
| 270 | + (setf cur-char (read-char stream nil)) |
| 271 | + (cond ((or (ch= cur-char #\() |
| 272 | + (ch= cur-char #\)) |
| 273 | + (ch= cur-char #\') |
| 274 | + (ch= cur-char #\") |
| 275 | + (ch= cur-char #\;) |
| 276 | + (is-whitespace? cur-char) |
| 277 | + (null cur-char)) |
| 278 | + (go ERROR_LEXEM_OUT)) |
| 279 | + (t (go ERROR_LEXEM))) |
| 280 | + ERROR_LEXEM_OUT |
| 281 | + (push (make-lexem (coerce (reverse lexem-l) 'string) |
| 282 | + cur-lexem-line |
| 283 | + cur-lexem-column |
| 284 | + :error-lexem |
| 285 | + :id (incf *cur-id*)) |
| 286 | + lexems) |
| 287 | + (setf lexem-l nil) |
| 288 | + (push (make-instance |
| 289 | + 'lexem-error |
| 290 | + :error-text (format nil "At (~S:~S) error lexem" cur-lexem-line cur-lexem-column) |
| 291 | + :error-lex-id *cur-id*) |
| 292 | + lex-errors) |
| 293 | + (go COMMON) |
239 | 294 | END |
240 | 295 | (return)) |
241 | 296 | (values (reverse lexems) |
|
0 commit comments