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