[back]
# grammar for c++ object and function declarations, with the following
# simplifications:
#
#   only direct and assignment initializer (no brace enclosed initializer)
#   no template names
#   no abstract parameter declarations
#   no throw specifications on function types
#   expression is zero, NUMBER or a name
#   no conversion or operator function names
#
# examples:
#
#   int i;
#   int j, f (int q);
#   A (int i);
#   ~ A ();
#   A (int i);
#   void f (int q) = 0;
#
# Names can be qualified or unqualified.
# 
# This grammar has three fixed ambiguities:
#
#   1. Double colon in nested name.
#
#        A ::B
#      
#      The :: preceding B is treated always as part of the nested name
#      A::B, never part of a qualified declarator B
#   
#   2. Left parenthesis starting function parameters vs. start of direct
#      initializer.
#
#        int (* f) (
#      
#      The left parenthesis is first tried as the start of function
#      parameter clause, then tried as the start of direct
#      initializer.
#
#   3. Constructor name vs. type name on left parenthesis
#
#        A (
#
#      The left parenthesis could be the start of a nested declarator,
#      or the start of the constructor parameter clause.  A constructor
#      name is tried before a type name.
#
# On UserTypeNode,
#
#   user-type -> name
#
# a real C++ parser would have to check if 'name' is a declared type name.
#
# On CtorName1Node,
#
#   ctor-name -> nested-name-opt IDENT
#
# a real C++ parser would have to check if 'IDENT' is a declared constructor name.

# start rule
start -> simple-decl-seq-opt

# simple declaration seq opt
[]
simple-decl-seq-opt -> simple-decl-seq
simple-decl-seq-opt -> 

# simple declaration seq
[]
simple-decl-seq -> simple-decl

[(SeqNode)]
simple-decl-seq -> simple-decl-seq simple-decl

#
# names are used as type names and declarator names
# 

# nested name opt
nested-name-opt -> nested-name
nested-name-opt ->

# nested name
#
# a name followed a :: always creates a nested name, the :: is never
# the start of a file scope qualified declarator name
#

[NestedName1Node]
nested-name -> DCOLON

[NestedName2Node]
nested-name -> name DCOLON >!

# name
[NameNode]
name -> nested-name-opt IDENT

# ctor name (and dtor name)
[CtorName1Node]
ctor-name -> nested-name-opt IDENT

[CtorName2Node]
ctor-name -> nested-name-opt TILDE IDENT

#
# declaration specifiers
# 

# built-in type
[BltnTypeNode]
bltn-type -> bltn-type-token

# built-in type tokens
bltn-type-token -> BOOL
bltn-type-token -> CHAR
bltn-type-token -> DOUBLE
bltn-type-token -> FLOAT
bltn-type-token -> INT
bltn-type-token -> LONG
bltn-type-token -> SHORT
bltn-type-token -> SIGNED
bltn-type-token -> UNSIGNED
bltn-type-token -> VOID
bltn-type-token -> WCHAR

# user type
[UserTypeNode] 
user-type -> name

# cv specifier
[CvSpecNode]
cv-spec -> cv-spec-token

# cv specifier token
cv-spec-token -> CONST
cv-spec-token -> VOLATILE

# cv specifier sequence opt
[]
cv-spec-seq-opt -> cv-spec-seq
cv-spec-seq-opt ->

# cv specifier sequence
[]
cv-spec-seq -> cv-spec

[(SeqNode)]
cv-spec-seq -> cv-spec-seq cv-spec

# ftor (function and storage) specifiers
[FtorSpecNode]
ftor-spec -> ftor-spec-token

# ftor specifier tokens
ftor-spec-token -> INLINE
ftor-spec-token -> VIRTUAL
ftor-spec-token -> EXPLICIT
ftor-spec-token -> STATIC
ftor-spec-token -> EXTERN
ftor-spec-token -> MUTABLE
ftor-spec-token -> AUTO
ftor-spec-token -> REGISTER

# 
# declaration specifier sequence
# 
# Below we list all possible declaration specifier sequences.  We'll
# use the following naming scheme
#
#   NAME                   SEQUENCE OF 
#   xxVx-decl-spec-seq     cv specifiers
#   xxxS-decl-spec-seq     ftor (function and storage) specifiers
#   xBxx-decl-spec-seq     built-in type specifiers
#   xUxx-decl-spec-seq     (one) user type
#   Txxx-decl-spec-seq     (one) typedef
# 
# We combine the names above to form "compound" declaration specifier
# sequences
#
#   NAME                   SEQUENCE OF 
#   xxVS-decl-spec-seq     cv and ftor specifiers
#   xBVx-decl-spec-seq     built-in type and cv specifiers
#   xUVS-decl-spec-seq     (one) user type, cv and ftor specifiers
#
# etc.
#
# We could extend this to include
#
#   NAME                   SEQUENCE OF
#   Fxxx-decl-spec-seq     (one) friend
#   xCxx-decl-spec-seq     (one) class definition
#   xExx-decl-spec-seq     (one) elaborated type
#   xNxx-decl-spec-seq     (one) enum definition
# 

# cv 

[SeqNode]
xxVx-decl-spec-seq -> xxVx-decl-spec-seq cv-spec

[]
xxVx-decl-spec-seq -> cv-spec

# ftor (function and storage)

[(SeqNode)]
xxxS-decl-spec-seq -> xxxS-decl-spec-seq ftor-spec

[]
xxxS-decl-spec-seq -> ftor-spec

# cv and ftor

[(SeqNode)]
xxVS-decl-spec-seq -> xxVx-decl-spec-seq ftor-spec

[(SeqNode)]
xxVS-decl-spec-seq -> xxxS-decl-spec-seq cv-spec

[(SeqNode)]
xxVS-decl-spec-seq -> xxVS-decl-spec-seq ftor-spec

[(SeqNode)]
xxVS-decl-spec-seq -> xxVS-decl-spec-seq cv-spec

# built-in type

[(SeqNode)]
xBxx-decl-spec-seq -> xBxx-decl-spec-seq bltn-type

[]
xBxx-decl-spec-seq -> bltn-type

# built-in type and cv

[(SeqNode)]
xBVx-decl-spec-seq -> xBxx-decl-spec-seq cv-spec

[(SeqNode)]
xBVx-decl-spec-seq -> xxVx-decl-spec-seq bltn-type

[(SeqNode)]
xBVx-decl-spec-seq -> xBVx-decl-spec-seq cv-spec

[(SeqNode)]
xBVx-decl-spec-seq -> xBVx-decl-spec-seq bltn-type

# built-in type and ftor

[(SeqNode)]
xBxS-decl-spec-seq -> xBxx-decl-spec-seq ftor-spec

[(SeqNode)]
xBxS-decl-spec-seq -> xxxS-decl-spec-seq bltn-type

[(SeqNode)]
xBxS-decl-spec-seq -> xBxS-decl-spec-seq ftor-spec

[(SeqNode)]
xBxS-decl-spec-seq -> xBxS-decl-spec-seq bltn-type

# built-in type, cv and ftor

[(SeqNode)]
xBVS-decl-spec-seq -> xBVx-decl-spec-seq ftor-spec

[(SeqNode)]
xBVS-decl-spec-seq -> xBxS-decl-spec-seq cv-spec

[(SeqNode)]
xBVS-decl-spec-seq -> xxVS-decl-spec-seq bltn-type

[(SeqNode)]
xBVS-decl-spec-seq -> xBVS-decl-spec-seq ftor-spec

[(SeqNode)]
xBVS-decl-spec-seq -> xBVS-decl-spec-seq cv-spec

[(SeqNode)]
xBVS-decl-spec-seq -> xBVS-decl-spec-seq bltn-type

# user type

[ ]
xUxx-decl-spec-seq -> user-type

# user type and cv

[(SeqNode)]
xUVx-decl-spec-seq -> xUxx-decl-spec-seq cv-spec

[(SeqNode)]
xUVx-decl-spec-seq -> xxVx-decl-spec-seq user-type

[(SeqNode)]
xUVx-decl-spec-seq -> xUVx-decl-spec-seq cv-spec

# user type and ftor

[(SeqNode)]
xUxS-decl-spec-seq -> xUxx-decl-spec-seq ftor-spec

[(SeqNode)]
xUxS-decl-spec-seq -> xxxS-decl-spec-seq user-type

[(SeqNode)]
xUxS-decl-spec-seq -> xUxS-decl-spec-seq ftor-spec

# user type, cv and ftor

[(SeqNode)]
xUVS-decl-spec-seq -> xUVx-decl-spec-seq ftor-spec

[(SeqNode)]
xUVS-decl-spec-seq -> xUxS-decl-spec-seq cv-spec

[(SeqNode)]
xUVS-decl-spec-seq -> xxVS-decl-spec-seq user-type

[(SeqNode)]
xUVS-decl-spec-seq -> xUVS-decl-spec-seq ftor-spec

[(SeqNode)]
xUVS-decl-spec-seq -> xUVS-decl-spec-seq cv-spec

# typedef

[ ]
Txxx-decl-spec-seq -> TYPEDEF

# typedef and cv

[(SeqNode)]
TxVx-decl-spec-seq -> Txxx-decl-spec-seq cv-spec

[(SeqNode)]
TxVx-decl-spec-seq -> xxVx-decl-spec-seq TYPEDEF

[(SeqNode)]
TxVx-decl-spec-seq -> TxVx-decl-spec-seq cv-spec

# typedef and ftor 

[(SeqNode)]
TxxS-decl-spec-seq -> Txxx-decl-spec-seq ftor-spec

[(SeqNode)]
TxxS-decl-spec-seq -> xxxS-decl-spec-seq TYPEDEF

[(SeqNode)]
TxxS-decl-spec-seq -> TxxS-decl-spec-seq ftor-spec

# typedef, cv and ftor

[(SeqNode)]
TxVS-decl-spec-seq -> TxVx-decl-spec-seq ftor-spec

[(SeqNode)]
TxVS-decl-spec-seq -> TxxS-decl-spec-seq cv-spec

[(SeqNode)]
TxVS-decl-spec-seq -> xxVS-decl-spec-seq TYPEDEF

[(SeqNode)]
TxVS-decl-spec-seq -> TxVS-decl-spec-seq ftor-spec

[(SeqNode)]
TxVS-decl-spec-seq -> TxVS-decl-spec-seq cv-spec

# typedef and built-in type

[(SeqNode)]
TBxx-decl-spec-seq -> Txxx-decl-spec-seq bltn-type

[(SeqNode)]
TBxx-decl-spec-seq -> xBxx-decl-spec-seq TYPEDEF

[(SeqNode)]
TBxx-decl-spec-seq -> TBxx-decl-spec-seq bltn-type

# typedef, built-in type and cv

[(SeqNode)]
TBVx-decl-spec-seq -> TBxx-decl-spec-seq cv-spec

[(SeqNode)]
TBVx-decl-spec-seq -> TxVx-decl-spec-seq bltn-type

[(SeqNode)]
TBVx-decl-spec-seq -> xBVx-decl-spec-seq TYPEDEF

[(SeqNode)]
TBVx-decl-spec-seq -> TBVx-decl-spec-seq cv-spec

[(SeqNode)]
TBVx-decl-spec-seq -> TBVx-decl-spec-seq bltn-type

# typedef, built-in type and ftor

[(SeqNode)]
TBxS-decl-spec-seq -> TBxx-decl-spec-seq ftor-spec

[(SeqNode)]
TBxS-decl-spec-seq -> TxxS-decl-spec-seq bltn-type

[(SeqNode)]
TBxS-decl-spec-seq -> xBxS-decl-spec-seq TYPEDEF

[(SeqNode)]
TBxS-decl-spec-seq -> TBxS-decl-spec-seq ftor-spec

[(SeqNode)]
TBxS-decl-spec-seq -> TBxS-decl-spec-seq bltn-type

# typedef, built-in type, cv and ftor

[(SeqNode)]
TBVS-decl-spec-seq -> TBVx-decl-spec-seq ftor-spec

[(SeqNode)]
TBVS-decl-spec-seq -> TBxS-decl-spec-seq cv-spec

[(SeqNode)]
TBVS-decl-spec-seq -> TxVS-decl-spec-seq bltn-type

[(SeqNode)]
TBVS-decl-spec-seq -> xBVS-decl-spec-seq TYPEDEF

[(SeqNode)]
TBVS-decl-spec-seq -> TBVS-decl-spec-seq ftor-spec

[(SeqNode)]
TBVS-decl-spec-seq -> TBVS-decl-spec-seq cv-spec

[(SeqNode)]
TBVS-decl-spec-seq -> TBVS-decl-spec-seq bltn-type

# typedef and user type

[(SeqNode)]
TUxx-decl-spec-seq -> Txxx-decl-spec-seq user-type

[(SeqNode)]
TUxx-decl-spec-seq -> xUxx-decl-spec-seq TYPEDEF

# typedef, user type and cv

[(SeqNode)]
TUVx-decl-spec-seq -> TUxx-decl-spec-seq cv-spec

[(SeqNode)]
TUVx-decl-spec-seq -> TxVx-decl-spec-seq user-type

[(SeqNode)]
TUVx-decl-spec-seq -> xUVx-decl-spec-seq TYPEDEF

[(SeqNode)]
TUVx-decl-spec-seq -> TUVx-decl-spec-seq cv-spec

# typedef, user type and ftor

[(SeqNode)]
TUxS-decl-spec-seq -> TUxx-decl-spec-seq ftor-spec

[(SeqNode)]
TUxS-decl-spec-seq -> TxxS-decl-spec-seq user-type

[(SeqNode)]
TUxS-decl-spec-seq -> xUxS-decl-spec-seq TYPEDEF

[(SeqNode)]
TUxS-decl-spec-seq -> TUxS-decl-spec-seq ftor-spec

# typedef, user type, cv and ftor

[(SeqNode)]
TUVS-decl-spec-seq -> TUVx-decl-spec-seq ftor-spec

[(SeqNode)]
TUVS-decl-spec-seq -> TUxS-decl-spec-seq cv-spec

[(SeqNode)]
TUVS-decl-spec-seq -> TxVS-decl-spec-seq user-type

[(SeqNode)]
TUVS-decl-spec-seq -> xUVS-decl-spec-seq TYPEDEF

[(SeqNode)]
TUVS-decl-spec-seq -> TUVS-decl-spec-seq ftor-spec

[(SeqNode)]
TUVS-decl-spec-seq -> TUVS-decl-spec-seq cv-spec

#
# simple declaration
#

# simple declaration
[SimpleDeclNode]
simple-decl -> nested-decl SEMI

# nested declaration
[]
nested-decl * -> nested-obj-init-decl

[]
nested-decl * -> nested-func-decl

# object declaration with initializer
[ObjInitDeclNode]
nested-obj-init-decl -> nested-obj-decl obj-init-opt

# object inititalizer opt
obj-init-opt -> obj-init
obj-init-opt -> 

# object initializer
[ObjInit1Node]
obj-init -> ASSIGN expr

[ObjInit2Node]
obj-init -> LPAREN expr-list RPAREN

# expr list
[]
expr-list -> expr

[(SeqNode)]
expr-list -> expr-list COMMA expr

# nested object declarator
#
# try obj-dcl before initializer, example:
#
#   int (* i) (
#
# try left paren as start of function parameters before direct initializer
# 
[NestedObjDecl1Node]
nested-obj-decl -> nested-decl COMMA obj-dcl >

[NestedObjDecl2Node]
nested-obj-decl -> obj-decl >

# object decl
[ Decl1Node ]
obj-decl -> xBxx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> xBVx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> xBxS-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> xBVS-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> xUxx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> xUVx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> xUxS-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> xUVS-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TBxx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TBVx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TBxS-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TBVS-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TUxx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TUVx-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TUxS-decl-spec-seq   obj-dcl

[(Decl1Node)]
obj-decl -> TUVS-decl-spec-seq   obj-dcl

#
# object declarator
#

[]
obj-dcl -> obj-a-dcl

# object-a declarator
[DclNode]
obj-a-dcl -> ptr-oper obj-a-dcl

[]
obj-a-dcl -> obj-a-direct-dcl

# object-b declarator
[(DclNode)]
obj-b-dcl -> ptr-oper obj-a-dcl

[]
obj-b-dcl -> obj-b-direct-dcl

# object-a direct declarator
[]
obj-a-direct-dcl -> obj-b-direct-dcl

[]
obj-a-direct-dcl -> obj-dcl-id

# object-a direct declarator
[DirectDcl1Node]
obj-b-direct-dcl -> obj-b-direct-dcl LPAREN param-decl-clause RPAREN cv-spec-seq-opt

[DirectDcl2Node]
obj-b-direct-dcl -> obj-a-direct-dcl LBRACK expr RBRACK

[DirectDcl3Node]
obj-b-direct-dcl -> LPAREN obj-b-dcl RPAREN

# object declarator id
obj-dcl-id -> obj-id

[(DirectDcl3Node)]
obj-dcl-id -> LPAREN obj-dcl-id RPAREN

# object id
[IdNode]
obj-id -> name

# pointer operator
[PtrOper1Node]
ptr-oper -> TIMES cv-spec-seq-opt

[PtrOper2Node]
ptr-oper -> AMPERSAND

[PtrOper3Node]
ptr-oper -> name DCOLON TIMES cv-spec-seq-opt

#
# parameter declaration
#

# parameter declaration clause
[ParamDeclClause1Node]
param-decl-clause -> param-decl-list-opt ellipse-opt

[ParamDeclClause2Node]
param-decl-clause -> param-decl-list COMMA ELLIPSE

# ellipse opt
ellipse-opt -> ELLIPSE 
ellipse-opt ->

# parameter declaration list opt
[]
param-decl-list-opt -> param-decl-list

param-decl-list-opt -> 

# parameter declaration list
[]
param-decl-list -> param-init-decl

[(SeqNode)]
param-decl-list -> param-decl-list COMMA param-init-decl

# parameter declaration with initializer (default argument)
[ParamInitDecl1Node]
param-init-decl -> param-decl

[ParamInitDecl2Node]
param-init-decl -> param-decl ASSIGN expr

# parameter declaration
[(Decl1Node)]
param-decl -> xBxx-decl-spec-seq   param-dcl

[(Decl1Node)]
param-decl -> xBVx-decl-spec-seq   param-dcl

[(Decl1Node)]
param-decl -> xBxS-decl-spec-seq   param-dcl

[(Decl1Node)]
param-decl -> xBVS-decl-spec-seq   param-dcl

[(Decl1Node)]
param-decl -> xUxx-decl-spec-seq   param-dcl

[(Decl1Node)]
param-decl -> xUVx-decl-spec-seq   param-dcl

[(Decl1Node)]
param-decl -> xUxS-decl-spec-seq   param-dcl

[(Decl1Node)]
param-decl -> xUVS-decl-spec-seq   param-dcl

# parameter declarator
# similar to object declarator except permits (implicit pointer to function) declarations
# of the form
#   int f (int i)

[]
param-dcl -> param-a-dcl

# param a dcl

[(DclNode)]
param-a-dcl -> ptr-oper param-a-dcl

[]
param-a-dcl -> param-a-direct-dcl

# param b dcl

[(DclNode)]
param-b-dcl -> ptr-oper param-a-dcl

[]
param-b-dcl -> param-b-direct-dcl

# param a direct dcl

[]
param-a-direct-dcl -> param-b-direct-dcl

[]
param-a-direct-dcl -> obj-dcl-id

# param b direct dcl

[(DirectDcl1Node)]
param-b-direct-dcl -> param-a-direct-dcl LPAREN param-decl-clause RPAREN cv-spec-seq-opt

[(DirectDcl2Node)]
param-b-direct-dcl -> param-a-direct-dcl LBRACK expr RBRACK

[(DirectDcl3Node)]
param-b-direct-dcl -> LPAREN param-b-dcl RPAREN

#
# function declaration
#

# try func-decl before initializer, example:
#
#   int f (
#
# try left paren as start of function parameters before object direct initializer
#
[ FuncDecl1Node ]
nested-func-decl -> nested-decl COMMA pure-func-dcl >

[ FuncDecl2Node ]
nested-func-decl -> func-decl >

# func decl

# try constructor names before types names

[ Decl2Node ]
func-decl ->                      pure-ctor-dcl >

[(Decl1Node)]
func-decl -> xxxS-decl-spec-seq   pure-ctor-dcl >

[(Decl1Node)]
func-decl -> xBxx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> xBVx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> xBxS-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> xBVS-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> xUxx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> xUVx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> xUxS-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> xUVS-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TBxx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TBVx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TBxS-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TBVS-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TUxx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TUVx-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TUxS-decl-spec-seq   pure-func-dcl

[(Decl1Node)]
func-decl -> TUVS-decl-spec-seq   pure-func-dcl

#
# function declarator
#

# pure function declarator
[PureDclNode]
pure-func-dcl -> func-dcl pure-opt

# pure opt
pure-opt -> pure
pure-opt -> 

# pure
[PureNode]
pure -> ASSIGN ZERO

# function declarator
[(DclNode)]
func-dcl -> ptr-oper func-dcl

[]
func-dcl -> func-b-direct-dcl

# function-a direct declarator
[]
func-a-direct-dcl -> obj-dcl-id

[]
func-a-direct-dcl -> func-b-direct-dcl

# function-b direct declarator
[(DirectDcl1Node)]
func-b-direct-dcl -> func-a-direct-dcl LPAREN param-decl-clause RPAREN cv-spec-seq-opt

[(DirectDcl2Node)]
func-b-direct-dcl -> func-b-direct-dcl LBRACK expr RBRACK

[(DirectDcl3Node)]
func-b-direct-dcl -> LPAREN func-dcl RPAREN

#
# ctor declarator
# 
# constructor and destructor declarator
#

# pure ctor decl (really only dtors can be pure)
pure-ctor-dcl -> ctor-dcl pure-opt

# ctor dcl
ctor-dcl -> ctor-direct-dcl

# ctor direct declarator
[(DirectDcl1Node)]
ctor-direct-dcl -> ctor-dcl-id LPAREN param-decl-clause RPAREN cv-spec-seq-opt

[(DirectDcl3Node)]
ctor-direct-dcl -> LPAREN ctor-dcl RPAREN

# ctor declarator id
ctor-dcl-id -> ctor-id

[(DirectDcl3Node)]
ctor-dcl-id -> LPAREN ctor-dcl-id RPAREN

# ctor id
[(IdNode)]
ctor-id -> ctor-name

#
# expression
#
# expression can be a name or a number
#

[Expr1Node]
expr -> name

[Expr2Node]
expr -> NUMBER

[Expr3Node]
expr -> ZERO
[back]