Commit | Line | Data |
---|---|---|
469d2149 CY |
1 | ;;; semantic/bovine/c.by -- LL grammar for C/C++ language specification |
2 | ;; | |
3 | ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Eric M. Ludlam | |
4 | ;; Copyright (C) 2002, 2003 David Ponce | |
5 | ;; | |
6 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
7 | ;; David Ponce <david@dponce.com> | |
8 | ;; Klaus Berndl <klaus.berndl@sdm.de> | |
9 | ;; | |
10 | ;; | |
11 | ;; This program is free software; you can redistribute it and/or modify | |
12 | ;; it under the terms of the GNU General Public License as published by | |
13 | ;; the Free Software Foundation; either version 2, or (at your option) | |
14 | ;; any later version. | |
15 | ;; | |
16 | ;; This software is distributed in the hope that it will be useful, | |
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;; GNU General Public License for more details. | |
20 | ;; | |
21 | ;; You should have received a copy of the GNU General Public License | |
22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
23 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
24 | ;; Boston, MA 02110-1301, USA. | |
25 | ;; | |
26 | ||
27 | ;; TODO: From Nate Schley | |
28 | ;; > * Can't parse signature element: "const char* const rmc_ClrTxt" | |
29 | ;; > * Can't parse signature element: "char* const dellog_ClrTxt" | |
30 | ;; > * Can't parse signature element: "const char* dellog_SetTxt" | |
31 | ;; > * Can't parse signature element: "const RmcCmdSSPADetailedStatus& status" | |
32 | ;; > | |
33 | ;; > And FWIW I have seen the following argument cases not handled, even | |
34 | ;; > with no leading/trailing spaces in the split: | |
35 | ;; > | |
36 | ;; > * Can't parse signature element: "const bool currentAlarmStatus" | |
37 | ;; > * Can't parse signature element: "unsigned char mode" | |
38 | ;; > * Can't parse signature element: "TskTimingTask* tsktimingtask" | |
39 | ;; > * Can't parse signature element: "unsigned char htrStatus" | |
40 | ;; > * Can't parse signature element: "char trackPower[]" | |
41 | ;; > * Can't parse signature element: "const RmcCmdMCDetailedStatus& status" | |
42 | ;; > * Can't parse signature element: "RmcBucStatus* rftBucStatus" | |
43 | ||
44 | %package c-by | |
45 | ||
46 | %languagemode c-mode c++-mode | |
47 | %start declaration | |
48 | %scopestart codeblock | |
49 | ||
50 | %token <punctuation> HASH "\\`[#]\\'" | |
51 | %token <punctuation> PERIOD "\\`[.]\\'" | |
52 | %token <punctuation> COLON "\\`[:]\\'" | |
53 | %token <punctuation> SEMICOLON "\\`[;]\\'" | |
54 | %token <punctuation> STAR "\\`[*]\\'" | |
55 | %token <punctuation> AMPERSAND "\\`[&]\\'" | |
56 | %token <punctuation> DIVIDE "\\`[/]\\'" | |
57 | %token <punctuation> PLUS "\\`[+]\\'" | |
58 | %token <punctuation> MINUS "\\`[-]\\'" | |
59 | %token <punctuation> BANG "\\`[!]\\'" | |
60 | %token <punctuation> EQUAL "\\`[=]\\'" | |
61 | %token <punctuation> LESS "\\`[<]\\'" | |
62 | %token <punctuation> GREATER "\\`[>]\\'" | |
63 | %token <punctuation> COMA "\\`[,]\\'" | |
64 | %token <punctuation> TILDE "\\`[~]\\'" | |
65 | %token <punctuation> MOD "\\`[%]\\'" | |
66 | %token <punctuation> HAT "\\`\\^\\'" | |
67 | %token <punctuation> OR "\\`[|]\\'" | |
68 | %token <string> C "\"C\"" | |
69 | %token <string> CPP "\"C\\+\\+\"" | |
70 | %token <number> ZERO "^0$" | |
71 | %token <symbol> RESTRICT "\\<\\(__\\)?restrict\\>" | |
72 | %token <open-paren> LPAREN "(" | |
73 | %token <close-paren> RPAREN ")" | |
74 | %token <open-paren> LBRACE "{" | |
75 | %token <close-paren> RBRACE "}" | |
76 | %token <semantic-list> BRACK_BLCK "\\[.*\\]$" | |
77 | %token <semantic-list> PAREN_BLCK "^(" | |
78 | %token <semantic-list> BRACE_BLCK "^{" | |
79 | %token <semantic-list> VOID_BLCK "^(void)$" | |
80 | %token <semantic-list> PARENS "()" | |
81 | %token <semantic-list> BRACKETS "\\[\\]" | |
82 | ||
83 | %token EXTERN "extern" | |
84 | %put EXTERN summary "Declaration Modifier: extern <type> <name> ..." | |
85 | %token STATIC "static" | |
86 | %put STATIC summary "Declaration Modifier: static <type> <name> ..." | |
87 | %token CONST "const" | |
88 | %put CONST summary "Declaration Modifier: const <type> <name> ..." | |
89 | %token VOLATILE "volatile" | |
90 | %put VOLATILE summary "Declaration Modifier: volatile <type> <name> ..." | |
91 | %token REGISTER "register" | |
92 | %put REGISTER summary "Declaration Modifier: register <type> <name> ..." | |
93 | %token SIGNED "signed" | |
94 | %put SIGNED summary "Numeric Type Modifier: signed <numeric type> <name> ..." | |
95 | %token UNSIGNED "unsigned" | |
96 | %put UNSIGNED summary "Numeric Type Modifier: unsigned <numeric type> <name> ..." | |
97 | ||
98 | %token INLINE "inline" | |
99 | %put INLINE summary "Function Modifier: inline <return type> <name>(...) {...};" | |
100 | %token VIRTUAL "virtual" | |
101 | %put VIRTUAL summary "Method Modifier: virtual <type> <name>(...) ..." | |
102 | %token MUTABLE "mutable" | |
103 | %put MUTABLE summary "Member Declaration Modifier: mutable <type> <name> ..." | |
104 | ||
105 | %token STRUCT "struct" | |
106 | %put STRUCT summary "Structure Type Declaration: struct [name] { ... };" | |
107 | %token UNION "union" | |
108 | %put UNION summary "Union Type Declaration: union [name] { ... };" | |
109 | %token ENUM "enum" | |
110 | %put ENUM summary "Enumeration Type Declaration: enum [name] { ... };" | |
111 | %token TYPEDEF "typedef" | |
112 | %put TYPEDEF summary "Arbitrary Type Declaration: typedef <typedeclaration> <name>;" | |
113 | %token CLASS "class" | |
114 | %put CLASS summary "Class Declaration: class <name>[:parents] { ... };" | |
115 | %token TYPENAME "typename" | |
116 | %put TYPENAME summary "typename is used to handle a qualified name as a typename;" | |
117 | %token NAMESPACE "namespace" | |
118 | %put NAMESPACE summary "Namespace Declaration: namespace <name> { ... };" | |
119 | %token USING "using" | |
120 | %put USING summary "using <namespace>;" | |
121 | ||
122 | %token NEW "new" | |
123 | %put NEW summary "new <classname>();" | |
124 | %token DELETE "delete" | |
125 | %put DELETE summary "delete <object>;" | |
126 | ||
127 | ;; Despite this, this parser can find templates by ignoring the TEMPLATE | |
128 | ;; keyword, and finding the class/method being templateized. | |
129 | %token TEMPLATE "template" | |
130 | %put TEMPLATE summary "template <class TYPE ...> TYPE_OR_FUNCTION" | |
131 | ||
132 | %token THROW "throw" | |
133 | %put THROW summary "<type> <methoddef> (<method args>) throw (<exception>) ..." | |
134 | %token REENTRANT "reentrant" | |
135 | %put REENTRANT summary "<type> <methoddef> (<method args>) reentrant ..." | |
136 | %token TRY "try" | |
137 | %token CATCH "catch" | |
138 | %put { TRY CATCH } summary "try { <body> } catch { <catch code> }" | |
139 | ||
140 | ;; Leave these alone for now. | |
141 | %token OPERATOR "operator" | |
142 | %token PUBLIC "public" | |
143 | %token PRIVATE "private" | |
144 | %token PROTECTED "protected" | |
145 | %token FRIEND "friend" | |
146 | %put FRIEND summary "friend class <CLASSNAME>" | |
147 | ||
148 | ;; These aren't used for parsing, but is a useful place to describe the keywords. | |
149 | %token IF "if" | |
150 | %token ELSE "else" | |
151 | %put {IF ELSE} summary "if (<condition>) { code } [ else { code } ]" | |
152 | ||
153 | %token DO "do" | |
154 | %token WHILE "while" | |
155 | %put DO summary " do { code } while (<condition>);" | |
156 | %put WHILE summary "do { code } while (<condition>); or while (<condition>) { code };" | |
157 | ||
158 | %token FOR "for" | |
159 | %put FOR summary "for(<init>; <condition>; <increment>) { code }" | |
160 | ||
161 | %token SWITCH "switch" | |
162 | %token CASE "case" | |
163 | %token DEFAULT "default" | |
164 | %put {SWITCH CASE DEFAULT} summary | |
165 | "switch (<variable>) { case <constvalue>: code; ... default: code; }" | |
166 | ||
167 | %token RETURN "return" | |
168 | %put RETURN summary "return <value>;" | |
169 | ||
170 | %token BREAK "break" | |
171 | %put BREAK summary "Non-local exit within a loop or switch (for, do/while, switch): break;" | |
172 | %token CONTINUE "continue" | |
173 | %put CONTINUE summary "Non-local continue within a loop (for, do/while): continue;" | |
174 | ||
175 | %token SIZEOF "sizeof" | |
176 | %put SIZEOF summary "Compile time macro: sizeof(<type or variable>) // size in bytes" | |
177 | ||
178 | ;; Types | |
179 | %token VOID "void" | |
180 | %put VOID summary "Built in typeless type: void" | |
181 | %token CHAR "char" | |
182 | %put CHAR summary "Integral Character Type: (0 to 256)" | |
183 | %token WCHAR "wchar_t" | |
184 | %put WCHAR summary "Wide Character Type" | |
185 | %token SHORT "short" | |
186 | %put SHORT summary "Integral Primitive Type: (-32768 to 32767)" | |
187 | %token INT "int" | |
188 | %put INT summary "Integral Primitive Type: (-2147483648 to 2147483647)" | |
189 | %token LONG "long" | |
190 | %put LONG summary "Integral primitive type (-9223372036854775808 to 9223372036854775807)" | |
191 | %token FLOAT "float" | |
192 | %put FLOAT summary "Primitive floating-point type (single-precision 32-bit IEEE 754)" | |
193 | %token DOUBLE "double" | |
194 | %put DOUBLE summary "Primitive floating-point type (double-precision 64-bit IEEE 754)" | |
195 | %token BOOL "bool" | |
196 | %put BOOL summary "Primitive boolean type" | |
197 | ||
198 | %token UNDERP "_P" | |
199 | %token UNDERUNDERP "__P" | |
200 | %put UNDERP summary "Common macro to eliminate prototype compatibility on some compilers" | |
201 | %put UNDERUNDERP summary "Common macro to eliminate prototype compatibility on some compilers" | |
202 | ||
203 | %% | |
204 | ||
205 | declaration | |
206 | : macro | |
207 | | type | |
208 | ;; TODO: Klaus Berndl: Is the define here necessary or even wrong? | |
209 | ;; Is this part not already covered by macro?? | |
210 | | define | |
211 | | var-or-fun | |
212 | | extern-c | |
213 | | template | |
214 | | using | |
215 | ; | |
216 | ||
217 | codeblock | |
218 | : define | |
219 | | codeblock-var-or-fun | |
220 | | type ;; type is less likely to be used here. | |
221 | | using | |
222 | ; | |
223 | ||
224 | extern-c-contents | |
225 | : open-paren | |
226 | ( nil ) | |
227 | | declaration | |
228 | | close-paren | |
229 | ( nil ) | |
230 | ; | |
231 | ||
232 | extern-c | |
233 | : EXTERN C semantic-list | |
234 | ;; Extern C commands which contain a list need to have the | |
235 | ;; entries of the list extracted, and spliced into the main | |
236 | ;; list of entries. This must be done via the function | |
237 | ;; that expands singular nonterminals, such as int x,y; | |
238 | (TAG "C" 'extern :members (EXPANDFULL $3 extern-c-contents) ) | |
239 | | EXTERN CPP semantic-list | |
240 | (TAG "C" 'extern :members (EXPANDFULL $3 extern-c-contents) ) | |
241 | | EXTERN C | |
242 | ;; A plain extern "C" call should add something to the token, | |
243 | ;; but just strip it from the buffer here for now. | |
244 | ( nil ) | |
245 | | EXTERN CPP | |
246 | ( nil ) | |
247 | ; | |
248 | ||
249 | macro | |
250 | : spp-macro-def | |
251 | (VARIABLE-TAG $1 nil nil :constant-flag t ) | |
252 | | spp-system-include | |
253 | (INCLUDE-TAG $1 t) | |
254 | | spp-include | |
255 | (INCLUDE-TAG $1 nil) | |
256 | ; | |
257 | ||
258 | ;; This is used in struct parts. | |
259 | define | |
260 | : spp-macro-def | |
261 | (VARIABLE-TAG $1 nil nil :constant-flag t) | |
262 | | spp-macro-undef | |
263 | ( nil ) | |
264 | ; | |
265 | ||
266 | ;; In C++, structures can have the same things as classes. | |
267 | ;; So delete this somday in the figure. | |
268 | ;; | |
269 | ;;structparts : semantic-list | |
270 | ;; (EXPANDFULL $1 structsubparts) | |
271 | ;; ; | |
272 | ;; | |
273 | ;;structsubparts : LBRACE | |
274 | ;; ( nil ) | |
275 | ;; | RBRACE | |
276 | ;; ( nil ) | |
277 | ;; | var-or-fun | |
278 | ;; | define | |
279 | ;; ;; sometimes there are defines in structs. | |
280 | ;; ; | |
281 | ||
282 | unionparts | |
283 | : semantic-list | |
284 | (EXPANDFULL $1 classsubparts) | |
285 | ; | |
286 | ||
287 | opt-symbol | |
288 | : symbol | |
289 | | ;;EMPTY | |
290 | ; | |
291 | ||
292 | ;; @todo - support 'friend' construct. | |
293 | classsubparts | |
294 | : LBRACE | |
295 | ( nil ) | |
296 | | RBRACE | |
297 | ( nil ) | |
298 | | class-protection opt-symbol COLON | |
299 | ;; For QT, they may put a `slot' keyword between the protection | |
300 | ;; and the COLON. @todo - Have the QT stuff use macros. | |
301 | (TAG (car $1) 'label) | |
302 | | var-or-fun | |
303 | | FRIEND func-decl | |
304 | (TAG (car $2) 'friend) | |
305 | | FRIEND CLASS symbol | |
306 | (TAG $3 'friend) | |
307 | | type | |
308 | | define | |
309 | | template | |
310 | | ;;EMPTY | |
311 | ; | |
312 | ||
313 | opt-class-parents | |
314 | : COLON class-parents opt-template-specifier | |
315 | ( $2 ) | |
316 | | ;;EMPTY | |
317 | ( ) | |
318 | ; | |
319 | ||
320 | one-class-parent | |
321 | : opt-class-protection opt-class-declmods namespace-symbol | |
322 | (TYPE-TAG (car $3) "class" nil nil :protection (car $1)) | |
323 | | opt-class-declmods opt-class-protection namespace-symbol | |
324 | (TYPE-TAG (car $3) "class" nil nil :protection (car $2)) | |
325 | ; | |
326 | ||
327 | class-parents | |
328 | : one-class-parent COMA class-parents | |
329 | ( ,(cons ,$1 $3 ) ) | |
330 | | one-class-parent | |
331 | ( $1 ) | |
332 | ; | |
333 | ||
334 | opt-class-declmods | |
335 | : class-declmods opt-class-declmods | |
336 | ( nil ) | |
337 | | ;;EMPTY | |
338 | ; | |
339 | ||
340 | class-declmods | |
341 | : VIRTUAL | |
342 | ; | |
343 | ||
344 | class-protection | |
345 | : PUBLIC | |
346 | | PRIVATE | |
347 | | PROTECTED | |
348 | ; | |
349 | ||
350 | opt-class-protection | |
351 | : class-protection | |
352 | ( ,$1 ) | |
353 | | ;;EMPTY - Same as private | |
354 | ( "unspecified" ) | |
355 | ; | |
356 | ||
357 | namespaceparts | |
358 | : semantic-list | |
359 | (EXPANDFULL $1 namespacesubparts) | |
360 | ; | |
361 | ||
362 | namespacesubparts | |
363 | : LBRACE | |
364 | ( nil ) | |
365 | | RBRACE | |
366 | ( nil ) | |
367 | | type | |
368 | | var-or-fun | |
369 | | define | |
370 | | class-protection COLON | |
371 | (TAG (car $1) 'label) | |
372 | ;; In C++, this label in a classsubpart represents | |
373 | ;; PUBLIC or PRIVATE bits. Ignore them for now. | |
374 | | template | |
375 | | using | |
376 | | ;;EMPTY | |
377 | ; | |
378 | ||
379 | enumparts | |
380 | : semantic-list | |
381 | (EXPANDFULL $1 enumsubparts) | |
382 | ; | |
383 | ||
384 | enumsubparts | |
385 | : symbol opt-assign | |
386 | (VARIABLE-TAG $1 "int" (car $2) :constant-flag t ) | |
387 | | LBRACE | |
388 | ( nil ) | |
389 | | RBRACE | |
390 | ( nil ) | |
391 | | COMA | |
392 | ( nil ) | |
393 | ; | |
394 | ||
395 | opt-name | |
396 | : symbol | |
397 | | ;;EMPTY | |
398 | ( "" ) | |
399 | ; | |
400 | ||
401 | typesimple | |
402 | : struct-or-class opt-class opt-name opt-template-specifier | |
403 | opt-class-parents semantic-list | |
404 | (TYPE-TAG (car $3) (car $1) | |
405 | (let ((semantic-c-classname (cons (car ,$3) (car ,$1)))) | |
406 | (EXPANDFULL $6 classsubparts)) | |
407 | $5 | |
408 | :template-specifier $4 | |
409 | :parent (car ,$2)) | |
410 | | struct-or-class opt-class opt-name opt-template-specifier | |
411 | opt-class-parents | |
412 | (TYPE-TAG (car $3) (car $1) nil $5 | |
413 | :template-specifier $4 | |
414 | :prototype t | |
415 | :parent (car ,$2)) | |
416 | | UNION opt-class opt-name unionparts | |
417 | (TYPE-TAG (car $3) $1 $4 nil | |
418 | :parent (car ,$2)) | |
419 | | ENUM opt-class opt-name enumparts | |
420 | (TYPE-TAG (car $3) $1 $4 nil | |
421 | :parent (car ,$2)) | |
422 | ;; Klaus Berndl: a typedef can be a typeformbase with all this | |
423 | ;; declmods stuff. | |
424 | | TYPEDEF declmods typeformbase cv-declmods typedef-symbol-list | |
425 | ;;;; We put the type this typedef renames into PARENT | |
426 | ;;;; but will move it in the expand function. | |
427 | (TYPE-TAG $5 $1 nil (list $3) ) | |
428 | ; | |
429 | ||
430 | typedef-symbol-list | |
431 | : typedefname COMA typedef-symbol-list | |
432 | ( ,(cons $1 $3) ) | |
433 | | typedefname | |
434 | ( $1 ) | |
435 | ; | |
436 | ||
437 | ;; TODO: Klaus Berndl: symbol -> namespace-symbol?! Answer: Probably | |
438 | ;; symbol is correct here! | |
439 | typedefname | |
440 | : opt-stars symbol opt-bits opt-array | |
441 | ( $1 $2 ) | |
442 | ; | |
443 | ||
444 | struct-or-class | |
445 | : STRUCT | |
446 | | CLASS | |
447 | ; | |
448 | ||
449 | type | |
450 | : typesimple SEMICOLON | |
451 | ( ,$1 ) | |
452 | ;; named namespaces like "namespace XXX {" | |
453 | | NAMESPACE symbol namespaceparts | |
454 | (TYPE-TAG $2 $1 $3 nil ) | |
455 | ;; unnamed namespaces like "namespace {" | |
456 | | NAMESPACE namespaceparts | |
457 | (TYPE-TAG "unnamed" $1 $2 nil ) | |
458 | ;; David Engster: namespace alias like "namespace foo = bar;" | |
459 | | NAMESPACE symbol EQUAL typeformbase SEMICOLON | |
460 | (TYPE-TAG $2 $1 (list (TYPE-TAG (car $4) $1 nil nil)) nil :kind 'alias ) | |
461 | ; | |
462 | ||
463 | ;; Klaus Berndl: We must parse "using namespace XXX" too | |
464 | ||
465 | ;; Using is vaguely like an include statement in the named portions | |
466 | ;; of the code. We should probably specify a new token type for this. | |
467 | ||
468 | using | |
469 | : USING usingname SEMICOLON | |
470 | (TAG (car $2) 'using :type ,$2 ) | |
471 | ; | |
472 | ||
473 | ;; Jan Moringen: Differentiate between 'using' and 'using namespace' | |
474 | ;; Adapted to creating type tags by EML. | |
475 | usingname | |
476 | : typeformbase | |
477 | (TYPE-TAG (car $1) "class" nil nil :prototype t) | |
478 | | NAMESPACE typeformbase | |
479 | (TYPE-TAG (car $2) "namespace" nil nil :prototype t) | |
480 | ; | |
481 | ||
482 | template | |
483 | : TEMPLATE template-specifier opt-friend template-definition | |
484 | ( ,(semantic-c-reconstitute-template $4 ,$2) ) | |
485 | ; | |
486 | ||
487 | opt-friend | |
488 | : FRIEND | |
489 | | ;;EMPTY | |
490 | ; | |
491 | ||
492 | opt-template-specifier | |
493 | : template-specifier | |
494 | ( ,$1 ) | |
495 | | ;;EMPTY | |
496 | ( ) | |
497 | ; | |
498 | ||
499 | template-specifier | |
500 | : LESS template-specifier-types GREATER | |
501 | ( ,$2 ) | |
502 | ; | |
503 | ||
504 | template-specifier-types | |
505 | : template-var template-specifier-type-list | |
506 | ( ,(cons ,$1 ,$2 ) ) | |
507 | | ;;EMPTY | |
508 | ; | |
509 | ||
510 | template-specifier-type-list | |
511 | : COMA template-specifier-types | |
512 | ( ,$2 ) | |
513 | | ;;EMPTY | |
514 | ( ) | |
515 | ; | |
516 | ||
517 | ;; template-var | |
518 | ;; : template-type opt-stars opt-template-equal | |
519 | ;; ( ,(cons (concat (car $1) (make-string (car ,$2) ?*)) | |
520 | ;; (cdr $1))) | |
521 | ;; ;; Klaus Berndl: for template-types the template-var can also be | |
522 | ;; ;; literals or constants. Example: map<ClassX, ClassY, 10> | |
523 | ;; ;; map_size10_var; This parses also template<class T, 0> which is | |
524 | ;; ;; nonsense but who cares.... | |
525 | ;; | string | |
526 | ;; ( $1 ) | |
527 | ;; | number | |
528 | ;; ( $1 ) | |
529 | ;; ; | |
530 | ||
531 | template-var | |
532 | : | |
533 | ;; Klaus Berndl: The following handles all template-vars of | |
534 | ;; template-definitions | |
535 | template-type opt-template-equal | |
536 | ( ,(cons (car $1) (cdr $1)) ) | |
537 | ;; Klaus Berndl: for template-types the template-var can also be | |
538 | ;; literals or constants. | |
539 | ;; Example: map<ClassX, ClassY, 10> map_size10_var; This parses also | |
540 | ;; template<class T, 0> which is nonsense but who cares.... | |
541 | | string | |
542 | ( $1 ) | |
543 | | number | |
544 | ( $1 ) | |
545 | ;; Klaus Berndl: In template-types arguments can be any symbols with | |
546 | ;; optional address-operator (&) and optional dereferencing operator | |
547 | ;; (*). Example map<ClassX, ClassY, *size_var_ptr> sized_map_var. | |
548 | | opt-stars opt-ref namespace-symbol | |
549 | ( ,$3 ) | |
550 | ;; Some code can compile down into a number, but starts out as an | |
551 | ;; expression, such as "sizeof(a)", or (sizeof(a)/sizeof(b)) | |
552 | | semantic-list | |
553 | ( $1 ) | |
554 | | SIZEOF semantic-list | |
555 | ( $2 ) | |
556 | ; | |
557 | ||
558 | opt-template-equal | |
559 | : EQUAL symbol LESS template-specifier-types GREATER | |
560 | ( $2 ) | |
561 | | EQUAL symbol | |
562 | ( $2 ) | |
563 | | ;;EMPTY | |
564 | ( ) | |
565 | ; | |
566 | ||
567 | template-type | |
568 | : CLASS symbol | |
569 | (TYPE-TAG $2 "class" nil nil ) | |
570 | | STRUCT symbol | |
571 | (TYPE-TAG $2 "struct" nil nil ) | |
572 | ;; TODO: Klaus Berndl: For the moment is is ok, that we parse the C++ | |
573 | ;; keyword typename as a class.... | |
574 | | TYPENAME symbol | |
575 | (TYPE-TAG $2 "class" nil nil) | |
576 | ;; Klaus Berndl: template-types can be all flavors of variable-args | |
577 | ;; but here the argument is ignored, only the type stuff is needed. | |
578 | | declmods typeformbase cv-declmods opt-stars | |
579 | opt-ref variablearg-opt-name | |
580 | (TYPE-TAG (car $2) nil nil nil | |
581 | :constant-flag (if (member "const" (append $1 $3)) t nil) | |
582 | :typemodifiers (delete "const" (append $1 $3)) | |
583 | :reference (car ,$5) | |
584 | :pointer (car $4) | |
585 | ) | |
586 | ; | |
587 | ||
588 | template-definition | |
589 | : type | |
590 | ( ,$1 ) | |
591 | | var-or-fun | |
592 | ( ,$1 ) | |
593 | ; | |
594 | ||
595 | opt-stars | |
596 | : STAR opt-starmod opt-stars | |
597 | ( (1+ (car $3)) ) | |
598 | | ;;EMPTY | |
599 | ( 0 ) | |
600 | ; | |
601 | ||
602 | opt-starmod | |
603 | : STARMOD opt-starmod | |
604 | ( ,(cons (,car ,$1) $2) ) | |
605 | | ;;EMPTY | |
606 | () | |
607 | ; | |
608 | ||
609 | STARMOD | |
610 | : CONST | |
611 | ; | |
612 | ||
613 | declmods | |
614 | : DECLMOD declmods | |
615 | ( ,(cons ,(car ,$1) $2 ) ) | |
616 | | DECLMOD | |
617 | ( ,$1 ) | |
618 | | ;;EMPTY | |
619 | () | |
620 | ; | |
621 | ||
622 | DECLMOD | |
623 | : EXTERN | |
624 | | STATIC | |
625 | | CVDECLMOD | |
626 | ;; Klaus Berndl: IMHO signed and unsigned are not decl-modes but | |
627 | ;; these are only valid for some buildin-types like short, int | |
628 | ;; etc... whereas "real" declmods are valid for all types, buildin | |
629 | ;; and user-defined! SIGNED UNSIGNED | |
630 | | INLINE | |
631 | | REGISTER | |
632 | | FRIEND | |
633 | ;; Klaus Berndl: There can be a few cases where TYPENAME is not | |
634 | ;; allowed in C++-syntax but better than not recognizing the allowed | |
635 | ;; situations. | |
636 | | TYPENAME | |
637 | | METADECLMOD | |
638 | ;; This is a hack in case we are in a class. | |
639 | | VIRTUAL | |
640 | ; | |
641 | ||
642 | metadeclmod | |
643 | : METADECLMOD | |
644 | () | |
645 | | ;;EMPTY | |
646 | () | |
647 | ; | |
648 | ||
649 | CVDECLMOD | |
650 | : CONST | |
651 | | VOLATILE | |
652 | ; | |
653 | ||
654 | cv-declmods | |
655 | : CVDECLMOD cv-declmods | |
656 | ( ,(cons ,(car ,$1) $2 ) ) | |
657 | | CVDECLMOD | |
658 | ( ,$1 ) | |
659 | | ;;EMPTY | |
660 | () | |
661 | ; | |
662 | ||
663 | METADECLMOD | |
664 | : VIRTUAL | |
665 | | MUTABLE | |
666 | ; | |
667 | ||
668 | ;; C++: A type can be modified into a reference by "&" | |
669 | opt-ref | |
670 | : AMPERSAND | |
671 | ( 1 ) | |
672 | | ;;EMPTY | |
673 | ( 0 ) | |
674 | ; | |
675 | ||
676 | typeformbase | |
677 | : typesimple | |
678 | ( ,$1 ) | |
679 | | STRUCT symbol | |
680 | (TYPE-TAG $2 $1 nil nil ) | |
681 | | UNION symbol | |
682 | (TYPE-TAG $2 $1 nil nil ) | |
683 | | ENUM symbol | |
684 | (TYPE-TAG $2 $1 nil nil ) | |
685 | | builtintype | |
686 | ( ,$1 ) | |
687 | | symbol template-specifier | |
688 | (TYPE-TAG $1 "class" nil nil :template-specifier $2) | |
689 | ;;| namespace-symbol opt-stars opt-template-specifier | |
690 | ;;| namespace-symbol opt-template-specifier | |
691 | | namespace-symbol-for-typeformbase opt-template-specifier | |
692 | (TYPE-TAG (car $1) "class" nil nil | |
693 | :template-specifier $2) | |
694 | | symbol | |
695 | ( $1 ) | |
696 | ; | |
697 | ||
698 | signedmod | |
699 | : UNSIGNED | |
700 | | SIGNED | |
701 | ; | |
702 | ||
703 | ;; Klaus Berndl: builtintype-types was builtintype | |
704 | builtintype-types | |
705 | : VOID | |
706 | | CHAR | |
707 | ;; Klaus Berndl: Added WCHAR | |
708 | | WCHAR | |
709 | | SHORT INT | |
710 | ( (concat $1 " " $2) ) | |
711 | | SHORT | |
712 | | INT | |
713 | | LONG INT | |
714 | ( (concat $1 " " $2) ) | |
715 | | FLOAT | |
716 | | DOUBLE | |
717 | | BOOL | |
718 | | LONG DOUBLE | |
719 | ( (concat $1 " " $2) ) | |
720 | ;; TODO: Klaus Berndl: Is there a long long, i think so?! | |
721 | | LONG LONG | |
722 | ( (concat $1 " " $2) ) | |
723 | | LONG | |
724 | ; | |
725 | ||
726 | builtintype | |
727 | : signedmod builtintype-types | |
728 | ( (concat (car $1) " " (car $2)) ) | |
729 | | builtintype-types | |
730 | ( ,$1 ) | |
731 | ;; Klaus Berndl: unsigned is synonym for unsigned int and signed for | |
732 | ;; signed int. To make this confusing stuff clear we add here the | |
733 | ;; int. | |
734 | | signedmod | |
735 | ( (concat (car $1) " int") ) | |
736 | ; | |
737 | ||
738 | ;; Klaus Berndl: This parses also nonsense like "const volatile int | |
739 | ;; const volatile const const volatile a ..." but IMHO nobody writes | |
740 | ;; such code. Normaly we shoud define a rule like typeformbase-mode | |
741 | ;; which exactly defines the different allowed cases and combinations | |
742 | ;; of declmods (minus the CVDECLMOD) typeformbase and cv-declmods so | |
743 | ;; we could recognize more invalid code but IMHO this is not worth the | |
744 | ;; effort... | |
745 | codeblock-var-or-fun | |
746 | : declmods typeformbase declmods | |
747 | opt-ref var-or-func-decl | |
748 | ( ,(semantic-c-reconstitute-token ,$5 $1 $2 ) ) | |
749 | ; | |
750 | ||
751 | var-or-fun | |
752 | : codeblock-var-or-fun | |
753 | ( ,$1 ) | |
754 | ;; it is possible for a function to not have a type, and | |
755 | ;; it is then assumed to be an int. How annoying. | |
756 | ;; In C++, this could be a constructor or a destructor. | |
757 | ;; Even more annoying. Only ever do this for regular | |
758 | ;; top-level items. Ignore this problem in code blocks | |
759 | ;; so that we don't have to deal with regular code | |
760 | ;; being erroneously converted into types. | |
761 | | declmods var-or-func-decl | |
762 | ( ,(semantic-c-reconstitute-token ,$2 $1 nil ) ) | |
763 | ; | |
764 | ||
765 | var-or-func-decl | |
766 | : func-decl | |
767 | ( ,$1 ) | |
768 | | var-decl | |
769 | ( ,$1 ) | |
770 | ; | |
771 | ||
772 | func-decl | |
773 | : opt-stars opt-class opt-destructor functionname | |
774 | opt-template-specifier | |
775 | opt-under-p | |
776 | arg-list | |
777 | opt-post-fcn-modifiers | |
778 | opt-throw | |
779 | opt-initializers | |
780 | fun-or-proto-end | |
781 | ( ,$4 'function | |
782 | ;; Extra stuff goes in here. | |
783 | ;; Continue with the stuff we found in | |
784 | ;; this definition | |
785 | $2 $3 $7 $9 $8 ,$1 ,$11 $5 ,$10) | |
786 | | opt-stars opt-class opt-destructor functionname | |
787 | opt-template-specifier | |
788 | opt-under-p | |
789 | ;; arg-list - - ini this case, a try implies a fcn. | |
790 | opt-post-fcn-modifiers | |
791 | opt-throw | |
792 | opt-initializers | |
793 | fun-try-end | |
794 | ( ,$4 'function | |
795 | ;; Extra stuff goes in here. | |
796 | ;; Continue with the stuff we found in | |
797 | ;; this definition | |
798 | $2 $3 nil $8 $7 ,$1 ,$10 $5 ,$9) | |
799 | ; | |
800 | ||
801 | var-decl | |
802 | : varnamelist SEMICOLON | |
803 | ( $1 'variable ) | |
804 | ; | |
805 | ||
806 | opt-under-p | |
807 | : UNDERP | |
808 | ( nil ) | |
809 | | UNDERUNDERP | |
810 | ( nil ) | |
811 | | ;;EMPTY | |
812 | ; | |
813 | ||
814 | ;; Klaus Berndl: symbol -> namespace-symbol | |
815 | opt-initializers | |
816 | : COLON namespace-symbol semantic-list opt-initializers | |
817 | | COMA namespace-symbol semantic-list opt-initializers | |
818 | | ;;EMPTY | |
819 | ; | |
820 | ||
821 | opt-post-fcn-modifiers | |
822 | : post-fcn-modifiers opt-post-fcn-modifiers | |
823 | ( ,(cons ,$1 $2) ) | |
824 | | ;;EMPTY | |
825 | ( nil ) | |
826 | ; | |
827 | ||
828 | post-fcn-modifiers | |
829 | : REENTRANT | |
830 | | CONST | |
831 | ; | |
832 | ||
833 | opt-throw | |
834 | : THROW semantic-list | |
835 | ( EXPAND $2 throw-exception-list ) | |
836 | | ;;EMPTY | |
837 | ; | |
838 | ||
839 | ;; Is this true? I don't actually know. | |
840 | throw-exception-list | |
841 | : namespace-symbol COMA throw-exception-list | |
842 | ( ,(cons (car $1) $3) ) | |
843 | | namespace-symbol RPAREN | |
844 | ( ,$1 ) | |
845 | | symbol RPAREN | |
846 | ( $1 ) | |
847 | | LPAREN throw-exception-list | |
848 | ( ,$2 ) | |
849 | | RPAREN | |
850 | ( ) | |
851 | ; | |
852 | ||
853 | opt-bits | |
854 | : COLON number | |
855 | ( $2 ) | |
856 | | ;;EMPTY | |
857 | ( nil ) | |
858 | ; | |
859 | ||
860 | opt-array | |
861 | : BRACK_BLCK opt-array | |
862 | ;; Eventually we want to replace the 1 below with a size | |
863 | ;; (if available) | |
864 | ( (cons 1 (car ,$2) ) ) | |
865 | | ;;EMPTY | |
866 | ( nil ) | |
867 | ; | |
868 | ||
869 | opt-assign | |
870 | : EQUAL expression | |
871 | ( $2 ) | |
872 | | ;;EMPTY | |
873 | ( nil ) | |
874 | ; | |
875 | ||
876 | opt-restrict | |
877 | : RESTRICT | |
878 | | ;;EMPTY | |
879 | ; | |
880 | ||
881 | ;; Klaus Berndl: symbol -> namespace-symbol?! I think so. Can be that | |
882 | ;; then also some invalid C++-syntax is parsed but this is better than | |
883 | ;; not parsing valid syntax. | |
884 | varname | |
885 | : opt-stars opt-restrict namespace-symbol opt-bits opt-array | |
886 | ( ,$3 ,$1 ,$4 ,$5 ) | |
887 | ; | |
888 | ||
889 | ;; I should store more in this def, but leave it simple for now. | |
890 | ;; Klaus Berndl: const and volatile can be written after the type! | |
891 | variablearg | |
892 | : declmods typeformbase cv-declmods opt-ref variablearg-opt-name | |
893 | ( VARIABLE-TAG (list $5) $2 nil | |
894 | :constant-flag (if (member "const" (append $1 $3)) t nil) | |
895 | :typemodifiers (delete "const" (append $1 $3)) | |
896 | :reference (car ,$4) | |
897 | ) | |
898 | ; | |
899 | ||
900 | variablearg-opt-name | |
901 | : varname | |
902 | ( ,$1 ) | |
903 | ;; Klaus Berndl: This allows variableargs without a arg-name being | |
904 | ;; parsed correct even if there several pointers (*) | |
905 | | opt-stars | |
906 | ( "" ,$1 nil nil nil ) | |
907 | ; | |
908 | ||
909 | varname-opt-initializer | |
910 | : semantic-list | |
911 | | opt-assign | |
912 | | ;; EMPTY | |
913 | ; | |
914 | ||
915 | varnamelist | |
916 | : opt-ref varname varname-opt-initializer COMA varnamelist | |
917 | ( ,(cons $2 $5) ) | |
918 | | opt-ref varname varname-opt-initializer | |
919 | ( $2 ) | |
920 | ; | |
921 | ||
922 | ;; Klaus Berndl: Is necessary to parse stuff like | |
923 | ;; class list_of_facts : public list<fact>, public entity | |
924 | ;; and | |
925 | ;; list <shared_ptr<item> >::const_iterator l; | |
926 | ;; Parses also invalid(?) and senseless(?) c++-syntax like | |
927 | ;; symbol<template-spec>::symbol1<template-spec1>::test_iterator | |
928 | ;; but better parsing too much than to less | |
929 | namespace-symbol | |
930 | : symbol opt-template-specifier COLON COLON namespace-symbol | |
931 | ( (concat $1 "::" (car $5)) ) | |
932 | | symbol opt-template-specifier | |
933 | ( $1 ) | |
934 | ; | |
935 | ||
936 | ;; Don't pull an optional template specifier at the end of the | |
937 | ;; namespace symbol so that it can be picked up by the type. | |
938 | namespace-symbol-for-typeformbase | |
939 | : symbol opt-template-specifier COLON COLON namespace-symbol-for-typeformbase | |
940 | ( (concat $1 "::" (car $5)) ) | |
941 | | symbol | |
942 | ( $1 ) | |
943 | ; | |
944 | ;; namespace-symbol | |
945 | ;; : symbol COLON COLON namespace-symbol | |
946 | ;; ( (concat $1 "::" (car $4)) ) | |
947 | ;; | symbol | |
948 | ;; ( $1 ) | |
949 | ;; ; | |
950 | ||
951 | namespace-opt-class | |
952 | : symbol COLON COLON namespace-opt-class | |
953 | ( (concat $1 "::" (car $4)) ) | |
954 | ;; Klaus Berndl: We must recognize template-specifiers here so we can | |
955 | ;; parse correctly the method-implementations of template-classes | |
956 | ;; outside the template-class-declaration Example: | |
957 | ;; TemplateClass1<T>::method_1(...) | |
958 | | symbol opt-template-specifier COLON COLON | |
959 | ( $1 ) | |
960 | ; | |
961 | ||
962 | ;; Klaus Berndl: The opt-class of a func-decl must be able to | |
963 | ;; recognize opt-classes with namespaces, e.g. | |
964 | ;; Test1::Test2::classname:: | |
965 | opt-class | |
966 | : namespace-opt-class | |
967 | ( ,$1 ) | |
968 | | ;;EMPTY | |
969 | ( nil ) | |
970 | ; | |
971 | ||
972 | opt-destructor | |
973 | : TILDE | |
974 | ( t ) | |
975 | | ;;EMPTY | |
976 | ( nil ) | |
977 | ; | |
978 | ||
979 | arg-list | |
980 | : PAREN_BLCK knr-arguments | |
981 | ( ,$2 ) | |
982 | | PAREN_BLCK | |
983 | (EXPANDFULL $1 arg-sub-list) | |
984 | | VOID_BLCK | |
985 | ( ) | |
986 | ; | |
987 | ||
988 | knr-varnamelist | |
989 | : varname COMA knr-varnamelist | |
990 | ( ,(cons $1 $3) ) | |
991 | | varname | |
992 | ( $1 ) | |
993 | ; | |
994 | ||
995 | ||
996 | knr-one-variable-decl | |
997 | : declmods typeformbase cv-declmods knr-varnamelist | |
998 | ( VARIABLE-TAG (nreverse $4) $2 nil | |
999 | :constant-flag (if (member "const" (append $3)) t nil) | |
1000 | :typemodifiers (delete "const" $3) | |
1001 | ) | |
1002 | ; | |
1003 | ||
1004 | knr-arguments | |
1005 | : knr-one-variable-decl SEMICOLON knr-arguments | |
1006 | ( ,(append (semantic-expand-c-tag ,$1) ,$3) ) | |
1007 | | knr-one-variable-decl SEMICOLON | |
1008 | ( ,(semantic-expand-c-tag ,$1) ) | |
1009 | ; | |
1010 | ||
1011 | arg-sub-list | |
1012 | : variablearg | |
1013 | ( ,$1 ) | |
1014 | | PERIOD PERIOD PERIOD RPAREN | |
1015 | (VARIABLE-TAG "..." "vararg" nil) | |
1016 | | COMA | |
1017 | ( nil ) | |
1018 | | LPAREN | |
1019 | ( nil ) | |
1020 | | RPAREN | |
1021 | ( nil ) | |
1022 | ; | |
1023 | ||
1024 | operatorsym | |
1025 | : LESS LESS EQUAL | |
1026 | ( "<<=" ) | |
1027 | | GREATER GREATER EQUAL | |
1028 | ( ">>=" ) | |
1029 | | LESS LESS | |
1030 | ( "<<" ) | |
1031 | | GREATER GREATER | |
1032 | ( ">>" ) | |
1033 | | EQUAL EQUAL | |
1034 | ( "==" ) | |
1035 | | LESS EQUAL | |
1036 | ( "<=" ) | |
1037 | | GREATER EQUAL | |
1038 | ( ">=" ) | |
1039 | | BANG EQUAL | |
1040 | ( "!=" ) | |
1041 | | PLUS EQUAL | |
1042 | ( "+=" ) | |
1043 | | MINUS EQUAL | |
1044 | ( "-=" ) | |
1045 | | STAR EQUAL | |
1046 | ( "*=" ) | |
1047 | | DIVIDE EQUAL | |
1048 | ( "/=" ) | |
1049 | | MOD EQUAL | |
1050 | ( "%=" ) | |
1051 | | AMPERSAND EQUAL | |
1052 | ( "&=" ) | |
1053 | | OR EQUAL | |
1054 | ( "|=" ) | |
1055 | | MINUS GREATER STAR | |
1056 | ( "->*" ) | |
1057 | | MINUS GREATER | |
1058 | ( "->" ) | |
1059 | | PARENS | |
1060 | ( "()" ) | |
1061 | | BRACKETS | |
1062 | ( "[]" ) | |
1063 | | LESS | |
1064 | | GREATER | |
1065 | | STAR | |
1066 | | PLUS PLUS | |
1067 | ( "++" ) | |
1068 | | PLUS | |
1069 | | MINUS MINUS | |
1070 | ( "--" ) | |
1071 | | MINUS | |
1072 | | AMPERSAND AMPERSAND | |
1073 | ( "&&" ) | |
1074 | | AMPERSAND | |
1075 | | OR OR | |
1076 | ( "||" ) | |
1077 | | OR | |
1078 | | DIVIDE | |
1079 | | EQUAL | |
1080 | | BANG | |
1081 | | TILDE | |
1082 | | MOD | |
1083 | | COMA | |
1084 | ;; HAT EQUAL seems to have a really unpleasant result and | |
1085 | ;; breaks everything after it. Leave it at the end, though it | |
1086 | ;; doesn't seem to work. | |
1087 | | HAT EQUAL | |
1088 | ( "^=" ) | |
1089 | | HAT | |
1090 | ; | |
1091 | ||
1092 | functionname | |
1093 | : OPERATOR operatorsym | |
1094 | ( ,$2 ) | |
1095 | | semantic-list | |
1096 | ( EXPAND $1 function-pointer ) | |
1097 | | symbol | |
1098 | ( $1 ) | |
1099 | ; | |
1100 | ||
1101 | function-pointer | |
1102 | : LPAREN STAR symbol RPAREN | |
1103 | ( (concat "*" $3) ) | |
1104 | ; | |
1105 | ||
1106 | fun-or-proto-end | |
1107 | : SEMICOLON | |
1108 | ( t ) | |
1109 | | semantic-list | |
1110 | ( nil ) | |
1111 | ;; Here is an anoying feature of C++ pure virtual methods | |
1112 | | EQUAL ZERO SEMICOLON | |
1113 | ( :pure-virtual-flag ) | |
1114 | | fun-try-end | |
1115 | ( nil ) | |
1116 | ; | |
1117 | ||
1118 | fun-try-end | |
1119 | : TRY opt-initializers BRACE_BLCK fun-try-several-catches | |
1120 | ( nil ) | |
1121 | ; | |
1122 | ||
1123 | fun-try-several-catches | |
1124 | : CATCH PAREN_BLCK BRACE_BLCK fun-try-several-catches | |
1125 | ( ) | |
1126 | | CATCH BRACE_BLCK fun-try-several-catches | |
1127 | ( ) | |
1128 | | ;; EMPTY | |
1129 | ( ) | |
1130 | ; | |
1131 | ||
1132 | type-cast | |
1133 | : semantic-list | |
1134 | ( EXPAND $1 type-cast-list ) | |
1135 | ; | |
1136 | ||
1137 | type-cast-list | |
1138 | : open-paren typeformbase close-paren | |
1139 | ; | |
1140 | ||
1141 | opt-stuff-after-symbol | |
1142 | : PAREN_BLCK | |
1143 | | BRACK_BLCK | |
1144 | | ;; EMPTY | |
1145 | ; | |
1146 | ||
1147 | multi-stage-dereference | |
1148 | : namespace-symbol opt-stuff-after-symbol PERIOD multi-stage-dereference ;; method call | |
1149 | | namespace-symbol opt-stuff-after-symbol MINUS GREATER multi-stage-dereference ;;method call | |
1150 | | namespace-symbol opt-stuff-after-symbol | |
1151 | ; | |
1152 | ||
1153 | string-seq | |
1154 | : string string-seq | |
1155 | ( (concat $1 (car $2)) ) | |
1156 | | string | |
1157 | ( $1 ) | |
1158 | ; | |
1159 | ||
1160 | expr-start | |
1161 | : MINUS | |
1162 | | PLUS | |
1163 | | STAR | |
1164 | | AMPERSAND | |
1165 | ; | |
1166 | ||
1167 | expr-binop | |
1168 | : MINUS | |
1169 | | PLUS | |
1170 | | STAR | |
1171 | | DIVIDE | |
1172 | | AMPERSAND AMPERSAND | |
1173 | | AMPERSAND | |
1174 | | OR OR | |
1175 | | OR | |
1176 | ;; There are more. | |
1177 | ; | |
1178 | ||
1179 | ;; Use expression for parsing only. Don't actually return anything | |
1180 | ;; for now. Hopefully we can fix this later. | |
1181 | expression | |
1182 | : unaryexpression expr-binop unaryexpression | |
1183 | ( (identity start) (identity end) ) | |
1184 | | unaryexpression | |
1185 | ( (identity start) (identity end) ) | |
1186 | ; | |
1187 | ||
1188 | unaryexpression | |
1189 | : number | |
1190 | | multi-stage-dereference | |
1191 | | NEW multi-stage-dereference | |
1192 | | NEW builtintype-types semantic-list | |
1193 | ;; Klaus Berndl: symbol -> namespace-symbol! | |
1194 | | namespace-symbol | |
1195 | ;; Klaus Berndl: C/C++ allows sequences of strings which are | |
1196 | ;; concatenated by the precompiler to one string | |
1197 | | string-seq | |
1198 | | type-cast expression ;; A cast to some other type | |
1199 | ;; Casting the results of one expression to something else. | |
1200 | | semantic-list expression | |
1201 | | semantic-list | |
1202 | | expr-start expression | |
1203 | ; | |
1204 | ||
1205 | ;;; semantic/bovine/c.by ends here |