[back]
# Grammar for tempate-id with type and non-type template arguments
#
# This grammar has several resolved conflicts:
#
# 1) A <1 > 2>
#
#    The first non-nested '>' terminates a template id, so '1 > 2' is
#    never a template non-type argument.
#
#    This is fixed by giving the GT a first priority with an exclusive
#    modifier:
#
#      name -> nested-name-opt IDENT LT template-arg-list-opt GT ^!
#
#    The same could have been achieved by giving template-arg-list-opt
#    a reduce priority with an exclusive modifier:
#    
#      name -> nested-name-opt IDENT LT template-arg-list-opt +! GT
#
# 2) A <1, 2>
#
#    The ',' is never the comma in a comma-expr.
#
#    This is fixed by giving COMMA a first priority with an
#    exclusive modifier:
#
#      template-arg-list -> template-arg-list COMMA ^! template-arg
#
# 3) A <B> or A <B * C>
#
#    The 'B' should first be tried as a type name, then as an expression.
#
#    This is fixed by giving the abstract declaration one shift priority
#    and one reduce priority:
#
#      template-arg -> abstract-decl >+
#      template-arg -> expr
#
#    The shift priority is for cases like 'B * C', the reduce priority
#    is for cases like 'B'.
#
# 4) A <int (*) (int)>
#
#    The first '(' is tried as the start of a nested abstract declarator,
#    then as the start of a parameter list. 
#
#    This is fixed by giving LPAREN a shift priority:
#
#      abstract-direct-dcl -> LPAREN > abstract-dcl RPAREN
#
# 5) A <(B <C>)>
#
#    B is first tried as a template name, then as an expression.  A real
#    C++ compiler would check on the template name reduction if 'B' is
#    a declared template.
#
#    This is fixed by giving name one shift prioirty:
#
#      primary-expr -> name >
#
#    Note that in 'A <B <C> >' the conflict doesn't arise because we've
#    already given abstract-decl a shift priority (see 3 above).
#
# The best way to understand the conflicts is to remove the fix then run basil
# and look at the log file.
#

# start rule
start -> name

# name
[Name1Node]
name -> nested-name-opt IDENT
[Name2Node]
name -> nested-name-opt IDENT LT template-arg-list-opt GT ^!

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

# nested name
[NestedName1Node]
nested-name -> DCOLON

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

#
# template argument list
#

# template arg list opt
template-arg-list-opt -> template-arg-list
template-arg-list-opt ->

# template arg list
template-arg-list -> template-arg
template-arg-list -> template-arg-list COMMA ^! template-arg

# template arg
template-arg -> abstract-decl >+
template-arg -> expr

#
# abstract decl
#
[ AbstractDeclNode ]
abstract-decl -> xBxx-decl-spec-seq abstract-dcl-opt

[(AbstractDeclNode)]
abstract-decl -> xBVx-decl-spec-seq abstract-dcl-opt

[(AbstractDeclNode)]
abstract-decl -> xBxS-decl-spec-seq abstract-dcl-opt

[(AbstractDeclNode)]
abstract-decl -> xBVS-decl-spec-seq abstract-dcl-opt

[(AbstractDeclNode)]
abstract-decl -> xUxx-decl-spec-seq abstract-dcl-opt

[(AbstractDeclNode)]
abstract-decl -> xUVx-decl-spec-seq abstract-dcl-opt

[(AbstractDeclNode)]
abstract-decl -> xUxS-decl-spec-seq abstract-dcl-opt

[(AbstractDeclNode)]
abstract-decl -> xUVS-decl-spec-seq abstract-dcl-opt

#
# abstract declarator: declarator without an id  
#

# abstract declarator
[AbstractDclNode]
abstract-dcl -> ptr-oper abstract-dcl-opt

[]
abstract-dcl -> abstract-direct-dcl

# abstract direct declarator
[AbstractDirectDcl1Node]
abstract-direct-dcl -> abstract-direct-dcl-opt LPAREN param-decl-clause RPAREN cv-spec-seq-opt

[AbstractDirectDcl2Node]
abstract-direct-dcl -> abstract-direct-dcl-opt LBRACK expr-opt RBRACK

# try a nested abstract declarator before an empty abstract direct declarator   
[AbstractDirectDcl3Node]
abstract-direct-dcl -> LPAREN > abstract-dcl RPAREN
        
# abstract declarator opt
[]
abstract-dcl-opt -> abstract-dcl

abstract-dcl-opt ->

# abstract direct declarator opt
[]
abstract-direct-dcl-opt -> abstract-direct-dcl

abstract-direct-dcl-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-decl

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

# parameter declaration
[ ParamDeclNode ]
param-decl -> xBxx-decl-spec-seq param-dcl

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

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

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

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

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

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

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

#
# parameter declarator
#
[]
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

#
# 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

#
# 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

#
# expression
#

# expr opt
expr-opt -> expr
expr-opt ->

# expr
[ExprNode]
expr -> comma-expr

# comma expr
[CommaExprNode] 
comma-expr -> comma-expr COMMA assign-expr
[]
comma-expr -> assign-expr

# assign expr
[G_AssignExprNode ]
assign-expr -> log-or-expr ASSIGN assign-expr
[]
assign-expr -> cond-expr

# conditional expr
[CondExprNode]
cond-expr -> log-or-expr QMARK expr COLON assign-expr

[]
cond-expr -> log-or-expr

# logical or expression
[LogOrExprNode]
log-or-expr -> log-or-expr OR log-and-expr
[]
log-or-expr -> log-and-expr

# logical and expression
[LogAndExprNode]
log-and-expr -> log-and-expr AND incl-or-expr

[]
log-and-expr -> incl-or-expr

# inclusive or expression
[InclOrExprNode]
incl-or-expr -> incl-or-expr BITOR excl-or-expr

[]
incl-or-expr -> excl-or-expr

# exclusive or expression
[ExclOrExprNode]
excl-or-expr -> excl-or-expr XOR and-expr

[]
excl-or-expr -> and-expr

# and expression
[AndExprNode]
and-expr -> and-expr BITAND eq-expr

[]
and-expr -> eq-expr

# equality expression
[G_EqExpr1Node ]
eq-expr -> eq-expr EQ rel-expr

[G_EqExpr2Node ]
eq-expr -> eq-expr NOTEQ rel-expr

[]
eq-expr -> rel-expr

# rel expression
[RelExpr1Node]
rel-expr -> rel-expr LT shift-expr

[RelExpr2Node]
rel-expr -> rel-expr GT shift-expr

[RelExpr3Node]
rel-expr -> rel-expr LTEQ shift-expr

[RelExpr4Node]
rel-expr -> rel-expr GTEQ shift-expr

[]
rel-expr -> shift-expr

# shift expression
[ShiftExpr1Node]
shift-expr -> shift-expr LSHIFT add-expr

[ShiftExpr2Node]
shift-expr -> shift-expr RSHIFT add-expr

[]
shift-expr -> add-expr

# additive expression
[AddExpr1Node]
add-expr -> add-expr PLUS mult-expr

[AddExpr2Node]
add-expr -> add-expr MINUS mult-expr

[]
add-expr -> mult-expr

# multipicative expression
#
# assume primary expr is next (skip cast, unary, postfix)
#
[MultExpr1Node]
mult-expr -> mult-expr TIMES primary-expr

[MultExpr2Node]
mult-expr -> mult-expr DIVIDE primary-expr

[MultExpr3Node]
mult-expr -> mult-expr MOD primary-expr

[]
mult-expr -> primary-expr

# primary expr
# assume a primary expr is a number, name or a nested expression
[PrimaryExpr1Node]
primary-expr -> NUMBER

[PrimaryExpr2Node]
primary-expr -> name >

[PrimaryExpr3Node]
primary-expr -> LPAREN expr RPAREN

[back]