1237 lines
30 KiB
Plaintext
1237 lines
30 KiB
Plaintext
;;; c.by -- LL grammar for C/C++ language specification
|
|
;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
|
|
;;
|
|
;; Author: Eric M. Ludlam <zappo@gnu.org>
|
|
;; David Ponce <david@dponce.com>
|
|
;; Klaus Berndl <klaus.berndl@sdm.de>
|
|
;;
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;; TODO: From Nate Schley
|
|
;; > * Can't parse signature element: "const char* const rmc_ClrTxt"
|
|
;; > * Can't parse signature element: "char* const dellog_ClrTxt"
|
|
;; > * Can't parse signature element: "const char* dellog_SetTxt"
|
|
;; > * Can't parse signature element: "const RmcCmdSSPADetailedStatus& status"
|
|
;; >
|
|
;; > And FWIW I have seen the following argument cases not handled, even
|
|
;; > with no leading/trailing spaces in the split:
|
|
;; >
|
|
;; > * Can't parse signature element: "const bool currentAlarmStatus"
|
|
;; > * Can't parse signature element: "unsigned char mode"
|
|
;; > * Can't parse signature element: "TskTimingTask* tsktimingtask"
|
|
;; > * Can't parse signature element: "unsigned char htrStatus"
|
|
;; > * Can't parse signature element: "char trackPower[]"
|
|
;; > * Can't parse signature element: "const RmcCmdMCDetailedStatus& status"
|
|
;; > * Can't parse signature element: "RmcBucStatus* rftBucStatus"
|
|
|
|
%package semantic-c-by
|
|
%provide semantic/bovine/c-by
|
|
|
|
%{
|
|
(declare-function semantic-c-reconstitute-token "semantic/bovine/c"
|
|
(tokenpart declmods typedecl))
|
|
(declare-function semantic-c-reconstitute-template "semantic/bovine/c"
|
|
(tag specifier))
|
|
(declare-function semantic-expand-c-tag "semantic/bovine/c" (tag))
|
|
(declare-function semantic-parse-region "semantic"
|
|
(start end &optional nonterminal depth returnonerror))
|
|
}
|
|
|
|
%languagemode c-mode c++-mode
|
|
%start declaration
|
|
%scopestart codeblock
|
|
|
|
%token <punctuation> HASH "\\`[#]\\'"
|
|
%token <punctuation> PERIOD "\\`[.]\\'"
|
|
%token <punctuation> COLON "\\`[:]\\'"
|
|
%token <punctuation> SEMICOLON "\\`[;]\\'"
|
|
%token <punctuation> STAR "\\`[*]\\'"
|
|
%token <punctuation> AMPERSAND "\\`[&]\\'"
|
|
%token <punctuation> DIVIDE "\\`[/]\\'"
|
|
%token <punctuation> PLUS "\\`[+]\\'"
|
|
%token <punctuation> MINUS "\\`[-]\\'"
|
|
%token <punctuation> BANG "\\`[!]\\'"
|
|
%token <punctuation> QUESTION "\\`[?]\\'"
|
|
%token <punctuation> EQUAL "\\`[=]\\'"
|
|
%token <punctuation> LESS "\\`[<]\\'"
|
|
%token <punctuation> GREATER "\\`[>]\\'"
|
|
%token <punctuation> COMA "\\`[,]\\'"
|
|
%token <punctuation> TILDE "\\`[~]\\'"
|
|
%token <punctuation> MOD "\\`[%]\\'"
|
|
%token <punctuation> HAT "\\`\\^\\'"
|
|
%token <punctuation> OR "\\`[|]\\'"
|
|
%token <string> C "\"C\""
|
|
%token <string> CPP "\"C\\+\\+\""
|
|
%token <number> ZERO "^0$"
|
|
%token <symbol> RESTRICT "\\<\\(__\\)?restrict\\>"
|
|
%token <open-paren> LPAREN "("
|
|
%token <close-paren> RPAREN ")"
|
|
%token <open-paren> LBRACE "{"
|
|
%token <close-paren> RBRACE "}"
|
|
%token <semantic-list> BRACK_BLCK "\\[.*\\]$"
|
|
%token <semantic-list> PAREN_BLCK "^("
|
|
%token <semantic-list> BRACE_BLCK "^{"
|
|
%token <semantic-list> VOID_BLCK "^(void)$"
|
|
%token <semantic-list> PARENS "()"
|
|
%token <semantic-list> BRACKETS "\\[\\]"
|
|
|
|
%token EXTERN "extern"
|
|
%put EXTERN summary "Declaration Modifier: extern <type> <name> ..."
|
|
%token STATIC "static"
|
|
%put STATIC summary "Declaration Modifier: static <type> <name> ..."
|
|
%token CONST "const"
|
|
%put CONST summary "Declaration Modifier: const <type> <name> ..."
|
|
%token VOLATILE "volatile"
|
|
%put VOLATILE summary "Declaration Modifier: volatile <type> <name> ..."
|
|
%token REGISTER "register"
|
|
%put REGISTER summary "Declaration Modifier: register <type> <name> ..."
|
|
%token SIGNED "signed"
|
|
%put SIGNED summary "Numeric Type Modifier: signed <numeric type> <name> ..."
|
|
%token UNSIGNED "unsigned"
|
|
%put UNSIGNED summary "Numeric Type Modifier: unsigned <numeric type> <name> ..."
|
|
|
|
%token INLINE "inline"
|
|
%put INLINE summary "Function Modifier: inline <return type> <name>(...) {...};"
|
|
%token VIRTUAL "virtual"
|
|
%put VIRTUAL summary "Method Modifier: virtual <type> <name>(...) ..."
|
|
%token MUTABLE "mutable"
|
|
%put MUTABLE summary "Member Declaration Modifier: mutable <type> <name> ..."
|
|
%token EXPLICIT "explicit"
|
|
%put EXPLICIT summary "Forbids implicit type conversion: explicit <constructor>"
|
|
|
|
%token STRUCT "struct"
|
|
%put STRUCT summary "Structure Type Declaration: struct [name] { ... };"
|
|
%token UNION "union"
|
|
%put UNION summary "Union Type Declaration: union [name] { ... };"
|
|
%token ENUM "enum"
|
|
%put ENUM summary "Enumeration Type Declaration: enum [name] { ... };"
|
|
%token TYPEDEF "typedef"
|
|
%put TYPEDEF summary "Arbitrary Type Declaration: typedef <typedeclaration> <name>;"
|
|
%token CLASS "class"
|
|
%put CLASS summary "Class Declaration: class <name>[:parents] { ... };"
|
|
%token TYPENAME "typename"
|
|
%put TYPENAME summary "typename is used to handle a qualified name as a typename;"
|
|
%token NAMESPACE "namespace"
|
|
%put NAMESPACE summary "Namespace Declaration: namespace <name> { ... };"
|
|
%token USING "using"
|
|
%put USING summary "using <namespace>;"
|
|
|
|
%token NEW "new"
|
|
%put NEW summary "new <classname>();"
|
|
%token DELETE "delete"
|
|
%put DELETE summary "delete <object>;"
|
|
|
|
;; Despite this, this parser can find templates by ignoring the TEMPLATE
|
|
;; keyword, and finding the class/method being templatized.
|
|
%token TEMPLATE "template"
|
|
%put TEMPLATE summary "template <class TYPE ...> TYPE_OR_FUNCTION"
|
|
|
|
%token THROW "throw"
|
|
%put THROW summary "<type> <methoddef> (<method args>) throw (<exception>) ..."
|
|
%token REENTRANT "reentrant"
|
|
%put REENTRANT summary "<type> <methoddef> (<method args>) reentrant ..."
|
|
%token TRY "try"
|
|
%token CATCH "catch"
|
|
%put { TRY CATCH } summary "try { <body> } catch { <catch code> }"
|
|
|
|
;; Leave these alone for now.
|
|
%token OPERATOR "operator"
|
|
%token PUBLIC "public"
|
|
%token PRIVATE "private"
|
|
%token PROTECTED "protected"
|
|
%token FRIEND "friend"
|
|
%put FRIEND summary "friend class <CLASSNAME>"
|
|
|
|
;; These aren't used for parsing, but is a useful place to describe the keywords.
|
|
%token IF "if"
|
|
%token ELSE "else"
|
|
%put {IF ELSE} summary "if (<condition>) { code } [ else { code } ]"
|
|
|
|
%token DO "do"
|
|
%token WHILE "while"
|
|
%put DO summary " do { code } while (<condition>);"
|
|
%put WHILE summary "do { code } while (<condition>); or while (<condition>) { code };"
|
|
|
|
%token FOR "for"
|
|
%put FOR summary "for(<init>; <condition>; <increment>) { code }"
|
|
|
|
%token SWITCH "switch"
|
|
%token CASE "case"
|
|
%token DEFAULT "default"
|
|
%put {SWITCH CASE DEFAULT} summary
|
|
"switch (<variable>) { case <constvalue>: code; ... default: code; }"
|
|
|
|
%token RETURN "return"
|
|
%put RETURN summary "return <value>;"
|
|
|
|
%token BREAK "break"
|
|
%put BREAK summary "Non-local exit within a loop or switch (for, do/while, switch): break;"
|
|
%token CONTINUE "continue"
|
|
%put CONTINUE summary "Non-local continue within a loop (for, do/while): continue;"
|
|
|
|
%token SIZEOF "sizeof"
|
|
%put SIZEOF summary "Compile time macro: sizeof(<type or variable>) // size in bytes"
|
|
|
|
;; Types
|
|
%token VOID "void"
|
|
%put VOID summary "Built in type: void"
|
|
%token CHAR "char"
|
|
%put CHAR summary "Integral Character Type: (0 to 256)"
|
|
%token WCHAR "wchar_t"
|
|
%put WCHAR summary "Wide Character Type"
|
|
%token SHORT "short"
|
|
%put SHORT summary "Integral Primitive Type: (-32768 to 32767)"
|
|
%token INT "int"
|
|
%put INT summary "Integral Primitive Type: (-2147483648 to 2147483647)"
|
|
%token LONG "long"
|
|
%put LONG summary "Integral primitive type (-9223372036854775808 to 9223372036854775807)"
|
|
%token FLOAT "float"
|
|
%put FLOAT summary "Primitive floating-point type (single-precision 32-bit IEEE 754)"
|
|
%token DOUBLE "double"
|
|
%put DOUBLE summary "Primitive floating-point type (double-precision 64-bit IEEE 754)"
|
|
%token BOOL "bool"
|
|
%put BOOL summary "Primitive boolean type"
|
|
|
|
%token UNDERP "_P"
|
|
%token UNDERUNDERP "__P"
|
|
%put UNDERP summary "Common macro to eliminate prototype compatibility on some compilers"
|
|
%put UNDERUNDERP summary "Common macro to eliminate prototype compatibility on some compilers"
|
|
|
|
%%
|
|
|
|
declaration
|
|
: macro
|
|
| type
|
|
;; TODO: Klaus Berndl: Is the define here necessary or even wrong?
|
|
;; Is this part not already covered by macro??
|
|
| define
|
|
| var-or-fun
|
|
| extern-c
|
|
| template
|
|
| using
|
|
;
|
|
|
|
codeblock
|
|
: define
|
|
| codeblock-var-or-fun
|
|
| type ;; type is less likely to be used here.
|
|
| using
|
|
;
|
|
|
|
extern-c-contents
|
|
: open-paren
|
|
( nil )
|
|
| declaration
|
|
| close-paren
|
|
( nil )
|
|
;
|
|
|
|
extern-c
|
|
: EXTERN C semantic-list
|
|
;; Extern C commands which contain a list need to have the
|
|
;; entries of the list extracted, and spliced into the main
|
|
;; list of entries. This must be done via the function
|
|
;; that expands singular nonterminals, such as int x,y;
|
|
(TAG "C" 'extern :members (EXPANDFULL $3 extern-c-contents) )
|
|
| EXTERN CPP semantic-list
|
|
(TAG "C" 'extern :members (EXPANDFULL $3 extern-c-contents) )
|
|
| EXTERN C
|
|
;; A plain extern "C" call should add something to the token,
|
|
;; but just strip it from the buffer here for now.
|
|
( nil )
|
|
| EXTERN CPP
|
|
( nil )
|
|
;
|
|
|
|
macro
|
|
: spp-macro-def
|
|
(VARIABLE-TAG $1 nil nil :constant-flag t )
|
|
| spp-system-include
|
|
(INCLUDE-TAG $1 t)
|
|
| spp-include
|
|
(INCLUDE-TAG $1 nil)
|
|
;
|
|
|
|
;; This is used in struct parts.
|
|
define
|
|
: spp-macro-def
|
|
(VARIABLE-TAG $1 nil nil :constant-flag t)
|
|
| spp-macro-undef
|
|
( nil )
|
|
;
|
|
|
|
;; In C++, structures can have the same things as classes.
|
|
;; So delete this some day in the figure.
|
|
;;
|
|
;;structparts : semantic-list
|
|
;; (EXPANDFULL $1 structsubparts)
|
|
;; ;
|
|
;;
|
|
;;structsubparts : LBRACE
|
|
;; ( nil )
|
|
;; | RBRACE
|
|
;; ( nil )
|
|
;; | var-or-fun
|
|
;; | define
|
|
;; ;; sometimes there are defines in structs.
|
|
;; ;
|
|
|
|
unionparts
|
|
: semantic-list
|
|
(EXPANDFULL $1 classsubparts)
|
|
;
|
|
|
|
opt-symbol
|
|
: symbol
|
|
| ;;EMPTY
|
|
;
|
|
|
|
;; @todo - support 'friend' construct.
|
|
classsubparts
|
|
: LBRACE
|
|
( nil )
|
|
| RBRACE
|
|
( nil )
|
|
| class-protection opt-symbol COLON
|
|
;; For QT, they may put a `slot' keyword between the protection
|
|
;; and the COLON. @todo - Have the QT stuff use macros.
|
|
(TAG (car $1) 'label)
|
|
| var-or-fun
|
|
| FRIEND func-decl
|
|
(TAG (car $2) 'friend)
|
|
| FRIEND CLASS symbol
|
|
(TAG $3 'friend)
|
|
| type
|
|
| define
|
|
| template
|
|
| ;;EMPTY
|
|
;
|
|
|
|
opt-class-parents
|
|
: COLON class-parents opt-template-specifier
|
|
( $2 )
|
|
| ;;EMPTY
|
|
( )
|
|
;
|
|
|
|
one-class-parent
|
|
: opt-class-protection opt-class-declmods namespace-symbol
|
|
(TYPE-TAG (car $3) "class" nil nil :protection (car $1))
|
|
| opt-class-declmods opt-class-protection namespace-symbol
|
|
(TYPE-TAG (car $3) "class" nil nil :protection (car $2))
|
|
;
|
|
|
|
class-parents
|
|
: one-class-parent COMA class-parents
|
|
( ,(cons ,$1 $3 ) )
|
|
| one-class-parent
|
|
( $1 )
|
|
;
|
|
|
|
opt-class-declmods
|
|
: class-declmods opt-class-declmods
|
|
( nil )
|
|
| ;;EMPTY
|
|
;
|
|
|
|
class-declmods
|
|
: VIRTUAL
|
|
;
|
|
|
|
class-protection
|
|
: PUBLIC
|
|
| PRIVATE
|
|
| PROTECTED
|
|
;
|
|
|
|
opt-class-protection
|
|
: class-protection
|
|
( ,$1 )
|
|
| ;;EMPTY - Same as private
|
|
( "unspecified" )
|
|
;
|
|
|
|
namespaceparts
|
|
: semantic-list
|
|
(EXPANDFULL $1 namespacesubparts)
|
|
;
|
|
|
|
namespacesubparts
|
|
: LBRACE
|
|
( nil )
|
|
| RBRACE
|
|
( nil )
|
|
| type
|
|
| var-or-fun
|
|
| define
|
|
| class-protection COLON
|
|
(TAG (car $1) 'label)
|
|
;; In C++, this label in a classsubpart represents
|
|
;; PUBLIC or PRIVATE bits. Ignore them for now.
|
|
| template
|
|
| using
|
|
;; Includes inside namespaces
|
|
| spp-include
|
|
(TAG $1 'include :inside-ns t)
|
|
| ;;EMPTY
|
|
;
|
|
|
|
enumparts
|
|
: semantic-list
|
|
(EXPANDFULL $1 enumsubparts)
|
|
;
|
|
|
|
enumsubparts
|
|
: symbol opt-assign
|
|
(VARIABLE-TAG $1 "int" (car $2) :constant-flag t )
|
|
| LBRACE
|
|
( nil )
|
|
| RBRACE
|
|
( nil )
|
|
| COMA
|
|
( nil )
|
|
;
|
|
|
|
opt-name
|
|
: symbol
|
|
| ;;EMPTY
|
|
( "" )
|
|
;
|
|
|
|
typesimple
|
|
: struct-or-class opt-class opt-name opt-template-specifier
|
|
opt-class-parents semantic-list
|
|
(TYPE-TAG (car $3) (car $1)
|
|
(dlet ((semantic-c-classname (cons (car ,$3) (car ,$1))))
|
|
(EXPANDFULL $6 classsubparts))
|
|
$5
|
|
:template-specifier $4
|
|
:parent (car ,$2))
|
|
| struct-or-class opt-class opt-name opt-template-specifier
|
|
opt-class-parents
|
|
(TYPE-TAG (car $3) (car $1) nil $5
|
|
:template-specifier $4
|
|
:prototype t
|
|
:parent (car ,$2))
|
|
| UNION opt-class opt-name unionparts
|
|
(TYPE-TAG (car $3) $1 $4 nil
|
|
:parent (car ,$2))
|
|
| ENUM opt-class opt-name enumparts
|
|
(TYPE-TAG (car $3) $1 $4 nil
|
|
:parent (car ,$2))
|
|
;; Klaus Berndl: a typedef can be a typeformbase with all this
|
|
;; declmods stuff.
|
|
| TYPEDEF declmods typeformbase cv-declmods typedef-symbol-list
|
|
;;;; We put the type this typedef renames into PARENT
|
|
;;;; but will move it in the expand function.
|
|
(TYPE-TAG $5 $1 nil (list $3) )
|
|
;
|
|
|
|
typedef-symbol-list
|
|
: typedefname COMA typedef-symbol-list
|
|
( ,(cons $1 $3) )
|
|
| typedefname
|
|
( $1 )
|
|
;
|
|
|
|
;; TODO: Klaus Berndl: symbol -> namespace-symbol?! Answer: Probably
|
|
;; symbol is correct here!
|
|
typedefname
|
|
: opt-stars symbol opt-bits opt-array
|
|
( $1 $2 )
|
|
;
|
|
|
|
struct-or-class
|
|
: STRUCT
|
|
| CLASS
|
|
;
|
|
|
|
type
|
|
: typesimple SEMICOLON
|
|
( ,$1 )
|
|
;; named namespaces like "namespace XXX {"
|
|
| NAMESPACE symbol namespaceparts
|
|
(TYPE-TAG $2 $1 $3 nil )
|
|
;; unnamed namespaces like "namespace {"
|
|
| NAMESPACE namespaceparts
|
|
(TYPE-TAG "unnamed" $1 $2 nil )
|
|
;; David Engster: namespace alias like "namespace foo = bar;"
|
|
| NAMESPACE symbol EQUAL typeformbase SEMICOLON
|
|
(TYPE-TAG $2 $1 (list (TYPE-TAG (car $4) $1 nil nil)) nil :kind 'alias )
|
|
;
|
|
|
|
;; Klaus Berndl: We must parse "using namespace XXX" too
|
|
|
|
;; Using is vaguely like an include statement in the named portions
|
|
;; of the code. We should probably specify a new token type for this.
|
|
|
|
using
|
|
: USING usingname SEMICOLON
|
|
(TAG (car $2) 'using :type ,$2 )
|
|
;
|
|
|
|
;; Jan Moringen: Differentiate between 'using' and 'using namespace'
|
|
;; Adapted to creating type tags by EML.
|
|
usingname
|
|
: typeformbase
|
|
(TYPE-TAG (car $1) "class" nil nil :prototype t)
|
|
| NAMESPACE typeformbase
|
|
(TYPE-TAG (car $2) "namespace" nil nil :prototype t)
|
|
;
|
|
|
|
template
|
|
: TEMPLATE template-specifier opt-friend template-definition
|
|
( ,(semantic-c-reconstitute-template $4 ,$2) )
|
|
;
|
|
|
|
opt-friend
|
|
: FRIEND
|
|
| ;;EMPTY
|
|
;
|
|
|
|
opt-template-specifier
|
|
: template-specifier
|
|
( ,$1 )
|
|
| ;;EMPTY
|
|
( )
|
|
;
|
|
|
|
template-specifier
|
|
: LESS template-specifier-types GREATER
|
|
( ,$2 )
|
|
;
|
|
|
|
template-specifier-types
|
|
: template-var template-specifier-type-list
|
|
( ,(cons ,$1 ,$2 ) )
|
|
| ;;EMPTY
|
|
;
|
|
|
|
template-specifier-type-list
|
|
: COMA template-specifier-types
|
|
( ,$2 )
|
|
| ;;EMPTY
|
|
( )
|
|
;
|
|
|
|
;; template-var
|
|
;; : template-type opt-stars opt-template-equal
|
|
;; ( ,(cons (concat (car $1) (make-string (car ,$2) ?*))
|
|
;; (cdr $1)))
|
|
;; ;; Klaus Berndl: for template-types the template-var can also be
|
|
;; ;; literals or constants. Example: map<ClassX, ClassY, 10>
|
|
;; ;; map_size10_var; This parses also template<class T, 0> which is
|
|
;; ;; nonsense but who cares....
|
|
;; | string
|
|
;; ( $1 )
|
|
;; | number
|
|
;; ( $1 )
|
|
;; ;
|
|
|
|
template-var
|
|
:
|
|
;; Klaus Berndl: The following handles all template-vars of
|
|
;; template-definitions
|
|
template-type opt-template-equal
|
|
( ,(cons (car $1) (cdr $1)) )
|
|
;; Klaus Berndl: for template-types the template-var can also be
|
|
;; literals or constants.
|
|
;; Example: map<ClassX, ClassY, 10> map_size10_var; This parses also
|
|
;; template<class T, 0> which is nonsense but who cares....
|
|
| string
|
|
( $1 )
|
|
| number
|
|
( $1 )
|
|
;; Klaus Berndl: In template-types arguments can be any symbols with
|
|
;; optional address-operator (&) and optional dereferencing operator
|
|
;; (*). Example map<ClassX, ClassY, *size_var_ptr> sized_map_var.
|
|
| opt-stars opt-ref namespace-symbol
|
|
( ,$3 )
|
|
;; Some code can compile down into a number, but starts out as an
|
|
;; expression, such as "sizeof(a)", or (sizeof(a)/sizeof(b))
|
|
| semantic-list
|
|
( $1 )
|
|
| SIZEOF semantic-list
|
|
( $2 )
|
|
;
|
|
|
|
opt-template-equal
|
|
: EQUAL symbol LESS template-specifier-types GREATER
|
|
( $2 )
|
|
| EQUAL symbol
|
|
( $2 )
|
|
| ;;EMPTY
|
|
( )
|
|
;
|
|
|
|
template-type
|
|
: CLASS symbol
|
|
(TYPE-TAG $2 "class" nil nil )
|
|
| STRUCT symbol
|
|
(TYPE-TAG $2 "struct" nil nil )
|
|
;; TODO: Klaus Berndl: For the moment it is ok, that we parse the C++
|
|
;; keyword typename as a class....
|
|
| TYPENAME symbol
|
|
(TYPE-TAG $2 "class" nil nil)
|
|
;; Klaus Berndl: template-types can be all flavors of variable-args
|
|
;; but here the argument is ignored, only the type stuff is needed.
|
|
| declmods typeformbase cv-declmods opt-stars
|
|
opt-ref variablearg-opt-name
|
|
(TYPE-TAG (car $2) nil nil nil
|
|
:template-specifier (plist-get (nth 2 $2) :template-specifier)
|
|
:constant-flag (if (member "const" (append $1 $3)) t nil)
|
|
:typemodifiers (delete "const" (append $1 $3))
|
|
:reference (car ,$5)
|
|
:pointer (car $4)
|
|
:typevar (car $6)
|
|
)
|
|
;
|
|
|
|
template-definition
|
|
: type
|
|
( ,$1 )
|
|
| var-or-fun
|
|
( ,$1 )
|
|
;
|
|
|
|
opt-stars
|
|
: STAR opt-starmod opt-stars
|
|
( (1+ (car $3)) )
|
|
| ;;EMPTY
|
|
( 0 )
|
|
;
|
|
|
|
opt-starmod
|
|
: STARMOD opt-starmod
|
|
( ,(cons (,car ,$1) $2) )
|
|
| ;;EMPTY
|
|
()
|
|
;
|
|
|
|
STARMOD
|
|
: CONST
|
|
;
|
|
|
|
declmods
|
|
: DECLMOD declmods
|
|
( ,(cons ,(car ,$1) $2 ) )
|
|
| DECLMOD
|
|
( ,$1 )
|
|
| ;;EMPTY
|
|
()
|
|
;
|
|
|
|
DECLMOD
|
|
: EXTERN
|
|
| STATIC
|
|
| CVDECLMOD
|
|
;; Klaus Berndl: IMHO signed and unsigned are not decl-modes but
|
|
;; these are only valid for some buildin-types like short, int
|
|
;; etc... whereas "real" declmods are valid for all types, buildin
|
|
;; and user-defined! SIGNED UNSIGNED
|
|
| INLINE
|
|
| REGISTER
|
|
| FRIEND
|
|
;; Klaus Berndl: There can be a few cases where TYPENAME is not
|
|
;; allowed in C++-syntax but better than not recognizing the allowed
|
|
;; situations.
|
|
| TYPENAME
|
|
| METADECLMOD
|
|
;; This is a hack in case we are in a class.
|
|
| VIRTUAL
|
|
;
|
|
|
|
metadeclmod
|
|
: METADECLMOD
|
|
()
|
|
| ;;EMPTY
|
|
()
|
|
;
|
|
|
|
CVDECLMOD
|
|
: CONST
|
|
| VOLATILE
|
|
;
|
|
|
|
cv-declmods
|
|
: CVDECLMOD cv-declmods
|
|
( ,(cons ,(car ,$1) $2 ) )
|
|
| CVDECLMOD
|
|
( ,$1 )
|
|
| ;;EMPTY
|
|
()
|
|
;
|
|
|
|
METADECLMOD
|
|
: VIRTUAL
|
|
| MUTABLE
|
|
;
|
|
|
|
;; C++: A type can be modified into a reference by "&"
|
|
opt-ref
|
|
: AMPERSAND
|
|
( 1 )
|
|
| ;;EMPTY
|
|
( 0 )
|
|
;
|
|
|
|
typeformbase
|
|
: typesimple
|
|
( ,$1 )
|
|
| STRUCT symbol
|
|
(TYPE-TAG $2 $1 nil nil )
|
|
| UNION symbol
|
|
(TYPE-TAG $2 $1 nil nil )
|
|
| ENUM symbol
|
|
(TYPE-TAG $2 $1 nil nil )
|
|
| builtintype
|
|
( ,$1 )
|
|
| symbol template-specifier
|
|
(TYPE-TAG $1 "class" nil nil :template-specifier $2)
|
|
;;| namespace-symbol opt-stars opt-template-specifier
|
|
;;| namespace-symbol opt-template-specifier
|
|
| namespace-symbol-for-typeformbase opt-template-specifier
|
|
(TYPE-TAG (car $1) "class" nil nil
|
|
:template-specifier $2)
|
|
| symbol
|
|
( $1 )
|
|
;
|
|
|
|
signedmod
|
|
: UNSIGNED
|
|
| SIGNED
|
|
;
|
|
|
|
;; Klaus Berndl: builtintype-types was builtintype
|
|
builtintype-types
|
|
: VOID
|
|
| CHAR
|
|
;; Klaus Berndl: Added WCHAR
|
|
| WCHAR
|
|
| SHORT INT
|
|
( (concat $1 " " $2) )
|
|
| SHORT
|
|
| INT
|
|
| LONG INT
|
|
( (concat $1 " " $2) )
|
|
| FLOAT
|
|
| DOUBLE
|
|
| BOOL
|
|
| LONG DOUBLE
|
|
( (concat $1 " " $2) )
|
|
;; TODO: Klaus Berndl: Is there a long long, i think so?!
|
|
| LONG LONG
|
|
( (concat $1 " " $2) )
|
|
| LONG
|
|
;
|
|
|
|
builtintype
|
|
: signedmod builtintype-types
|
|
( (concat (car $1) " " (car $2)) )
|
|
| builtintype-types
|
|
( ,$1 )
|
|
;; Klaus Berndl: unsigned is synonym for unsigned int and signed for
|
|
;; signed int. To make this confusing stuff clear we add here the
|
|
;; int.
|
|
| signedmod
|
|
( (concat (car $1) " int") )
|
|
;
|
|
|
|
;; Klaus Berndl: This parses also nonsense like "const volatile int
|
|
;; const volatile const const volatile a ..." but IMHO nobody writes
|
|
;; such code. Normally we should define a rule like typeformbase-mode
|
|
;; which exactly defines the different allowed cases and combinations
|
|
;; of declmods (minus the CVDECLMOD) typeformbase and cv-declmods so
|
|
;; we could recognize more invalid code but IMHO this is not worth the
|
|
;; effort...
|
|
codeblock-var-or-fun
|
|
: declmods typeformbase declmods
|
|
opt-ref var-or-func-decl
|
|
( ,(semantic-c-reconstitute-token ,$5 $1 $2 ) )
|
|
;
|
|
|
|
var-or-fun
|
|
: codeblock-var-or-fun
|
|
( ,$1 )
|
|
;; it is possible for a function to not have a type, and
|
|
;; it is then assumed to be an int. How annoying.
|
|
;; In C++, this could be a constructor or a destructor.
|
|
;; Even more annoying. Only ever do this for regular
|
|
;; top-level items. Ignore this problem in code blocks
|
|
;; so that we don't have to deal with regular code
|
|
;; being erroneously converted into types.
|
|
| declmods var-or-func-decl
|
|
( ,(semantic-c-reconstitute-token ,$2 $1 nil ) )
|
|
;
|
|
|
|
var-or-func-decl
|
|
: func-decl
|
|
( ,$1 )
|
|
| var-decl
|
|
( ,$1 )
|
|
;
|
|
|
|
func-decl
|
|
: opt-stars opt-class opt-destructor functionname
|
|
opt-template-specifier
|
|
opt-under-p
|
|
arg-list
|
|
opt-post-fcn-modifiers
|
|
opt-throw
|
|
opt-initializers
|
|
fun-or-proto-end
|
|
( ,$4 'function
|
|
;; Extra stuff goes in here.
|
|
;; Continue with the stuff we found in
|
|
;; this definition
|
|
$2 $3 $7 $9 $8 ,$1 ,$11 $5 ,$10)
|
|
| opt-stars opt-class opt-destructor functionname
|
|
opt-template-specifier
|
|
opt-under-p
|
|
;; arg-list - - ini this case, a try implies a fcn.
|
|
opt-post-fcn-modifiers
|
|
opt-throw
|
|
opt-initializers
|
|
fun-try-end
|
|
( ,$4 'function
|
|
;; Extra stuff goes in here.
|
|
;; Continue with the stuff we found in
|
|
;; this definition
|
|
$2 $3 nil $8 $7 ,$1 ,$10 $5 ,$9)
|
|
;
|
|
|
|
var-decl
|
|
: varnamelist SEMICOLON
|
|
( $1 'variable )
|
|
;
|
|
|
|
opt-under-p
|
|
: UNDERP
|
|
( nil )
|
|
| UNDERUNDERP
|
|
( nil )
|
|
| ;;EMPTY
|
|
;
|
|
|
|
;; Klaus Berndl: symbol -> namespace-symbol
|
|
opt-initializers
|
|
: COLON namespace-symbol semantic-list opt-initializers
|
|
| COMA namespace-symbol semantic-list opt-initializers
|
|
| ;;EMPTY
|
|
;
|
|
|
|
opt-post-fcn-modifiers
|
|
: post-fcn-modifiers opt-post-fcn-modifiers
|
|
( ,(cons ,(car $1) $2) )
|
|
| ;;EMPTY
|
|
( nil )
|
|
;
|
|
|
|
post-fcn-modifiers
|
|
: REENTRANT
|
|
| CONST
|
|
;
|
|
|
|
opt-throw
|
|
: THROW semantic-list
|
|
( EXPAND $2 throw-exception-list )
|
|
| ;;EMPTY
|
|
;
|
|
|
|
;; Is this true? I don't actually know.
|
|
throw-exception-list
|
|
: namespace-symbol COMA throw-exception-list
|
|
( ,(cons (car $1) $3) )
|
|
| namespace-symbol RPAREN
|
|
( ,$1 )
|
|
| symbol RPAREN
|
|
( $1 )
|
|
| LPAREN throw-exception-list
|
|
( ,$2 )
|
|
| RPAREN
|
|
( )
|
|
;
|
|
|
|
opt-bits
|
|
: COLON number
|
|
( $2 )
|
|
| ;;EMPTY
|
|
( nil )
|
|
;
|
|
|
|
opt-array
|
|
: BRACK_BLCK opt-array
|
|
;; Eventually we want to replace the 1 below with a size
|
|
;; (if available)
|
|
( (cons 1 (car ,$2) ) )
|
|
| ;;EMPTY
|
|
( nil )
|
|
;
|
|
|
|
opt-assign
|
|
: EQUAL expression
|
|
( $2 )
|
|
| ;;EMPTY
|
|
( nil )
|
|
;
|
|
|
|
opt-restrict
|
|
: RESTRICT
|
|
| ;;EMPTY
|
|
;
|
|
|
|
;; Klaus Berndl: symbol -> namespace-symbol?! I think so. Can be that
|
|
;; then also some invalid C++-syntax is parsed but this is better than
|
|
;; not parsing valid syntax.
|
|
varname
|
|
: opt-stars opt-restrict namespace-symbol opt-bits opt-array
|
|
( ,$3 ,$1 ,$4 ,$5 )
|
|
;
|
|
|
|
;; I should store more in this def, but leave it simple for now.
|
|
;; Klaus Berndl: const and volatile can be written after the type!
|
|
variablearg
|
|
: declmods typeformbase cv-declmods opt-ref variablearg-opt-name opt-assign
|
|
( VARIABLE-TAG (list (append $5 ,$6)) $2 nil
|
|
:constant-flag (if (member "const" (append $1 $3)) t nil)
|
|
:typemodifiers (delete "const" (append $1 $3))
|
|
:reference (car ,$4)
|
|
)
|
|
;
|
|
|
|
variablearg-opt-name
|
|
: varname
|
|
( ,$1 )
|
|
| semantic-list arg-list
|
|
( (car ( EXPAND $1 function-pointer )) $2)
|
|
;; Klaus Berndl: This allows variableargs without an arg-name being
|
|
;; parsed correctly even if there several pointers (*)
|
|
| opt-stars
|
|
( "" ,$1 nil nil nil )
|
|
;
|
|
|
|
varname-opt-initializer
|
|
: semantic-list
|
|
| opt-assign
|
|
| ;; EMPTY
|
|
;
|
|
|
|
varnamelist
|
|
: opt-ref varname varname-opt-initializer COMA varnamelist
|
|
( ,(cons (append $2 $3) $5) )
|
|
| opt-ref varname varname-opt-initializer
|
|
( (append $2 $3) )
|
|
;
|
|
|
|
;; Klaus Berndl: Is necessary to parse stuff like
|
|
;; class list_of_facts : public list<fact>, public entity
|
|
;; and
|
|
;; list <shared_ptr<item> >::const_iterator l;
|
|
;; Parses also invalid(?) and senseless(?) c++-syntax like
|
|
;; symbol<template-spec>::symbol1<template-spec1>::test_iterator
|
|
;; but better parsing too much than to less
|
|
namespace-symbol
|
|
: symbol opt-template-specifier COLON COLON namespace-symbol
|
|
( (concat $1 "::" (car $5)) )
|
|
| symbol opt-template-specifier
|
|
( $1 )
|
|
;
|
|
|
|
;; Don't pull an optional template specifier at the end of the
|
|
;; namespace symbol so that it can be picked up by the type.
|
|
namespace-symbol-for-typeformbase
|
|
: symbol opt-template-specifier COLON COLON namespace-symbol-for-typeformbase
|
|
( (concat $1 "::" (car $5)) )
|
|
| symbol
|
|
( $1 )
|
|
;
|
|
;; namespace-symbol
|
|
;; : symbol COLON COLON namespace-symbol
|
|
;; ( (concat $1 "::" (car $4)) )
|
|
;; | symbol
|
|
;; ( $1 )
|
|
;; ;
|
|
|
|
namespace-opt-class
|
|
: symbol COLON COLON namespace-opt-class
|
|
( (concat $1 "::" (car $4)) )
|
|
;; Klaus Berndl: We must recognize template-specifiers here so we can
|
|
;; parse correctly the method-implementations of template-classes
|
|
;; outside the template-class-declaration Example:
|
|
;; TemplateClass1<T>::method_1(...)
|
|
| symbol opt-template-specifier COLON COLON
|
|
( $1 )
|
|
;
|
|
|
|
;; Klaus Berndl: The opt-class of a func-decl must be able to
|
|
;; recognize opt-classes with namespaces, e.g.
|
|
;; Test1::Test2::classname::
|
|
opt-class
|
|
: namespace-opt-class
|
|
( ,$1 )
|
|
| ;;EMPTY
|
|
( nil )
|
|
;
|
|
|
|
opt-destructor
|
|
: TILDE
|
|
( t )
|
|
| ;;EMPTY
|
|
( nil )
|
|
;
|
|
|
|
arg-list
|
|
: PAREN_BLCK knr-arguments
|
|
( ,$2 )
|
|
| PAREN_BLCK
|
|
(EXPANDFULL $1 arg-sub-list)
|
|
| VOID_BLCK
|
|
( )
|
|
;
|
|
|
|
knr-varnamelist
|
|
: varname COMA knr-varnamelist
|
|
( ,(cons $1 $3) )
|
|
| varname
|
|
( $1 )
|
|
;
|
|
|
|
|
|
knr-one-variable-decl
|
|
: declmods typeformbase cv-declmods knr-varnamelist
|
|
( VARIABLE-TAG (nreverse $4) $2 nil
|
|
:constant-flag (if (member "const" (append $3)) t nil)
|
|
:typemodifiers (delete "const" $3)
|
|
)
|
|
;
|
|
|
|
knr-arguments
|
|
: knr-one-variable-decl SEMICOLON knr-arguments
|
|
( ,(append (semantic-expand-c-tag ,$1) ,$3) )
|
|
| knr-one-variable-decl SEMICOLON
|
|
( ,(semantic-expand-c-tag ,$1) )
|
|
;
|
|
|
|
arg-sub-list
|
|
: variablearg
|
|
( ,$1 )
|
|
| PERIOD PERIOD PERIOD RPAREN
|
|
(VARIABLE-TAG "..." "vararg" nil)
|
|
| COMA
|
|
( nil )
|
|
| LPAREN
|
|
( nil )
|
|
| RPAREN
|
|
( nil )
|
|
;
|
|
|
|
operatorsym
|
|
: LESS LESS EQUAL
|
|
( "<<=" )
|
|
| GREATER GREATER EQUAL
|
|
( ">>=" )
|
|
| LESS LESS
|
|
( "<<" )
|
|
| GREATER GREATER
|
|
( ">>" )
|
|
| EQUAL EQUAL
|
|
( "==" )
|
|
| LESS EQUAL
|
|
( "<=" )
|
|
| GREATER EQUAL
|
|
( ">=" )
|
|
| BANG EQUAL
|
|
( "!=" )
|
|
| PLUS EQUAL
|
|
( "+=" )
|
|
| MINUS EQUAL
|
|
( "-=" )
|
|
| STAR EQUAL
|
|
( "*=" )
|
|
| DIVIDE EQUAL
|
|
( "/=" )
|
|
| MOD EQUAL
|
|
( "%=" )
|
|
| AMPERSAND EQUAL
|
|
( "&=" )
|
|
| OR EQUAL
|
|
( "|=" )
|
|
| MINUS GREATER STAR
|
|
( "->*" )
|
|
| MINUS GREATER
|
|
( "->" )
|
|
| PARENS
|
|
( "()" )
|
|
| BRACKETS
|
|
( "[]" )
|
|
| LESS
|
|
| GREATER
|
|
| STAR
|
|
| PLUS PLUS
|
|
( "++" )
|
|
| PLUS
|
|
| MINUS MINUS
|
|
( "--" )
|
|
| MINUS
|
|
| AMPERSAND AMPERSAND
|
|
( "&&" )
|
|
| AMPERSAND
|
|
| OR OR
|
|
( "||" )
|
|
| OR
|
|
| DIVIDE
|
|
| EQUAL
|
|
| BANG
|
|
| TILDE
|
|
| MOD
|
|
| COMA
|
|
;; HAT EQUAL seems to have a really unpleasant result and
|
|
;; breaks everything after it. Leave it at the end, though it
|
|
;; doesn't seem to work.
|
|
| HAT EQUAL
|
|
( "^=" )
|
|
| HAT
|
|
;
|
|
|
|
functionname
|
|
: OPERATOR operatorsym
|
|
( ,$2 )
|
|
| semantic-list
|
|
( EXPAND $1 function-pointer )
|
|
| symbol
|
|
( $1 )
|
|
;
|
|
|
|
function-pointer
|
|
: LPAREN STAR opt-symbol RPAREN
|
|
( (concat "*" ,(car $3)) )
|
|
| LPAREN symbol RPAREN
|
|
( $2 )
|
|
;
|
|
|
|
fun-or-proto-end
|
|
: SEMICOLON
|
|
( t )
|
|
| semantic-list
|
|
( nil )
|
|
;; Here is an annoying feature of C++ pure virtual methods
|
|
| EQUAL ZERO SEMICOLON
|
|
( :pure-virtual-flag )
|
|
| fun-try-end
|
|
( nil )
|
|
;
|
|
|
|
fun-try-end
|
|
: TRY opt-initializers BRACE_BLCK fun-try-several-catches
|
|
( nil )
|
|
;
|
|
|
|
fun-try-several-catches
|
|
: CATCH PAREN_BLCK BRACE_BLCK fun-try-several-catches
|
|
( )
|
|
| CATCH BRACE_BLCK fun-try-several-catches
|
|
( )
|
|
| ;; EMPTY
|
|
( )
|
|
;
|
|
|
|
type-cast
|
|
: semantic-list
|
|
( EXPAND $1 type-cast-list )
|
|
;
|
|
|
|
type-cast-list
|
|
: open-paren typeformbase close-paren
|
|
;
|
|
|
|
opt-brackets-after-symbol
|
|
: brackets-after-symbol
|
|
| ;; EMPTY
|
|
;
|
|
|
|
brackets-after-symbol
|
|
: PAREN_BLCK
|
|
| BRACK_BLCK
|
|
;
|
|
|
|
multi-stage-dereference
|
|
: namespace-symbol opt-brackets-after-symbol
|
|
PERIOD multi-stage-dereference ;; method call
|
|
| namespace-symbol opt-brackets-after-symbol
|
|
MINUS GREATER multi-stage-dereference ;;method call
|
|
| namespace-symbol opt-brackets-after-symbol
|
|
PERIOD namespace-symbol opt-brackets-after-symbol
|
|
| namespace-symbol opt-brackets-after-symbol
|
|
MINUS GREATER namespace-symbol opt-brackets-after-symbol
|
|
| namespace-symbol brackets-after-symbol
|
|
;
|
|
|
|
string-seq
|
|
: string string-seq
|
|
( (concat $1 (car $2)) )
|
|
| string
|
|
( $1 )
|
|
;
|
|
|
|
expr-start
|
|
: MINUS
|
|
| PLUS
|
|
| STAR
|
|
| AMPERSAND
|
|
;
|
|
|
|
expr-binop
|
|
: MINUS
|
|
| PLUS
|
|
| STAR
|
|
| DIVIDE
|
|
| AMPERSAND AMPERSAND
|
|
| AMPERSAND
|
|
| OR OR
|
|
| OR
|
|
| MOD
|
|
;; There are more.
|
|
;
|
|
|
|
;; Use expression for parsing only. Don't actually return anything
|
|
;; for now. Hopefully we can fix this later.
|
|
expression
|
|
: unaryexpression QUESTION unaryexpression COLON unaryexpression
|
|
( (identity start) (identity end) )
|
|
| unaryexpression expr-binop unaryexpression
|
|
( (identity start) (identity end) )
|
|
| unaryexpression
|
|
( (identity start) (identity end) )
|
|
;
|
|
|
|
unaryexpression
|
|
: number
|
|
| multi-stage-dereference
|
|
| NEW multi-stage-dereference
|
|
| NEW builtintype-types semantic-list
|
|
| symbol
|
|
;; Klaus Berndl: C/C++ allows sequences of strings which are
|
|
;; concatenated by the precompiler to one string
|
|
| string-seq
|
|
| type-cast expression ;; A cast to some other type
|
|
;; Casting the results of one expression to something else.
|
|
| semantic-list expression
|
|
| semantic-list
|
|
| expr-start expression
|
|
;
|
|
|
|
;;; c.by ends here
|