Commit | Line | Data |
---|---|---|
994e5cea | 1 | ;;; lex-spp.el --- Semantic Lexical Pre-processor |
7a0e7d33 | 2 | |
5df4f04c | 3 | ;; Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. |
7a0e7d33 CY |
4 | |
5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
6 | ||
7 | ;; This file is part of GNU Emacs. | |
8 | ||
9 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation, either version 3 of the License, or | |
12 | ;; (at your option) any later version. | |
13 | ||
14 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ||
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ;;; Commentary: | |
23 | ;; | |
24 | ;; The Semantic Preprocessor works with semantic-lex to provide a phase | |
25 | ;; during lexical analysis to do the work of a pre-processor. | |
26 | ;; | |
27 | ;; A pre-processor identifies lexical syntax mixed in with another language | |
28 | ;; and replaces some keyword tokens with streams of alternate tokens. | |
29 | ;; | |
30 | ;; If you use SPP in your language, be sure to specify this in your | |
31 | ;; semantic language setup function: | |
32 | ;; | |
33 | ;; (add-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook nil t) | |
34 | ;; | |
35 | ;; | |
36 | ;; Special Lexical Tokens: | |
37 | ;; | |
38 | ;; There are several special lexical tokens that are used by the | |
39 | ;; Semantic PreProcessor lexer. They are: | |
40 | ;; | |
41 | ;; Declarations: | |
42 | ;; spp-macro-def - A definition of a lexical macro. | |
43 | ;; spp-macro-undef - A removal of a definition of a lexical macro. | |
44 | ;; spp-system-include - A system level include file | |
45 | ;; spp-include - An include file | |
46 | ;; spp-concat - A lexical token representing textual concatenation | |
47 | ;; of symbol parts. | |
48 | ;; | |
49 | ;; Operational tokens: | |
50 | ;; spp-arg-list - Represents an argument list to a macro. | |
51 | ;; spp-symbol-merge - A request for multiple symbols to be textually merged. | |
52 | ;; | |
53 | ;;; TODO: | |
54 | ;; | |
55 | ;; Use `semantic-push-parser-warning' for situations where there are likely | |
56 | ;; macros that are undefined unexpectedly, or other problem. | |
57 | ;; | |
58 | ;; TODO: | |
59 | ;; | |
60 | ;; Try to handle the case of: | |
61 | ;; | |
62 | ;; #define NN namespace nn { | |
63 | ;; #define NN_END } | |
64 | ;; | |
65 | ;; NN | |
66 | ;; int mydecl() {} | |
67 | ;; NN_END | |
68 | ;; | |
69 | ||
55b522b2 | 70 | (require 'semantic) |
7a0e7d33 CY |
71 | (require 'semantic/lex) |
72 | ||
73 | ;;; Code: | |
74 | (defvar semantic-lex-spp-macro-symbol-obarray nil | |
75 | "Table of macro keywords used by the Semantic Preprocessor. | |
76 | These symbols will be used in addition to those in | |
77 | `semantic-lex-spp-dynamic-macro-symbol-obarray'.") | |
78 | (make-variable-buffer-local 'semantic-lex-spp-macro-symbol-obarray) | |
79 | ||
80 | (defvar semantic-lex-spp-project-macro-symbol-obarray nil | |
81 | "Table of macro keywords for this project. | |
82 | These symbols will be used in addition to those in | |
83 | `semantic-lex-spp-dynamic-macro-symbol-obarray'.") | |
84 | (make-variable-buffer-local 'semantic-lex-spp-project-macro-symbol-obarray) | |
85 | ||
86 | (defvar semantic-lex-spp-dynamic-macro-symbol-obarray nil | |
87 | "Table of macro keywords used during lexical analysis. | |
88 | Macros are lexical symbols which are replaced by other lexical | |
89 | tokens during lexical analysis. During analysis symbols can be | |
90 | added and removed from this symbol table.") | |
91 | (make-variable-buffer-local 'semantic-lex-spp-dynamic-macro-symbol-obarray) | |
92 | ||
93 | (defvar semantic-lex-spp-dynamic-macro-symbol-obarray-stack nil | |
9bf6c65c | 94 | "A stack of obarrays for temporarily scoped macro values.") |
7a0e7d33 CY |
95 | (make-variable-buffer-local 'semantic-lex-spp-dynamic-macro-symbol-obarray-stack) |
96 | ||
97 | (defvar semantic-lex-spp-expanded-macro-stack nil | |
98 | "The stack of lexical SPP macros we have expanded.") | |
99 | ;; The above is not buffer local. Some macro expansions need to be | |
100 | ;; dumped into a secondary buffer for re-lexing. | |
101 | ||
102 | ;;; NON-RECURSIVE MACRO STACK | |
103 | ;; C Pre-processor does not allow recursive macros. Here are some utils | |
104 | ;; for managing the symbol stack of where we've been. | |
105 | ||
106 | (defmacro semantic-lex-with-macro-used (name &rest body) | |
107 | "With the macro NAME currently being expanded, execute BODY. | |
108 | Pushes NAME into the macro stack. The above stack is checked | |
109 | by `semantic-lex-spp-symbol' to not return true for any symbol | |
110 | currently being expanded." | |
111 | `(unwind-protect | |
112 | (progn | |
113 | (push ,name semantic-lex-spp-expanded-macro-stack) | |
114 | ,@body) | |
115 | (pop semantic-lex-spp-expanded-macro-stack))) | |
116 | (put 'semantic-lex-with-macro-used 'lisp-indent-function 1) | |
117 | ||
118 | (add-hook | |
119 | 'edebug-setup-hook | |
120 | #'(lambda () | |
121 | ||
122 | (def-edebug-spec semantic-lex-with-macro-used | |
123 | (symbolp def-body) | |
124 | ) | |
125 | ||
126 | )) | |
127 | ||
128 | ;;; MACRO TABLE UTILS | |
129 | ;; | |
130 | ;; The dynamic macro table is a buffer local variable that is modified | |
131 | ;; during the analysis. OBARRAYs are used, so the language must | |
132 | ;; have symbols that are compatible with Emacs Lisp symbols. | |
133 | ;; | |
134 | (defsubst semantic-lex-spp-symbol (name) | |
135 | "Return spp symbol with NAME or nil if not found. | |
9bf6c65c | 136 | The search priority is: |
7a0e7d33 CY |
137 | 1. DYNAMIC symbols |
138 | 2. PROJECT specified symbols. | |
139 | 3. SYSTEM specified symbols." | |
140 | (and | |
141 | ;; Only strings... | |
142 | (stringp name) | |
143 | ;; Make sure we don't recurse. | |
144 | (not (member name semantic-lex-spp-expanded-macro-stack)) | |
145 | ;; Do the check of the various tables. | |
146 | (or | |
147 | ;; DYNAMIC | |
148 | (and (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray) | |
149 | (intern-soft name semantic-lex-spp-dynamic-macro-symbol-obarray)) | |
150 | ;; PROJECT | |
151 | (and (arrayp semantic-lex-spp-project-macro-symbol-obarray) | |
152 | (intern-soft name semantic-lex-spp-project-macro-symbol-obarray)) | |
153 | ;; SYSTEM | |
154 | (and (arrayp semantic-lex-spp-macro-symbol-obarray) | |
155 | (intern-soft name semantic-lex-spp-macro-symbol-obarray)) | |
156 | ;; ... | |
157 | ))) | |
158 | ||
159 | (defsubst semantic-lex-spp-symbol-p (name) | |
160 | "Return non-nil if a keyword with NAME exists in any keyword table." | |
161 | (if (semantic-lex-spp-symbol name) | |
162 | t)) | |
163 | ||
164 | (defsubst semantic-lex-spp-dynamic-map () | |
165 | "Return the dynamic macro map for the current buffer." | |
166 | (or semantic-lex-spp-dynamic-macro-symbol-obarray | |
167 | (setq semantic-lex-spp-dynamic-macro-symbol-obarray | |
168 | (make-vector 13 0)))) | |
169 | ||
170 | (defsubst semantic-lex-spp-dynamic-map-stack () | |
171 | "Return the dynamic macro map for the current buffer." | |
172 | (or semantic-lex-spp-dynamic-macro-symbol-obarray-stack | |
173 | (setq semantic-lex-spp-dynamic-macro-symbol-obarray-stack | |
174 | (make-vector 13 0)))) | |
175 | ||
ac73b1fa CY |
176 | (defun semantic-lex-spp-value-valid-p (value) |
177 | "Return non-nil if VALUE is valid." | |
178 | (or (null value) | |
179 | (stringp value) | |
180 | (and (consp value) | |
181 | (or (semantic-lex-token-p (car value)) | |
182 | (eq (car (car value)) 'spp-arg-list))))) | |
183 | ||
184 | (defvar semantic-lex-spp-debug-symbol nil | |
185 | "A symbol to break on if it is being set somewhere.") | |
186 | ||
187 | (defun semantic-lex-spp-enable-debug-symbol (sym) | |
188 | "Enable debugging for symbol SYM. | |
189 | Disable debugging by entering nothing." | |
190 | (interactive "sSymbol: ") | |
191 | (if (string= sym "") | |
192 | (setq semantic-lex-spp-debug-symbol nil) | |
193 | (setq semantic-lex-spp-debug-symbol sym))) | |
194 | ||
195 | (defmacro semantic-lex-spp-validate-value (name value) | |
196 | "Validate the NAME and VALUE of a macro before it is set." | |
197 | ; `(progn | |
198 | ; (when (not (semantic-lex-spp-value-valid-p ,value)) | |
199 | ; (error "Symbol \"%s\" with bogus value %S" ,name ,value)) | |
200 | ; (when (and semantic-lex-spp-debug-symbol | |
201 | ; (string= semantic-lex-spp-debug-symbol name)) | |
202 | ; (debug)) | |
203 | ; ) | |
204 | nil | |
205 | ) | |
206 | ||
7a0e7d33 CY |
207 | (defun semantic-lex-spp-symbol-set (name value &optional obarray-in) |
208 | "Set value of spp symbol with NAME to VALUE and return VALUE. | |
209 | If optional OBARRAY-IN is non-nil, then use that obarray instead of | |
210 | the dynamic map." | |
ac73b1fa | 211 | (semantic-lex-spp-validate-value name value) |
7a0e7d33 CY |
212 | (if (and (stringp value) (string= value "")) (setq value nil)) |
213 | (set (intern name (or obarray-in | |
214 | (semantic-lex-spp-dynamic-map))) | |
215 | value)) | |
216 | ||
217 | (defsubst semantic-lex-spp-symbol-remove (name &optional obarray) | |
218 | "Remove the spp symbol with NAME. | |
219 | If optional OBARRAY is non-nil, then use that obarray instead of | |
220 | the dynamic map." | |
221 | (unintern name (or obarray | |
222 | (semantic-lex-spp-dynamic-map)))) | |
223 | ||
224 | (defun semantic-lex-spp-symbol-push (name value) | |
225 | "Push macro NAME with VALUE into the map. | |
226 | Reverse with `semantic-lex-spp-symbol-pop'." | |
ac73b1fa | 227 | (semantic-lex-spp-validate-value name value) |
7a0e7d33 CY |
228 | (let* ((map (semantic-lex-spp-dynamic-map)) |
229 | (stack (semantic-lex-spp-dynamic-map-stack)) | |
230 | (mapsym (intern name map)) | |
231 | (stacksym (intern name stack)) | |
232 | (mapvalue (when (boundp mapsym) (symbol-value mapsym))) | |
233 | ) | |
234 | (when (boundp mapsym) | |
235 | ;; Make sure there is a stack | |
236 | (if (not (boundp stacksym)) (set stacksym nil)) | |
237 | ;; If there is a value to push, then push it. | |
238 | (set stacksym (cons mapvalue (symbol-value stacksym))) | |
239 | ) | |
240 | ;; Set our new value here. | |
241 | (set mapsym value) | |
242 | )) | |
243 | ||
244 | (defun semantic-lex-spp-symbol-pop (name) | |
245 | "Pop macro NAME from the stackmap into the orig map. | |
246 | Reverse with `semantic-lex-spp-symbol-pop'." | |
247 | (let* ((map (semantic-lex-spp-dynamic-map)) | |
248 | (stack (semantic-lex-spp-dynamic-map-stack)) | |
249 | (mapsym (intern name map)) | |
250 | (stacksym (intern name stack)) | |
251 | (oldvalue nil) | |
252 | ) | |
253 | (if (or (not (boundp stacksym) ) | |
254 | (= (length (symbol-value stacksym)) 0)) | |
255 | ;; Nothing to pop, remove it. | |
256 | (unintern name map) | |
257 | ;; If there is a value to pop, then add it to the map. | |
258 | (set mapsym (car (symbol-value stacksym))) | |
259 | (set stacksym (cdr (symbol-value stacksym))) | |
260 | ))) | |
261 | ||
262 | (defsubst semantic-lex-spp-symbol-stream (name) | |
263 | "Return replacement stream of macro with NAME." | |
264 | (let ((spp (semantic-lex-spp-symbol name))) | |
265 | (if spp | |
266 | (symbol-value spp)))) | |
267 | ||
268 | (defun semantic-lex-make-spp-table (specs) | |
269 | "Convert spp macro list SPECS into an obarray and return it. | |
270 | SPECS must be a list of (NAME . REPLACEMENT) elements, where: | |
271 | ||
272 | NAME is the name of the spp macro symbol to define. | |
273 | REPLACEMENT a string that would be substituted in for NAME." | |
274 | ||
275 | ;; Create the symbol hash table | |
276 | (let ((semantic-lex-spp-macro-symbol-obarray (make-vector 13 0)) | |
277 | spec) | |
278 | ;; fill it with stuff | |
279 | (while specs | |
280 | (setq spec (car specs) | |
281 | specs (cdr specs)) | |
282 | (semantic-lex-spp-symbol-set | |
283 | (car spec) | |
284 | (cdr spec) | |
285 | semantic-lex-spp-macro-symbol-obarray)) | |
286 | semantic-lex-spp-macro-symbol-obarray)) | |
287 | ||
288 | (defun semantic-lex-spp-save-table () | |
289 | "Return a list of spp macros and values. | |
290 | The return list is meant to be saved in a semanticdb table." | |
291 | (let (macros) | |
292 | (when (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray) | |
293 | (mapatoms | |
294 | #'(lambda (symbol) | |
295 | (setq macros (cons (cons (symbol-name symbol) | |
296 | (symbol-value symbol)) | |
297 | macros))) | |
298 | semantic-lex-spp-dynamic-macro-symbol-obarray)) | |
299 | macros)) | |
300 | ||
301 | (defun semantic-lex-spp-macros () | |
302 | "Return a list of spp macros as Lisp symbols. | |
303 | The value of each symbol is the replacement stream." | |
304 | (let (macros) | |
305 | (when (arrayp semantic-lex-spp-macro-symbol-obarray) | |
306 | (mapatoms | |
307 | #'(lambda (symbol) | |
308 | (setq macros (cons symbol macros))) | |
309 | semantic-lex-spp-macro-symbol-obarray)) | |
310 | (when (arrayp semantic-lex-spp-project-macro-symbol-obarray) | |
311 | (mapatoms | |
312 | #'(lambda (symbol) | |
313 | (setq macros (cons symbol macros))) | |
314 | semantic-lex-spp-project-macro-symbol-obarray)) | |
315 | (when (arrayp semantic-lex-spp-dynamic-macro-symbol-obarray) | |
316 | (mapatoms | |
317 | #'(lambda (symbol) | |
318 | (setq macros (cons symbol macros))) | |
319 | semantic-lex-spp-dynamic-macro-symbol-obarray)) | |
320 | macros)) | |
321 | ||
322 | (defun semantic-lex-spp-set-dynamic-table (new-entries) | |
323 | "Set the dynamic symbol table to NEW-ENTRIES. | |
324 | For use with semanticdb restoration of state." | |
325 | (dolist (e new-entries) | |
326 | ;; Default obarray for below is the dynamic map. | |
327 | (semantic-lex-spp-symbol-set (car e) (cdr e)))) | |
328 | ||
329 | (defun semantic-lex-spp-reset-hook (start end) | |
330 | "Reset anything needed by SPP for parsing. | |
331 | In this case, reset the dynamic macro symbol table if | |
332 | START is (point-min). | |
333 | END is not used." | |
334 | (when (= start (point-min)) | |
335 | (setq semantic-lex-spp-dynamic-macro-symbol-obarray nil | |
336 | semantic-lex-spp-dynamic-macro-symbol-obarray-stack nil | |
337 | ;; This shouldn't not be nil, but reset just in case. | |
338 | semantic-lex-spp-expanded-macro-stack nil) | |
339 | )) | |
340 | ||
341 | ;;; MACRO EXPANSION: Simple cases | |
342 | ;; | |
343 | ;; If a user fills in the table with simple strings, we can | |
344 | ;; support that by converting them into tokens with the | |
345 | ;; various analyzers that are available. | |
346 | ||
347 | (defun semantic-lex-spp-extract-regex-and-compare (analyzer value) | |
348 | "Extract a regexp from an ANALYZER and use to match VALUE. | |
349 | Return non-nil if it matches" | |
350 | (let* ((condition (car analyzer)) | |
351 | (regex (cond ((eq (car condition) 'looking-at) | |
352 | (nth 1 condition)) | |
353 | (t | |
354 | nil)))) | |
355 | (when regex | |
356 | (string-match regex value)) | |
357 | )) | |
358 | ||
359 | (defun semantic-lex-spp-simple-macro-to-macro-stream (val beg end argvalues) | |
360 | "Convert lexical macro contents VAL into a macro expansion stream. | |
361 | These are for simple macro expansions that a user may have typed in directly. | |
362 | As such, we need to analyze the input text, to figure out what kind of real | |
363 | lexical token we should be inserting in its place. | |
364 | ||
365 | Argument VAL is the value of some macro to be converted into a stream. | |
366 | BEG and END are the token bounds of the macro to be expanded | |
367 | that will somehow gain a much longer token stream. | |
368 | ARGVALUES are values for any arg list, or nil." | |
369 | (cond | |
370 | ;; We perform a replacement. Technically, this should | |
371 | ;; be a full lexical step over the "val" string, but take | |
372 | ;; a guess that its just a keyword or existing symbol. | |
373 | ;; | |
374 | ;; Probably a really bad idea. See how it goes. | |
375 | ((semantic-lex-spp-extract-regex-and-compare | |
376 | semantic-lex-symbol-or-keyword val) | |
377 | (semantic-lex-push-token | |
378 | (semantic-lex-token (or (semantic-lex-keyword-p val) 'symbol) | |
379 | beg end | |
380 | val))) | |
381 | ||
382 | ;; Ok, the rest of these are various types of syntax. | |
383 | ;; Conveniences for users that type in their symbol table. | |
384 | ((semantic-lex-spp-extract-regex-and-compare | |
385 | semantic-lex-punctuation val) | |
386 | (semantic-lex-token 'punctuation beg end val)) | |
387 | ((semantic-lex-spp-extract-regex-and-compare | |
388 | semantic-lex-number val) | |
389 | (semantic-lex-token 'number beg end val)) | |
390 | ((semantic-lex-spp-extract-regex-and-compare | |
391 | semantic-lex-paren-or-list val) | |
392 | (semantic-lex-token 'semantic-list beg end val)) | |
393 | ((semantic-lex-spp-extract-regex-and-compare | |
394 | semantic-lex-string val) | |
395 | (semantic-lex-token 'string beg end val)) | |
396 | (t nil) | |
397 | )) | |
398 | ||
399 | ;;; MACRO EXPANSION : Lexical token replacement | |
400 | ;; | |
401 | ;; When substituting in a macro from a token stream of formatted | |
402 | ;; semantic lex tokens, things can be much more complicated. | |
403 | ;; | |
404 | ;; Some macros have arguments that get set into the dynamic macro | |
405 | ;; table during replacement. | |
406 | ;; | |
407 | ;; In general, the macro tokens are substituted into the regular | |
408 | ;; token stream, but placed under the characters of the original | |
409 | ;; macro symbol. | |
410 | ;; | |
411 | ;; Argument lists are saved as a lexical token at the beginning | |
412 | ;; of a replacement value. | |
413 | ||
a6d7d3ef | 414 | (defun semantic-lex-spp-one-token-to-txt (tok &optional blocktok) |
7a0e7d33 CY |
415 | "Convert the token TOK into a string. |
416 | If TOK is made of multiple tokens, convert those to text. This | |
417 | conversion is needed if a macro has a merge symbol in it that | |
418 | combines the text of two previously distinct symbols. For | |
9bf6c65c | 419 | example, in c: |
7a0e7d33 | 420 | |
a6d7d3ef CY |
421 | #define (a,b) a ## b; |
422 | ||
423 | If optional string BLOCKTOK matches the expanded value, then do not | |
424 | continue processing recursively." | |
7a0e7d33 CY |
425 | (let ((txt (semantic-lex-token-text tok)) |
426 | (sym nil) | |
427 | ) | |
a6d7d3ef CY |
428 | (cond |
429 | ;; Recursion prevention | |
430 | ((and (stringp blocktok) (string= txt blocktok)) | |
431 | blocktok) | |
432 | ;; A complex symbol | |
433 | ((and (eq (car tok) 'symbol) | |
434 | (setq sym (semantic-lex-spp-symbol txt)) | |
435 | (not (semantic-lex-spp-macro-with-args (symbol-value sym))) | |
436 | ) | |
437 | ;; Now that we have a symbol, | |
438 | (let ((val (symbol-value sym))) | |
439 | (cond | |
440 | ;; This is another lexical token. | |
441 | ((and (consp val) | |
442 | (symbolp (car val))) | |
443 | (semantic-lex-spp-one-token-to-txt val txt)) | |
444 | ;; This is a list of tokens. | |
445 | ((and (consp val) | |
446 | (consp (car val)) | |
447 | (symbolp (car (car val)))) | |
448 | (mapconcat (lambda (subtok) | |
449 | (semantic-lex-spp-one-token-to-txt subtok)) | |
450 | val | |
451 | "")) | |
452 | ;; If val is nil, that's probably wrong. | |
453 | ;; Found a system header case where this was true. | |
454 | ((null val) "") | |
455 | ;; Debug wierd stuff. | |
456 | (t (debug))) | |
457 | )) | |
458 | ((stringp txt) | |
459 | txt) | |
460 | (t nil)) | |
7a0e7d33 CY |
461 | )) |
462 | ||
463 | (defun semantic-lex-spp-macro-with-args (val) | |
464 | "If the macro value VAL has an argument list, return the arglist." | |
465 | (when (and val (consp val) (consp (car val)) | |
466 | (eq 'spp-arg-list (car (car val)))) | |
467 | (car (cdr (car val))))) | |
468 | ||
469 | (defun semantic-lex-spp-token-macro-to-macro-stream (val beg end argvalues) | |
470 | "Convert lexical macro contents VAL into a macro expansion stream. | |
471 | Argument VAL is the value of some macro to be converted into a stream. | |
472 | BEG and END are the token bounds of the macro to be expanded | |
473 | that will somehow gain a much longer token stream. | |
474 | ARGVALUES are values for any arg list, or nil. | |
475 | See comments in code for information about how token streams are processed | |
476 | and what valid VAL values are." | |
477 | ||
478 | ;; A typical VAL value might be either a stream of tokens. | |
479 | ;; Tokens saved into a macro stream always includes the text from the | |
480 | ;; buffer, since the locations specified probably don't represent | |
481 | ;; that text anymore, or even the same buffer. | |
482 | ;; | |
483 | ;; CASE 1: Simple token stream | |
484 | ;; | |
485 | ;; #define SUPER mysuper:: | |
486 | ;; ==> | |
487 | ;;((symbol "mysuper" 480 . 487) | |
488 | ;; (punctuation ":" 487 . 488) | |
489 | ;; (punctuation ":" 488 . 489)) | |
490 | ;; | |
491 | ;; CASE 2: Token stream with argument list | |
492 | ;; | |
493 | ;; #define INT_FCN(name) int name (int in) | |
494 | ;; ==> | |
495 | ;; ((spp-arg-list ("name") 558 . 564) | |
496 | ;; (INT "int" 565 . 568) | |
497 | ;; (symbol "name" 569 . 573) | |
498 | ;; (semantic-list "(int in)" 574 . 582)) | |
499 | ;; | |
500 | ;; In the second case, a macro with an argument list as the a rgs as the | |
501 | ;; first entry. | |
502 | ;; | |
503 | ;; CASE 3: Symbol text merge | |
504 | ;; | |
505 | ;; #define TMP(a) foo_ ## a | |
506 | ;; ==> | |
507 | ;; ((spp-arg-list ("a") 20 . 23) | |
508 | ;; (spp-symbol-merge ((symbol "foo_" 24 . 28) (symbol "a" 32 . 33)) | |
509 | ;; 24 . 33)) | |
510 | ;; | |
511 | ;; Usually in conjunction with a macro with an argument, merging symbol | |
512 | ;; parts is a way of fabricating new symbols from pieces inside the macro. | |
513 | ;; These macros use `spp-symbol-merge' tokens whose TEXT part is another | |
514 | ;; token stream. This sub-stream ought to consist of only 2 SYMBOL pieces, | |
515 | ;; though I suppose keywords might be ok. The end result of this example | |
516 | ;; merge symbol would be (symbol "foo_A" 24 . 33) where A is the symbol | |
517 | ;; passed in from the arg list "a". | |
518 | ;; | |
519 | ;; CASE 4: Nested token streams | |
520 | ;; | |
521 | ;; #define FOO(f) f | |
522 | ;; #define BLA bla FOO(foo) | |
523 | ;; ==> | |
524 | ;; ((INT "int" 82 . 85) | |
525 | ;; (symbol "FOO" 86 . 89) | |
526 | ;; (semantic-list "(foo)" 89 . 94)) | |
527 | ;; | |
528 | ;; Nested token FOO shows up in the table of macros, and gets replace | |
529 | ;; inline. This is the same as case 2. | |
530 | ||
531 | (let ((arglist (semantic-lex-spp-macro-with-args val)) | |
532 | (argalist nil) | |
533 | (val-tmp nil) | |
534 | (v nil) | |
535 | ) | |
536 | ;; CASE 2: Dealing with the arg list. | |
537 | (when arglist | |
538 | ;; Skip the arg list. | |
539 | (setq val (cdr val)) | |
540 | ||
541 | ;; Push args into the replacement list. | |
542 | (let ((AV argvalues)) | |
543 | (dolist (A arglist) | |
544 | (let* ((argval (car AV))) | |
545 | ||
546 | (semantic-lex-spp-symbol-push A argval) | |
547 | (setq argalist (cons (cons A argval) argalist)) | |
548 | (setq AV (cdr AV))))) | |
549 | ) | |
550 | ||
551 | ;; Set val-tmp after stripping arguments. | |
552 | (setq val-tmp val) | |
553 | ||
554 | ;; CASE 1: Push everything else onto the list. | |
555 | ;; Once the arg list is stripped off, CASE 2 is the same | |
556 | ;; as CASE 1. | |
557 | (while val-tmp | |
558 | (setq v (car val-tmp)) | |
559 | (setq val-tmp (cdr val-tmp)) | |
560 | ||
561 | (let* (;; The text of the current lexical token. | |
562 | (txt (car (cdr v))) | |
563 | ;; Try to convert txt into a macro declaration. If it is | |
564 | ;; not a macro, use nil. | |
565 | (txt-macro-or-nil (semantic-lex-spp-symbol txt)) | |
566 | ;; If our current token is a macro, then pull off the argument | |
567 | ;; list. | |
568 | (macro-and-args | |
569 | (when txt-macro-or-nil | |
570 | (semantic-lex-spp-macro-with-args (symbol-value txt-macro-or-nil))) | |
571 | ) | |
572 | ;; We need to peek at the next token when testing for | |
573 | ;; used macros with arg lists. | |
574 | (next-tok-class (semantic-lex-token-class (car val-tmp))) | |
575 | ) | |
576 | ||
577 | (cond | |
578 | ;; CASE 3: Merge symbols together. | |
579 | ((eq (semantic-lex-token-class v) 'spp-symbol-merge) | |
580 | ;; We need to merge the tokens in the 'text segement together, | |
581 | ;; and produce a single symbol from it. | |
582 | (let ((newsym | |
583 | (mapconcat (lambda (tok) | |
584 | (semantic-lex-spp-one-token-to-txt tok)) | |
585 | txt | |
586 | ""))) | |
587 | (semantic-lex-push-token | |
588 | (semantic-lex-token 'symbol beg end newsym)) | |
589 | )) | |
590 | ||
591 | ;; CASE 2: Argument replacement. If a discovered symbol is in | |
592 | ;; the active list of arguments, then we need to substitute | |
593 | ;; in the new value. | |
594 | ((and (eq (semantic-lex-token-class v) 'symbol) txt-macro-or-nil | |
595 | (or (and macro-and-args (eq next-tok-class 'semantic-list)) | |
596 | (not macro-and-args)) | |
597 | ) | |
598 | (let ((AV nil)) | |
599 | (when macro-and-args | |
600 | (setq AV | |
601 | (semantic-lex-spp-stream-for-arglist (car val-tmp))) | |
602 | ;; We used up these args. Pull from the stream. | |
603 | (setq val-tmp (cdr val-tmp)) | |
604 | ) | |
605 | ||
606 | (semantic-lex-with-macro-used txt | |
607 | ;; Don't recurse directly into this same fcn, because it is | |
608 | ;; convenient to have plain string replacements too. | |
609 | (semantic-lex-spp-macro-to-macro-stream | |
610 | (symbol-value txt-macro-or-nil) | |
611 | beg end AV)) | |
612 | )) | |
613 | ||
614 | ;; This is a HACK for the C parser. The 'macros text | |
615 | ;; property is some storage so that the parser can do | |
616 | ;; some C specific text manipulations. | |
617 | ((eq (semantic-lex-token-class v) 'semantic-list) | |
618 | ;; Push our arg list onto the semantic list. | |
619 | (when argalist | |
620 | (setq txt (concat txt)) ; Copy the text. | |
621 | (put-text-property 0 1 'macros argalist txt)) | |
622 | (semantic-lex-push-token | |
623 | (semantic-lex-token (semantic-lex-token-class v) beg end txt)) | |
624 | ) | |
625 | ||
626 | ;; CASE 1: Just another token in the stream. | |
627 | (t | |
628 | ;; Nothing new. | |
629 | (semantic-lex-push-token | |
630 | (semantic-lex-token (semantic-lex-token-class v) beg end txt)) | |
631 | ) | |
632 | ))) | |
633 | ||
634 | ;; CASE 2: The arg list we pushed onto the symbol table | |
635 | ;; must now be removed. | |
636 | (dolist (A arglist) | |
637 | (semantic-lex-spp-symbol-pop A)) | |
638 | )) | |
639 | ||
640 | ;;; Macro Merging | |
641 | ;; | |
642 | ;; Used when token streams from different macros include eachother. | |
643 | ;; Merged macro streams perform in place replacements. | |
644 | ||
645 | (defun semantic-lex-spp-merge-streams (raw-stream) | |
646 | "Merge elements from the RAW-STREAM together. | |
647 | Handle spp-concat symbol concatenation. | |
648 | Handle Nested macro replacements. | |
649 | Return the cooked stream." | |
650 | (let ((cooked-stream nil)) | |
651 | ;; Merge the stream | |
652 | (while raw-stream | |
653 | (cond ((eq (semantic-lex-token-class (car raw-stream)) 'spp-concat) | |
654 | ;; handle hashhash, by skipping it. | |
655 | (setq raw-stream (cdr raw-stream)) | |
656 | ;; Now merge the symbols. | |
657 | (let ((prev-tok (car cooked-stream)) | |
658 | (next-tok (car raw-stream))) | |
659 | (setq cooked-stream (cdr cooked-stream)) | |
660 | (push (semantic-lex-token | |
661 | 'spp-symbol-merge | |
662 | (semantic-lex-token-start prev-tok) | |
663 | (semantic-lex-token-end next-tok) | |
664 | (list prev-tok next-tok)) | |
665 | cooked-stream) | |
666 | )) | |
667 | (t | |
668 | (push (car raw-stream) cooked-stream)) | |
669 | ) | |
670 | (setq raw-stream (cdr raw-stream)) | |
671 | ) | |
672 | ||
673 | (nreverse cooked-stream)) | |
674 | ) | |
675 | ||
676 | ;;; MACRO EXPANSION | |
677 | ;; | |
678 | ;; There are two types of expansion. | |
679 | ;; | |
680 | ;; 1. Expansion using a value made up of lexical tokens. | |
681 | ;; 2. User input replacement from a plain string. | |
682 | ||
683 | (defun semantic-lex-spp-macro-to-macro-stream (val beg end argvalues) | |
684 | "Convert lexical macro contents VAL into a macro expansion stream. | |
685 | Argument VAL is the value of some macro to be converted into a stream. | |
686 | BEG and END are the token bounds of the macro to be expanded | |
687 | that will somehow gain a much longer token stream. | |
688 | ARGVALUES are values for any arg list, or nil." | |
689 | (cond | |
690 | ;; If val is nil, then just skip it. | |
691 | ((null val) t) | |
692 | ;; If it is a token, then return that token rebuilt. | |
693 | ((and (consp val) (car val) (symbolp (car val))) | |
694 | (semantic-lex-push-token | |
695 | (semantic-lex-token (car val) beg end (semantic-lex-token-text val)))) | |
696 | ;; Test for a token list. | |
697 | ((and (consp val) (consp (car val)) (car (car val)) | |
698 | (symbolp (car (car val)))) | |
699 | (semantic-lex-spp-token-macro-to-macro-stream val beg end argvalues)) | |
700 | ;; Test for miscellaneous strings. | |
701 | ((stringp val) | |
702 | (semantic-lex-spp-simple-macro-to-macro-stream val beg end argvalues)) | |
703 | )) | |
704 | ||
705 | ;;; -------------------------------------------------------- | |
706 | ;;; | |
707 | ;;; ANALYZERS: | |
708 | ;;; | |
709 | ||
710 | ;;; Symbol Is Macro | |
711 | ;; | |
712 | ;; An analyser that will push tokens from a macro in place | |
713 | ;; of the macro symbol. | |
714 | ;; | |
715 | (defun semantic-lex-spp-anlyzer-do-replace (sym val beg end) | |
716 | "Do the lexical replacement for SYM with VAL. | |
717 | Argument BEG and END specify the bounds of SYM in the buffer." | |
718 | (if (not val) | |
719 | (setq semantic-lex-end-point end) | |
720 | (let ((arg-in nil) | |
721 | (arg-parsed nil) | |
722 | (arg-split nil) | |
723 | ) | |
724 | ||
725 | ;; Check for arguments. | |
726 | (setq arg-in (semantic-lex-spp-macro-with-args val)) | |
727 | ||
728 | (when arg-in | |
729 | (save-excursion | |
730 | (goto-char end) | |
731 | (setq arg-parsed | |
732 | (semantic-lex-spp-one-token-and-move-for-macro | |
8d106ea0 CY |
733 | ;; NOTE: This used to be (point-at-eol), but |
734 | ;; that was too close for multi-line arguments | |
735 | ;; to a macro. Point max may be too far if there | |
736 | ;; is a typo in the buffer. | |
737 | ;; | |
738 | ;; Look here for performance issues while a user is typing | |
739 | ;; incomplete code. | |
740 | (point-max))) | |
7a0e7d33 CY |
741 | (setq end (semantic-lex-token-end arg-parsed)) |
742 | ||
743 | (when (and (listp arg-parsed) (eq (car arg-parsed) 'semantic-list)) | |
744 | (setq arg-split | |
745 | ;; Use lex to split up the contents of the argument list. | |
746 | (semantic-lex-spp-stream-for-arglist arg-parsed) | |
747 | )) | |
748 | )) | |
749 | ||
750 | ;; if we have something to sub in, then do it. | |
751 | (semantic-lex-spp-macro-to-macro-stream val beg end arg-split) | |
752 | (setq semantic-lex-end-point end) | |
753 | ) | |
754 | )) | |
755 | ||
756 | (defvar semantic-lex-spp-replacements-enabled t | |
757 | "Non-nil means do replacements when finding keywords. | |
758 | Disable this only to prevent recursive expansion issues.") | |
759 | ||
760 | (defun semantic-lex-spp-analyzer-push-tokens-for-symbol (str beg end) | |
761 | "Push lexical tokens for the symbol or keyword STR. | |
762 | STR occurs in the current buffer between BEG and END." | |
55b522b2 | 763 | (let (sym val count) |
7a0e7d33 CY |
764 | (cond |
765 | ;; | |
766 | ;; It is a macro. Prepare for a replacement. | |
767 | ((and semantic-lex-spp-replacements-enabled | |
768 | (semantic-lex-spp-symbol-p str)) | |
769 | (setq sym (semantic-lex-spp-symbol str) | |
770 | val (symbol-value sym) | |
771 | count 0) | |
772 | ||
773 | (let ((semantic-lex-spp-expanded-macro-stack | |
774 | semantic-lex-spp-expanded-macro-stack)) | |
775 | ||
776 | (semantic-lex-with-macro-used str | |
777 | ;; Do direct replacements of single value macros of macros. | |
778 | ;; This solves issues with a macro containing one symbol that | |
779 | ;; is another macro, and get arg lists passed around. | |
780 | (while (and val (consp val) | |
781 | (semantic-lex-token-p (car val)) | |
782 | (eq (length val) 1) | |
783 | (eq (semantic-lex-token-class (car val)) 'symbol) | |
784 | (semantic-lex-spp-symbol-p (semantic-lex-token-text (car val))) | |
785 | (< count 10) | |
786 | ) | |
787 | (setq str (semantic-lex-token-text (car val))) | |
788 | (setq sym (semantic-lex-spp-symbol str) | |
789 | val (symbol-value sym)) | |
790 | ;; Prevent recursion | |
791 | (setq count (1+ count)) | |
792 | ;; This prevents a different kind of recursion. | |
793 | (push str semantic-lex-spp-expanded-macro-stack) | |
794 | ) | |
795 | ||
796 | (semantic-lex-spp-anlyzer-do-replace sym val beg end)) | |
797 | ||
798 | )) | |
799 | ;; Anything else. | |
800 | (t | |
801 | ;; A regular keyword. | |
802 | (semantic-lex-push-token | |
803 | (semantic-lex-token (or (semantic-lex-keyword-p str) 'symbol) | |
804 | beg end)))) | |
805 | )) | |
806 | ||
807 | (define-lex-regex-analyzer semantic-lex-spp-replace-or-symbol-or-keyword | |
808 | "Like 'semantic-lex-symbol-or-keyword' plus preprocessor macro replacement." | |
809 | "\\(\\sw\\|\\s_\\)+" | |
810 | (let ((str (match-string 0)) | |
811 | (beg (match-beginning 0)) | |
812 | (end (match-end 0))) | |
813 | (semantic-lex-spp-analyzer-push-tokens-for-symbol str beg end))) | |
814 | ||
815 | ;;; ANALYZERS FOR NEW MACROS | |
816 | ;; | |
817 | ;; These utilities and analyzer declaration function are for | |
818 | ;; creating an analyzer which produces new macros in the macro table. | |
819 | ;; | |
820 | ;; There are two analyzers. One for new macros, and one for removing | |
821 | ;; a macro. | |
822 | ||
823 | (defun semantic-lex-spp-first-token-arg-list (token) | |
824 | "If TOKEN is a semantic-list, turn it into a an SPP ARG LIST." | |
825 | (when (and (consp token) | |
826 | (symbolp (car token)) | |
827 | (eq 'semantic-list (car token))) | |
828 | ;; Convert TOKEN in place. | |
55b522b2 CY |
829 | (let ((argsplit (split-string (semantic-lex-token-text token) |
830 | "[(), ]" t))) | |
7a0e7d33 CY |
831 | (setcar token 'spp-arg-list) |
832 | (setcar (nthcdr 1 token) argsplit)) | |
833 | )) | |
834 | ||
835 | (defun semantic-lex-spp-one-token-and-move-for-macro (max) | |
836 | "Lex up one token, and move to end of that token. | |
837 | Don't go past MAX." | |
838 | (let ((ans (semantic-lex (point) max 0 0))) | |
839 | (if (not ans) | |
840 | (progn (goto-char max) | |
841 | nil) | |
842 | (when (> (semantic-lex-token-end (car ans)) max) | |
843 | (let ((bounds (semantic-lex-token-bounds (car ans)))) | |
844 | (setcdr bounds max))) | |
845 | (goto-char (semantic-lex-token-end (car ans))) | |
846 | (car ans)) | |
847 | )) | |
848 | ||
849 | (defun semantic-lex-spp-stream-for-arglist (token) | |
850 | "Lex up the contents of the arglist TOKEN. | |
851 | Parsing starts inside the parens, and ends at the end of TOKEN." | |
852 | (let ((end (semantic-lex-token-end token)) | |
853 | (fresh-toks nil) | |
854 | (toks nil)) | |
855 | (save-excursion | |
856 | ||
857 | (if (stringp (nth 1 token)) | |
858 | ;; If the 2nd part of the token is a string, then we have | |
859 | ;; a token specifically extracted from a buffer. Possibly | |
860 | ;; a different buffer. This means we need to do something | |
861 | ;; nice to parse its contents. | |
862 | (let ((txt (semantic-lex-token-text token))) | |
863 | (semantic-lex-spp-lex-text-string | |
864 | (substring txt 1 (1- (length txt))))) | |
865 | ||
866 | ;; This part is like the original | |
867 | (goto-char (semantic-lex-token-start token)) | |
868 | ;; A cheat for going into the semantic list. | |
869 | (forward-char 1) | |
870 | (setq fresh-toks (semantic-lex-spp-stream-for-macro (1- end))) | |
871 | (dolist (tok fresh-toks) | |
872 | (when (memq (semantic-lex-token-class tok) '(symbol semantic-list)) | |
873 | (setq toks (cons tok toks)))) | |
874 | ||
875 | (nreverse toks))))) | |
876 | ||
a964f5e5 CY |
877 | (defvar semantic-lex-spp-hack-depth 0 |
878 | "Current depth of recursive calls to `semantic-lex-spp-lex-text-string'.") | |
879 | ||
7a0e7d33 CY |
880 | (defun semantic-lex-spp-lex-text-string (text) |
881 | "Lex the text string TEXT using the current buffer's state. | |
882 | Use this to parse text extracted from a macro as if it came from | |
883 | the current buffer. Since the lexer is designed to only work in | |
884 | a buffer, we need to create a new buffer, and populate it with rules | |
885 | and variable state from the current buffer." | |
a964f5e5 CY |
886 | (let* ((semantic-lex-spp-hack-depth (1+ semantic-lex-spp-hack-depth)) |
887 | (buf (get-buffer-create (format " *SPP parse hack %d*" | |
888 | semantic-lex-spp-hack-depth))) | |
7a0e7d33 CY |
889 | (mode major-mode) |
890 | (fresh-toks nil) | |
891 | (toks nil) | |
892 | (origbuff (current-buffer)) | |
893 | (important-vars '(semantic-lex-spp-macro-symbol-obarray | |
894 | semantic-lex-spp-project-macro-symbol-obarray | |
895 | semantic-lex-spp-dynamic-macro-symbol-obarray | |
896 | semantic-lex-spp-dynamic-macro-symbol-obarray-stack | |
897 | semantic-lex-spp-expanded-macro-stack | |
898 | )) | |
899 | ) | |
dd9af436 CY |
900 | (if (> semantic-lex-spp-hack-depth 5) |
901 | nil | |
902 | (with-current-buffer buf | |
903 | (erase-buffer) | |
904 | ;; Below is a painful hack to make sure everything is setup correctly. | |
905 | (when (not (eq major-mode mode)) | |
906 | (save-match-data | |
907 | ||
908 | ;; Protect against user-hooks that throw errors. | |
909 | (condition-case nil | |
910 | (funcall mode) | |
911 | (error nil)) | |
912 | ||
913 | ;; Hack in mode-local | |
914 | (activate-mode-local-bindings) | |
915 | ||
916 | ;; CHEATER! The following 3 lines are from | |
917 | ;; `semantic-new-buffer-fcn', but we don't want to turn | |
918 | ;; on all the other annoying modes for this little task. | |
919 | (setq semantic-new-buffer-fcn-was-run t) | |
920 | (semantic-lex-init) | |
921 | (semantic-clear-toplevel-cache) | |
922 | (remove-hook 'semantic-lex-reset-hooks 'semantic-lex-spp-reset-hook | |
923 | t) | |
924 | )) | |
a6d7d3ef | 925 | |
dd9af436 CY |
926 | ;; Second Cheat: copy key variables regarding macro state from the |
927 | ;; the originating buffer we are parsing. We need to do this every time | |
928 | ;; since the state changes. | |
929 | (dolist (V important-vars) | |
930 | (set V (semantic-buffer-local-value V origbuff))) | |
931 | (insert text) | |
932 | (goto-char (point-min)) | |
a6d7d3ef | 933 | |
dd9af436 | 934 | (setq fresh-toks (semantic-lex-spp-stream-for-macro (point-max)))) |
7a0e7d33 | 935 | |
dd9af436 CY |
936 | (dolist (tok fresh-toks) |
937 | (when (memq (semantic-lex-token-class tok) '(symbol semantic-list)) | |
938 | (setq toks (cons tok toks))))) | |
7a0e7d33 CY |
939 | |
940 | (nreverse toks))) | |
941 | ||
942 | ;;;; FIRST DRAFT | |
943 | ;; This is the fist version of semantic-lex-spp-stream-for-arglist | |
944 | ;; that worked pretty well. It doesn't work if the TOKEN was derived | |
945 | ;; from some other buffer, in which case it can get the wrong answer | |
946 | ;; or throw an error if the token location in the originating buffer is | |
947 | ;; larger than the current buffer. | |
948 | ;;(defun semantic-lex-spp-stream-for-arglist-orig (token) | |
949 | ;; "Lex up the contents of the arglist TOKEN. | |
950 | ;; Parsing starts inside the parens, and ends at the end of TOKEN." | |
951 | ;; (save-excursion | |
952 | ;; (let ((end (semantic-lex-token-end token)) | |
953 | ;; (fresh-toks nil) | |
954 | ;; (toks nil)) | |
955 | ;; (goto-char (semantic-lex-token-start token)) | |
956 | ;; ;; A cheat for going into the semantic list. | |
957 | ;; (forward-char 1) | |
958 | ;; (setq fresh-toks (semantic-lex-spp-stream-for-macro (1- end))) | |
959 | ;; (dolist (tok fresh-toks) | |
960 | ;; (when (memq (semantic-lex-token-class tok) '(symbol semantic-list)) | |
961 | ;; (setq toks (cons tok toks)))) | |
962 | ;; (nreverse toks)) | |
963 | ;; )) | |
964 | ||
965 | ;;;; USING SPLIT | |
966 | ;; This doesn't work, because some arguments passed into a macro | |
967 | ;; might contain non-simple symbol words, which this doesn't handle. | |
968 | ;; | |
969 | ;; Thus, you need a full lex to occur. | |
970 | ;; (defun semantic-lex-spp-stream-for-arglist-split (token) | |
971 | ;; "Lex up the contents of the arglist TOKEN. | |
972 | ;; Parsing starts inside the parens, and ends at the end of TOKEN." | |
973 | ;; (let* ((txt (semantic-lex-token-text token)) | |
974 | ;; (split (split-string (substring txt 1 (1- (length txt))) | |
975 | ;; "(), " t)) | |
976 | ;; ;; Hack for lexing. | |
977 | ;; (semantic-lex-spp-analyzer-push-tokens-for-symbol nil)) | |
978 | ;; (dolist (S split) | |
979 | ;; (semantic-lex-spp-analyzer-push-tokens-for-symbol S 0 1)) | |
980 | ;; (reverse semantic-lex-spp-analyzer-push-tokens-for-symbol))) | |
981 | ||
982 | ||
983 | (defun semantic-lex-spp-stream-for-macro (eos) | |
984 | "Lex up a stream of tokens for a #define statement. | |
985 | Parsing starts at the current point location. | |
986 | EOS is the end of the stream to lex for this macro." | |
987 | (let ((stream nil)) | |
988 | (while (< (point) eos) | |
989 | (let* ((tok (semantic-lex-spp-one-token-and-move-for-macro eos)) | |
990 | (str (when tok | |
991 | (semantic-lex-token-text tok))) | |
992 | ) | |
993 | (if str | |
994 | (push (semantic-lex-token (semantic-lex-token-class tok) | |
995 | (semantic-lex-token-start tok) | |
996 | (semantic-lex-token-end tok) | |
997 | str) | |
998 | stream) | |
999 | ;; Nothing to push. | |
1000 | nil))) | |
1001 | (goto-char eos) | |
1002 | ;; Fix the order | |
1003 | (nreverse stream) | |
1004 | )) | |
1005 | ||
1006 | (defmacro define-lex-spp-macro-declaration-analyzer (name doc regexp tokidx | |
1007 | &rest valform) | |
1008 | "Define a lexical analyzer for defining new MACROS. | |
1009 | NAME is the name of the analyzer. | |
1010 | DOC is the documentation for the analyzer. | |
1011 | REGEXP is a regular expression for the analyzer to match. | |
1012 | See `define-lex-regex-analyzer' for more on regexp. | |
1013 | TOKIDX is an index into REGEXP for which a new lexical token | |
1014 | of type `spp-macro-def' is to be created. | |
1015 | VALFORM are forms that return the value to be saved for this macro, or nil. | |
1016 | When implementing a macro, you can use `semantic-lex-spp-stream-for-macro' | |
1017 | to convert text into a lexical stream for storage in the macro." | |
1018 | (let ((start (make-symbol "start")) | |
1019 | (end (make-symbol "end")) | |
1020 | (val (make-symbol "val")) | |
1021 | (startpnt (make-symbol "startpnt")) | |
1022 | (endpnt (make-symbol "endpnt"))) | |
1023 | `(define-lex-regex-analyzer ,name | |
1024 | ,doc | |
1025 | ,regexp | |
1026 | (let ((,start (match-beginning ,tokidx)) | |
1027 | (,end (match-end ,tokidx)) | |
1028 | (,startpnt semantic-lex-end-point) | |
1029 | (,val (save-match-data ,@valform)) | |
1030 | (,endpnt semantic-lex-end-point)) | |
1031 | (semantic-lex-spp-symbol-set | |
1032 | (buffer-substring-no-properties ,start ,end) | |
1033 | ,val) | |
1034 | (semantic-lex-push-token | |
1035 | (semantic-lex-token 'spp-macro-def | |
1036 | ,start ,end)) | |
1037 | ;; Preserve setting of the end point from the calling macro. | |
1038 | (when (and (/= ,startpnt ,endpnt) | |
1039 | (/= ,endpnt semantic-lex-end-point)) | |
1040 | (setq semantic-lex-end-point ,endpnt)) | |
1041 | )))) | |
1042 | ||
1043 | (defmacro define-lex-spp-macro-undeclaration-analyzer (name doc regexp tokidx) | |
1044 | "Undefine a lexical analyzer for defining new MACROS. | |
1045 | NAME is the name of the analyzer. | |
1046 | DOC is the documentation for the analyzer. | |
1047 | REGEXP is a regular expression for the analyzer to match. | |
1048 | See `define-lex-regex-analyzer' for more on regexp. | |
1049 | TOKIDX is an index into REGEXP for which a new lexical token | |
1050 | of type `spp-macro-undef' is to be created." | |
1051 | (let ((start (make-symbol "start")) | |
1052 | (end (make-symbol "end"))) | |
1053 | `(define-lex-regex-analyzer ,name | |
1054 | ,doc | |
1055 | ,regexp | |
1056 | (let ((,start (match-beginning ,tokidx)) | |
1057 | (,end (match-end ,tokidx)) | |
1058 | ) | |
1059 | (semantic-lex-spp-symbol-remove | |
1060 | (buffer-substring-no-properties ,start ,end)) | |
1061 | (semantic-lex-push-token | |
1062 | (semantic-lex-token 'spp-macro-undef | |
1063 | ,start ,end)) | |
1064 | )))) | |
1065 | ||
1066 | ;;; INCLUDES | |
1067 | ;; | |
1068 | ;; These analyzers help a language define how include files | |
1069 | ;; are identified. These are ONLY for languages that perform | |
1070 | ;; an actual textual includesion, and not for imports. | |
1071 | ;; | |
1072 | ;; This section is supposed to allow the macros from the headers to be | |
1073 | ;; added to the local dynamic macro table, but that hasn't been | |
1074 | ;; written yet. | |
1075 | ;; | |
1076 | (defcustom semantic-lex-spp-use-headers-flag nil | |
1077 | "*Non-nil means to pre-parse headers as we go. | |
1078 | For languages that use the Semantic pre-processor, this can | |
1079 | improve the accuracy of parsed files where include files | |
1080 | can change the state of what's parsed in the current file. | |
1081 | ||
1082 | Note: Note implemented yet" | |
1083 | :group 'semantic | |
1084 | :type 'boolean) | |
1085 | ||
1086 | (defun semantic-lex-spp-merge-header (name) | |
1087 | "Extract and merge any macros from the header with NAME. | |
1088 | Finds the header file belonging to NAME, gets the macros | |
1089 | from that file, and then merge the macros with our current | |
1090 | symbol table." | |
1091 | (when semantic-lex-spp-use-headers-flag | |
1092 | ;; @todo - do this someday, ok? | |
1093 | )) | |
1094 | ||
1095 | (defmacro define-lex-spp-include-analyzer (name doc regexp tokidx | |
1096 | &rest valform) | |
1097 | "Define a lexical analyzer for defining a new INCLUDE lexical token. | |
1098 | Macros defined in the found include will be added to our running table | |
1099 | at the time the include statement is found. | |
1100 | NAME is the name of the analyzer. | |
1101 | DOC is the documentation for the analyzer. | |
1102 | REGEXP is a regular expression for the analyzer to match. | |
1103 | See `define-lex-regex-analyzer' for more on regexp. | |
1104 | TOKIDX is an index into REGEXP for which a new lexical token | |
1105 | of type `spp-macro-include' is to be created. | |
1106 | VALFORM are forms that return the name of the thing being included, and the | |
1107 | type of include. The return value should be of the form: | |
1108 | (NAME . TYPE) | |
1109 | where NAME is the name of the include, and TYPE is the type of the include, | |
1110 | where a valid symbol is 'system, or nil." | |
1111 | (let ((start (make-symbol "start")) | |
1112 | (end (make-symbol "end")) | |
1113 | (val (make-symbol "val")) | |
1114 | (startpnt (make-symbol "startpnt")) | |
1115 | (endpnt (make-symbol "endpnt"))) | |
1116 | `(define-lex-regex-analyzer ,name | |
1117 | ,doc | |
1118 | ,regexp | |
1119 | (let ((,start (match-beginning ,tokidx)) | |
1120 | (,end (match-end ,tokidx)) | |
1121 | (,startpnt semantic-lex-end-point) | |
1122 | (,val (save-match-data ,@valform)) | |
1123 | (,endpnt semantic-lex-end-point)) | |
1124 | ;;(message "(car ,val) -> %S" (car ,val)) | |
1125 | (semantic-lex-spp-merge-header (car ,val)) | |
1126 | (semantic-lex-push-token | |
1127 | (semantic-lex-token (if (eq (cdr ,val) 'system) | |
1128 | 'spp-system-include | |
1129 | 'spp-include) | |
1130 | ,start ,end | |
1131 | (car ,val))) | |
1132 | ;; Preserve setting of the end point from the calling macro. | |
1133 | (when (and (/= ,startpnt ,endpnt) | |
1134 | (/= ,endpnt semantic-lex-end-point)) | |
1135 | (setq semantic-lex-end-point ,endpnt)) | |
1136 | )))) | |
1137 | ||
1138 | ;;; EIEIO USAGE | |
1139 | ;; | |
1140 | ;; Semanticdb can save off macro tables for quick lookup later. | |
1141 | ;; | |
1142 | ;; These routines are for saving macro lists into an EIEIO persistent | |
1143 | ;; file. | |
1144 | (defvar semantic-lex-spp-macro-max-length-to-save 200 | |
1145 | "*Maximum length of an SPP macro before we opt to not save it.") | |
1146 | ||
b90caf50 | 1147 | ;;;###autoload |
7a0e7d33 CY |
1148 | (defun semantic-lex-spp-table-write-slot-value (value) |
1149 | "Write out the VALUE of a slot for EIEIO. | |
1150 | The VALUE is a spp lexical table." | |
1151 | (if (not value) | |
1152 | (princ "nil") | |
1153 | (princ "\n '(") | |
1154 | ;(princ value) | |
1155 | (dolist (sym value) | |
1156 | (princ "(") | |
1157 | (prin1 (car sym)) | |
1158 | (let* ((first (car (cdr sym))) | |
1159 | (rest (cdr sym))) | |
988b91ce EL |
1160 | (if (not (listp first)) |
1161 | (insert "nil ;; bogus macro found.\n") | |
1162 | (when (eq (car first) 'spp-arg-list) | |
1163 | (princ " ") | |
1164 | (prin1 first) | |
1165 | (setq rest (cdr rest))) | |
1166 | ||
1167 | (when rest | |
1168 | (princ " . ") | |
1169 | (let ((len (length (cdr rest)))) | |
1170 | (cond ((< len 2) | |
1171 | (condition-case nil | |
1172 | (prin1 rest) | |
1173 | (error | |
1174 | (princ "nil ;; Error writing macro\n")))) | |
1175 | ((< len semantic-lex-spp-macro-max-length-to-save) | |
1176 | (princ "\n ") | |
1177 | (condition-case nil | |
1178 | (prin1 rest) | |
1179 | (error | |
1180 | (princ "nil ;; Error writing macro\n ")))) | |
1181 | (t ;; Too Long! | |
1182 | (princ "nil ;; Too Long!\n "))))))) | |
1183 | (princ ")\n ")) | |
1184 | (princ ")\n"))) | |
7a0e7d33 | 1185 | |
7a0e7d33 CY |
1186 | ;;; MACRO TABLE DEBUG |
1187 | ;; | |
1188 | (defun semantic-lex-spp-describe (&optional buffer) | |
1189 | "Describe the current list of spp macros for BUFFER. | |
1190 | If BUFFER is not provided, use the current buffer." | |
1191 | (interactive) | |
1192 | (let ((syms (save-excursion | |
1193 | (if buffer (set-buffer buffer)) | |
1194 | (semantic-lex-spp-macros))) | |
1195 | (sym nil)) | |
1196 | (with-output-to-temp-buffer "*SPP MACROS*" | |
1197 | (princ "Macro\t\tValue\n") | |
1198 | (while syms | |
1199 | (setq sym (car syms) | |
1200 | syms (cdr syms)) | |
1201 | (princ (symbol-name sym)) | |
1202 | (princ "\t") | |
1203 | (if (< (length (symbol-name sym)) 8) | |
1204 | (princ "\t")) | |
1205 | (prin1 (symbol-value sym)) | |
1206 | (princ "\n") | |
1207 | )))) | |
1208 | ||
1209 | ;;; EDEBUG Handlers | |
1210 | ;; | |
1211 | (add-hook | |
1212 | 'edebug-setup-hook | |
1213 | #'(lambda () | |
1214 | ||
1215 | (def-edebug-spec define-lex-spp-macro-declaration-analyzer | |
1216 | (&define name stringp stringp form def-body) | |
1217 | ) | |
1218 | ||
1219 | (def-edebug-spec define-lex-spp-macro-undeclaration-analyzer | |
1220 | (&define name stringp stringp form) | |
1221 | ) | |
1222 | ||
1223 | (def-edebug-spec define-lex-spp-include-analyzer | |
b90caf50 | 1224 | (&define name stringp stringp form def-body)))) |
7a0e7d33 CY |
1225 | |
1226 | (provide 'semantic/lex-spp) | |
1227 | ||
b90caf50 CY |
1228 | ;; Local variables: |
1229 | ;; generated-autoload-file: "loaddefs.el" | |
b90caf50 CY |
1230 | ;; generated-autoload-load-name: "semantic/lex-spp" |
1231 | ;; End: | |
1232 | ||
3999968a | 1233 | ;; arch-tag: 8877d83e-07ea-4d86-a960-e3562138d8a5 |
7a0e7d33 | 1234 | ;;; semantic-lex-spp.el ends here |