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