/*
* Copyright (c) 2002, The Tendra Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Crown Copyright (c) 1997, 1998
*
* This TenDRA(r) Computer Program is subject to Copyright
* owned by the United Kingdom Secretary of State for Defence
* acting through the Defence Evaluation and Research Agency
* (DERA). It is made available to Recipients with a
* royalty-free licence for its use, reproduction, transfer
* to other parties and amendment for any purpose not excluding
* product development provided that any such use et cetera
* shall be deemed to be acceptance of the following conditions:-
*
* (1) Its Recipients shall ensure that this Notice is
* reproduced upon any copies or amended versions of it;
*
* (2) Any amended version of it shall be clearly marked to
* show both the nature of and the organisation responsible
* for the relevant amendment or amendments;
*
* (3) Its onward transfer from a recipient to another
* party shall be deemed to be that party's acceptance of
* these conditions;
*
* (4) DERA gives no warranty or assurance as to its
* quality or suitability for any purpose and DERA accepts
* no liability whatsoever in relation to any use to which
* it may be put.
*
* $TenDRA: tendra/src/producers/cpp/syntax/syntax.sid,v 1.9 2005/10/16 07:47:46 stefanf Exp $
*/
/*
* C++ SYNTAX
*
* This module contains the syntax for the C++ language.
*/
/*
* TYPE DECLARATIONS
*
* The types BOOL, COUNT and LEX are natural types arising from the
* parser. The remaining types directly correspond to types within the
* main program, or composite types formed from them.
*/
%types%
ACCESS;
ACCESSES;
BOOL;
BTYPE;
CONDITION;
COUNT;
CV;
DECL;
DSPEC;
EXP;
IDENTIFIER;
KEY;
LEX;
LINKAGE;
LIST-EXP;
LIST-TYPE;
NAMESPACE;
NUMBER;
OFFSET;
QUALIFIER;
TEMPLATE;
TYPE;
/*
* LIST OF TERMINALS
*
* This list of terminals corresponds to that given in symbols.h and
* psyntax.h.
*/
%terminals%
!unknown;
/* Identifiers */
identifier: () -> (:IDENTIFIER);
type-name: () -> (:IDENTIFIER);
namespace-name: () -> (:IDENTIFIER);
statement-name: () -> (:IDENTIFIER);
destructor-name: () -> (:IDENTIFIER);
template-id: () -> (:IDENTIFIER);
template-type: () -> (:IDENTIFIER);
/* Nested name specifiers */
nested-name: () -> (:NAMESPACE);
full-name: () -> (:NAMESPACE);
nested-name-star: () -> (:IDENTIFIER);
full-name-star: () -> (:IDENTIFIER);
/* Literals */
!char-lit; !wchar-lit; !string-lit; !wstring-lit; !integer-lit;
/* Literal expressions */
char-exp: () -> (:EXP);
wchar-exp: () -> (:EXP);
string-exp: () -> (:EXP);
wstring-exp: () -> (:EXP);
integer-exp: () -> (:EXP);
floating-exp: () -> (:EXP);
/* Token applications */
complex-exp: () -> (:EXP);
complex-stmt: () -> (:EXP);
complex-type: () -> (:TYPE);
/* Target-dependent preprocessing directives */
hash-if: () -> (:EXP);
hash-elif: () -> (:EXP);
hash-else;
hash-endif;
hash-pragma;
/* End of file markers */
!newline; eof;
/* Symbols */
and-1; and-eq-1; arrow; assign; !backslash; close-brace-1;
close-round; close-square-1; colon; comma; compl-1; div; div-eq;
dot; ellipsis; eq; greater; greater-eq; !hash-1; !hash-hash-1;
less; less-eq; logical-and-1; logical-or-1; lshift; lshift-eq;
minus; minus-eq; minus-minus; not-1; not-eq-1; open-brace-1;
open-round; open-square-1; or-1; or-eq-1; plus; plus-eq; plus-plus;
question; rem; rem-eq; rshift; rshift-eq; semicolon; star;
star-eq; xor-1; xor-eq-1; arrow-star; colon-colon; dot-star; abs;
max; min;
/* Digraphs */
!close-brace-2; !close-square-2; !hash-2; !hash-hash-2;
!open-brace-2; !open-square-2;
/* C keywords */
auto; break; case; char; const; continue; default; do; double;
else; enum; extern; float; for; goto; if; int; long; register;
return; short; signed; sizeof; static; struct; switch; typedef;
union; unsigned; void; volatile; while;
/* C99 keywords */
restrict;
/* C++ keywords */
asm; bool; catch; class; const-cast; delete; dynamic-cast;
explicit; export; false; friend; inline; mutable; namespace; new;
operator; private; protected; public; reinterpret-cast;
static-cast; template; this; throw; true; try; typeid; typename;
using; virtual; wchar-t;
/* ISO keywords */
!and-2; !and-eq-2; !compl-2; !logical-and-2; !logical-or-2;
!not-2; !not-eq-2; !or-2; !or-eq-2; !xor-2; !xor-eq-2;
/* TenDRA keywords */
!accept; !after; alignof; !all; !allow; !ambiguous; !analysis;
!argument; !arith-cap; !array; !as; !assert; !assignment; !begin;
!bitfield; !block; bottom; !cast; !character; !class-cap; !code;
!comment; !compatible; !complete; !compute; !conditional;
!conversion; !decimal; !decl; !define; !define-cap; !defined;
!definition; !depth; !directive; !directory; !disallow; discard;
!dollar; !either; !elif; ellipsis-exp; !end; !endif; !environment;
!equality; !error; !escape; exhaustive; !exp-cap; !explain;
!extend; !external; !extra; fall; !file; !float-cap; !forward;
!func-cap; !func-id; !function; !hexadecimal; !hiding; !ident; !identif;
!ifdef; !ifndef; !ignore; !implement; !implicit; !import; !include;
!includes; !include-next; !incompatible; !incomplete; !indented;
!initialization; !integer; !interface; !internal; !into; !int-cap;
!keyword; !limit; !line; !linkage; !lit; !longlong; !lvalue;
!macro; !main; !member; !member-cap; !name; !nat-cap; !nested;
!nline; !no; !no-def; !object; !octal; !of; !off; !on; !option;
!overflow; overload; !pointer; !postpone; !pragma; !pragma-2; !precedence;
!preserve; !printf; !proc-cap; !promote; !promoted; !prototype;
ptrdiff-t; !qualifier; !quote; reachable; !reference; !reject;
!representation; !reset; !resolution; !rvalue; !scalar-cap; !scanf;
set; size-t; !size-t-2; !sort; !std; !stmt-cap; !string;
!struct-cap; !suspend; !tag; !tag-cap; !tendra; !text; !this-name;
!token; !type; !type-cap; !typeof; !un-known; !unassert; !undef;
!unify; !union-cap; !unmatched; !unpostpone; unreachable; unused;
!use; !value; !variable; !variety-cap; !va-args; !volatile-t; vtable;
!warning; weak; !writeable; !zzzz;
/* Miscellaneous symbols */
!array-op; !builtin-file; !builtin-line; !close-template; !cond-op;
!delete-full; !delete-array; !delete-array-full; !func-op; !hash-op;
!hash-hash-op; inset-start; inset-end; !macro-arg; !new-full;
!new-array; !new-array-full; !open-init; !open-template; !zzzzzz;
/*
* ALTERNATIVE REPRESENTATIONS
*
* The ISO keywords and digraphs will have been replaced by their primary
* representations by this stage. These rules are effectively identities
* for these alternatives. Don't try removing them - SID gets very
* confused.
*/
%productions%
close-brace = { close-brace-1; };
close-square = { close-square-1; };
open-brace = { open-brace-1; };
open-square = { open-square-1; };
and = { and-1; };
and-eq = { and-eq-1; };
compl = { compl-1; };
logical-and = { logical-and-1; };
logical-or = { logical-or-1; };
not = { not-1; };
not-eq = { not-eq-1; };
or = { or-1; };
or-eq = { or-eq-1; };
xor = { xor-1; };
xor-eq = { xor-eq-1; };
ellipsis-aux = { ellipsis; || ellipsis-exp; };
/*
* LEXICAL TOKENS
*
* These actions give the lexical token numbers for various symbols.
*/
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
: () -> (:LEX);
/*
* EXPECTED SYMBOLS
*
* These rules are used when a certain symbol is expected. If it is
* not present then the action expected is called with the appropriate
* lexical token number.
*/
: (:LEX) -> ();
: () -> ();
: () -> ();
close-round-x = {
close-round;
## t = ; (t);
};
close-square-x = {
close-square;
## t = ; (t);
};
colon-x = {
colon;
## t = ; (t);
};
open-round-x = {
open-round;
## t = ; (t);
};
semicolon-x = {
semicolon;
## t = ; (t);
};
/*
* IDENTIFIERS
*
* The identifier terminal is exclusive - it does not include those
* identifiers which are actually type and namespace names. This rule
* gives all identifiers and sets the appropriate identifier type.
*/
any-identifier: () -> (id: IDENTIFIER) = {
id = identifier;
|| id = type-name;
|| id = namespace-name;
|| id = statement-name;
};
/*
* NAMESPACE SPECIFIERS
*
* The nested-name-specifiers are handled by the terminals nested-name
* (corresponding to nested-name-specifier in the specification) and
* full-name (corresponding to:: nested-name-specifier). These rules
* give various combinations of these specifiers.
*/
: () -> (:NAMESPACE);
: () -> (:NAMESPACE);
: (:NAMESPACE) -> ();
: (:NAMESPACE) -> ();
nonempty-nested-name: () -> (ns: NAMESPACE) = {
ns = nested-name; (ns);
|| ns = full-name; (ns);
};
any-nested-name: () -> (ns: NAMESPACE) = {
ns = nonempty-nested-name;
|| colon-colon; ns = ;
};
any-nested-name-opt: () -> (ns: NAMESPACE) = {
ns = any-nested-name;
|| ns = ;
};
/*
* LITERAL EXPRESSIONS
*
* These rules describe the literal expressions. These are the integer
* and floating point literals, the character and string literals, plus
* the boolean literals true and false. Concatenation of adjacent string
* literals has already been performed.
*/
: () -> (:EXP);
: () -> (:EXP);
integer-literal: () -> (e: EXP) = {
e = integer-exp;
};
character-literal: () -> (e: EXP) = {
e = char-exp;
|| e = wchar-exp;
};
floating-literal: () -> (e: EXP) = {
e = floating-exp;
};
string-literal: () -> (e: EXP) = {
e = string-exp;
|| e = wstring-exp;
};
boolean-literal: () -> (e: EXP) = {
false; e = ;
|| true; e = ;
};
literal: () -> (e: EXP) = {
e = integer-literal;
|| e = character-literal;
|| e = floating-literal;
|| e = string-literal;
|| e = boolean-literal;
};
/*
* OPERATOR AND CONVERSION FUNCTION IDENTIFIERS
*
* These rules describe the overloaded operator and conversion function
* names. These consist of 'operator' followed by one of a large number
* of operator names (including a few illegal ones which are immediately
* reported using error_overload) or a type name. Note the use of the
* predicate is_array to distinguish 'operator new []' from 'operator
* new [expression]'. The rule operator-id subsumes both the rules
* operator-function-id and conversion-function-id from the grammar.
*/
: () -> (:BOOL);
: () -> (:BOOL);
: (:BOOL) -> (:BOOL);
: (:BOOL) -> ();
: () -> (:QUALIFIER, :BOOL);
: (:QUALIFIER, :BOOL) -> ();
: () -> ();
: (:LEX) -> ();
: (:LEX) -> (:IDENTIFIER);
: (:TYPE, :BOOL) -> (:IDENTIFIER);
: () -> (:IDENTIFIER);
conversion-type-id: () -> (:TYPE);
operator-name: () -> (op: LEX) = {
op = ;
{
and;
|| and-eq;
|| arrow;
|| arrow-star;
|| assign;
|| comma;
|| compl;
|| div;
|| div-eq;
|| eq;
|| greater;
|| greater-eq;
|| less;
|| less-eq;
|| logical-and;
|| logical-or;
|| lshift;
|| lshift-eq;
|| minus;
|| minus-eq;
|| minus-minus;
|| not;
|| not-eq;
|| or;
|| or-eq;
|| plus;
|| plus-eq;
|| plus-plus;
|| rem;
|| rem-eq;
|| rshift;
|| rshift-eq;
|| star;
|| star-eq;
|| xor;
|| xor-eq;
|| abs;
|| max;
|| min;
};
||
open-round; close-round-x;
op = ;
||
open-square; close-square-x;
op = ;
||
new;
op = ;
||
delete;
op = ;
||
new; ? = ; open-square; close-square-x;
op = ;
||
delete; ? = ; open-square; close-square-x;
op = ;
||
op = ;
{
dot;
|| dot-star;
|| colon-colon;
|| colon;
|| alignof;
|| sizeof;
|| typeid;
|| vtable;
};
(op);
||
question; colon-x;
op = ;
(op);
};
operator-id: () -> (id: IDENTIFIER) = {
operator;
(i, b) = ;
td = ;
{
t = conversion-type-id;
d = (td);
tid = (t, d);
||
op = operator-name;
(td);
tid = (op);
};
(i, b);
id = tid;
};
/*
* IDENTIFIER EXPRESSIONS
*
* These rules describe the qualified and unqualified identifier
* expressions. The identifier qualifiers have been reworked slightly
* to make it clear exactly what is being qualified when and by what.
*/
: () -> (:BOOL);
: () -> (:BOOL);
: (:NAMESPACE, :IDENTIFIER) -> (:IDENTIFIER);
: (:IDENTIFIER) -> (:IDENTIFIER);
: (:IDENTIFIER) -> (:IDENTIFIER);
: (:NAMESPACE, :IDENTIFIER, :BOOL) -> (:IDENTIFIER);
: (:NAMESPACE) -> ();
: (:NAMESPACE) -> ();
: (:NAMESPACE) -> ();
: () -> (:IDENTIFIER);
unqualified-type: () -> (:IDENTIFIER);
any-qualified-type: () -> (:IDENTIFIER);
qualified-stmt-name: () -> (:IDENTIFIER);
template-opt: (ns: NAMESPACE) -> (t: BOOL) = {
(ns); template; t = ;
|| t = ;
};
nested-id: (ns: NAMESPACE) -> (id: IDENTIFIER) = {
id = identifier;
||
id = namespace-name;
||
id = destructor-name;
||
id = template-id;
||
(ns);
id = operator-id;
(ns);
};
unqualified-id: () -> (id: IDENTIFIER) = {
uid = identifier;
id = (uid);
||
uid = namespace-name;
id = (uid);
||
uid = operator-id;
id = (uid);
||
uid = destructor-name;
id = (uid);
||
uid = template-id;
id = (uid);
};
qualified-id: () -> (id: IDENTIFIER) = {
ns = nested-name;
q = template-opt (ns); uid = nested-id (ns);
(ns);
id = (ns, uid, q);
};
full-qualified-id: () -> (id: IDENTIFIER) = {
ns = full-name;
q = template-opt (ns); uid = nested-id (ns);
(ns);
id = (ns, uid, q);
};
top-qualified-id: () -> (id: IDENTIFIER) = {
colon-colon;
ns = ;
q = template-opt (ns); uid = nested-id (ns);
id = (ns, uid, q);
};
id-expression: () -> (id: IDENTIFIER) = {
id = unqualified-id;
|| id = qualified-id;
|| id = full-qualified-id;
|| id = top-qualified-id;
};
any-qualified-id: () -> (id: IDENTIFIER) = {
id = id-expression;
|| id = unqualified-type;
|| id = any-qualified-type;
|| id = qualified-stmt-name;
};
id-entry: () -> (id: IDENTIFIER) = {
id = any-qualified-id;
##
;
id = ;
};
/*
* PRIMARY EXPRESSIONS
*
* This rule describes the primary expressions. These include the
* literals, the identity expressions, the this expression and the
* parenthesised expressions. The assertion expressions are an
* extension.
*/
: () -> (:EXP);
: () -> (:EXP);
: () -> ();
: (:EXP) -> (:EXP);
: (:IDENTIFIER) -> (:EXP);
expression: () -> (:EXP);
primary-expression: () -> (e: EXP) = {
e = literal;
||
this;
e = ;
||
id = id-expression;
e = (id);
||
ellipsis-exp;
e = ;
||
open-round;
;
a = expression;
e = (a);
close-round;
||
e = complex-exp;
};
/*
* EXPRESSION LISTS
*
* These rules describes the lists of expressions. Note that the
* constituents are assignment-expressions so that any commas are list
* separators rather than comma operators.
*/
: () -> (:LIST-EXP);
: (:EXP, :LIST-EXP) -> (:LIST-EXP);
assignment-expression: () -> (:EXP);
expression-list: () -> (p: LIST-EXP) = {
e = assignment-expression;
{
comma; q = expression-list;
|| q = ;
};
p = (e, q);
};
expression-list-opt: () -> (p: LIST-EXP) = {
p = expression-list;
|| p = ;
};
/*
* QUALIFIED TYPE NAMES
*
* These rules describe the qualified and unqualified type names.
*/
any-type-name: () -> (id: IDENTIFIER) = {
id = type-name;
|| id = template-type;
};
unqualified-type: () -> (id: IDENTIFIER) = {
tid = any-type-name;
id = (tid);
};
qualified-type: () -> (id: IDENTIFIER) = {
ns = nested-name; tid = any-type-name;
(ns);
id = (ns, tid);
};
full-qualified-type: () -> (id: IDENTIFIER) = {
ns = full-name; tid = any-type-name;
(ns);
id = (ns, tid);
};
top-qualified-type: () -> (id: IDENTIFIER) = {
colon-colon; tid = any-type-name;
ns = ;
id = (ns, tid);
};
any-qualified-type: () -> (id: IDENTIFIER) = {
id = qualified-type;
|| id = full-qualified-type;
|| id = top-qualified-type;
};
/*
* FIELD SELECTOR EXPRESSIONS
*
* These rules are used to perform field selector look-up following a
* '.' or '->' operator. The input namespace gives the class being
* selected from (or the null namespace in case of an error). Note
* the provisions for dummy destructor calls.
*/
: () -> (:BTYPE);
: (:NAMESPACE) -> (:IDENTIFIER);
: (:IDENTIFIER, :BTYPE, :IDENTIFIER, :BTYPE) -> (:IDENTIFIER);
any-class-name: () -> (:IDENTIFIER);
base-type-specifier: () -> (:BTYPE);
field-type-expression: (ns: NAMESPACE) -> (id: IDENTIFIER) = {
tid = unqualified-type;
id = (ns, tid);
||
tid = qualified-type;
id = (ns, tid);
||
id = full-qualified-type;
||
id = top-qualified-type;
};
pseudo-destr-prefix: (ns: NAMESPACE) -> (id: IDENTIFIER, bt: BTYPE, cns: NAMESPACE) = {
cns = any-nested-name;
id = (cns);
bt = ;
||
id = field-type-expression (ns); colon-colon;
bt = ;
cns = ns;
||
bt = base-type-specifier; colon-colon;
id = ;
cns = ns;
};
pseudo-destr-suffix: () -> (id: IDENTIFIER, bt: BTYPE) = {
id = any-class-name;
bt = ;
||
bt = base-type-specifier;
id = ;
};
field-id-expression: (ns: NAMESPACE) -> (id: IDENTIFIER) = {
uid = nested-id (ns);
;
id = (ns, uid);
||
qid = qualified-id;
id = (ns, qid);
||
id = full-qualified-id;
||
id = top-qualified-id;
||
id = field-type-expression (ns);
||
(id1, bt1, ns1) = pseudo-destr-prefix (ns);
(i, b) = ;
compl; (id2, bt2) = pseudo-destr-suffix;
(i, b);
uid = (id1, bt1, id2, bt2);
id = (ns1, uid);
||
compl; (id2, bt2) = pseudo-destr-suffix;
;
id = (id2, bt2, id2, bt2);
};
/*
* POSTFIX EXPRESSIONS
*
* These rules describes the postfix expressions. These include array
* indexing, function calls and function style casts, field selectors,
* postfix increment and decrement operations, new style casts and
* type identification operators.
*/
: (:EXP) -> (:EXP);
: (:EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :LIST-EXP) -> (:EXP);
: (:TYPE, :EXP, :COUNT) -> (:EXP);
: (:TYPE, :LIST-EXP) -> (:EXP);
: (:TYPE, :EXP, :COUNT) -> (:EXP);
: (:TYPE, :EXP, :COUNT) -> (:EXP);
: (:TYPE, :EXP, :COUNT) -> (:EXP);
: (:TYPE, :EXP, :COUNT) -> (:EXP);
: (:EXP, :LEX, :COUNT) -> (:EXP);
: (:TYPE, :LEX, :COUNT) -> (:EXP);
: (:EXP) -> (:EXP, :TYPE, :NAMESPACE);
: (:EXP, :TYPE, :NAMESPACE, :IDENTIFIER, :BOOL) -> (:EXP);
: (:EXP) -> (:EXP, :TYPE, :NAMESPACE);
: (:EXP, :TYPE, :NAMESPACE, :IDENTIFIER, :BOOL) -> (:EXP);
: () -> ();
: () -> (:COUNT);
: () -> (:COUNT);
: (:COUNT) -> (:COUNT);
: (:COUNT) -> (:COUNT);
: () -> ();
: () -> ();
simple-type-id: () -> (:TYPE);
type-id: () -> (:TYPE, :COUNT);
type-id-false: () -> (:TYPE, :COUNT);
type-id-true: () -> (:TYPE, :COUNT);
cast-operand: () -> (t: TYPE, e: EXP, n: COUNT) = {
less; (t, n) = type-id; greater;
open-round; e = expression; close-round;
};
typeid-expression: (op: LEX) -> (e: EXP) = {
;
n1 = ;
m1 = ;
open-round;
{
a = expression; close-round;
n2 = (n1);
c = (a, op, n2);
||
(t, m2) = type-id-true; close-round;
c = (t, op, m2);
};
;
e = c;
};
postfix-expression: () -> (e: EXP) = {
e = primary-expression;
||
a = postfix-expression;
open-square; b = expression; close-square;
e = (a, b);
||
a = postfix-expression;
open-round; p = expression-list-opt; close-round;
e = (a, p);
||
t = simple-type-id;
open-round; p = expression-list-opt; close-round;
e = (t, p);
||
a = postfix-expression;
(b, t, ns) = (a);
dot; q = template-opt (ns); id = field-id-expression (ns);
e = (b, t, ns, id, q);
;
||
a = postfix-expression;
(b, t, ns) = (a);
arrow; q = template-opt (ns); id = field-id-expression (ns);
e = (b, t, ns, id, q);
;
||
a = postfix-expression; plus-plus;
e = (a);
||
a = postfix-expression; minus-minus;
e = (a);
||
dynamic-cast; (t, a, n) = cast-operand;
e = (t, a, n);
||
static-cast; (t, a, n) = cast-operand;
e = (t, a, n);
||
reinterpret-cast; (t, a, n) = cast-operand;
e = (t, a, n);
||
const-cast; (t, a, n) = cast-operand;
e = (t, a, n);
||
typeid; op = ; e = typeid-expression (op);
||
vtable; op = ; e = typeid-expression (op);
};
/*
* NEW EXPRESSIONS
*
* These rules describe the new expressions. These consist of a new
* operator followed by an optional placement, a type identifier (either
* a simplified form or a bracketed full form), and an optional initialiser
* list. Note that the second and third components have been combined
* as the single rule new-place-and-type.
*/
: () -> (:EXP);
: (:BOOL, :LIST-EXP, :TYPE, :COUNT, :BOOL, :EXP) -> (:EXP);
: () -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: (:TYPE, :LIST-EXP) -> (:EXP);
: (:TYPE) -> (:EXP);
new-type-id: () -> (:TYPE, :COUNT);
new-initialiser-opt: (t: TYPE) -> (e: EXP) = {
open-round; p = expression-list-opt; close-round;
e = (t, p);
||
e = (t);
};
colon-colon-opt: () -> (b: BOOL) = {
colon-colon; b = ;
|| b = ;
};
new-place-and-type: () -> (p: LIST-EXP, t: TYPE, n: COUNT) = {
open-round;
{
p = expression-list; close-round;
td = ;
{
open-round; (s, m) = type-id; close-round;
||
(s, m) = new-type-id;
};
(td);
t = s;
n = m;
||
(t, n) = type-id-false; close-round;
p = ;
};
||
(t, n) = new-type-id;
p = ;
};
new-expression: () -> (e: EXP) = {
b = colon-colon-opt; new;
td = ;
(p, t, n) = new-place-and-type;
d = (td);
s = ;
i = new-initialiser-opt (t);
a = (s, i);
e = (b, p, t, n, d, a);
};
/*
* DELETE EXPRESSIONS
*
* This rule describes the delete expressions. These consist of a
* delete operator followed by the expression to be deleted. The
* anachronistic form of the 'delete []' operator, in which the array
* size had to be given, has been included in the grammar, to be weeded
* out by the action anachronism_delete.
*/
: (:BOOL, :LEX, :EXP) -> (:EXP);
: (:EXP) -> ();
cast-expression: () -> (:EXP);
unary-expression: () -> (:EXP);
delete-operator: () -> (op: LEX) = {
delete;
op = ;
||
delete; open-square; close-square;
op = ;
||
delete; open-square; e = expression;
(e);
close-square;
op = ;
};
delete-expression: () -> (e: EXP) = {
b = colon-colon-opt;
op = delete-operator;
a = cast-expression;
e = (b, op, a);
};
/*
* UNARY EXPRESSIONS
*
* These rules describe the unary expressions. These include the simple
* unary operations (indirection, address, unary plus, unary minus, logical
* negation and bitwise complement), the prefix increment and decrement
* operations and sizeof expressions, as well as the new and delete
* expressions.
*/
: (:EXP) -> (:EXP);
: (:EXP) -> (:EXP);
: (:EXP) -> (:EXP);
: (:LEX, :EXP) -> (:EXP);
: (:EXP) -> (:EXP);
: (:EXP) -> (:EXP);
: (:LEX, :TYPE, :EXP, :COUNT) -> (:EXP);
: (:LEX, :EXP, :COUNT) -> (:TYPE);
sizeof-expression: (op: LEX) -> (e: EXP) = {
;
n1 = ;
m1 = ;
{
a = unary-expression;
n2 = (n1);
m2 = (m1);
t = (op, a, n2);
c = (op, t, a, m2);
||
open-round; (t, m2) = type-id-true;
a = ;
c = (op, t, a, m2);
close-round;
};
;
e = c;
};
unary-operator: () -> () = {
plus;
|| minus;
|| compl;
|| abs;
};
unary-expression: () -> (e: EXP) = {
e = postfix-expression;
||
plus-plus; a = cast-expression;
e = (a);
||
minus-minus; a = cast-expression;
e = (a);
||
star; a = cast-expression;
e = (a);
||
and; a = cast-expression;
e = (a);
||
not; a = cast-expression;
e = (a);
||
op = ; unary-operator;
a = cast-expression;
e = (op, a);
||
sizeof; op = ; e = sizeof-expression (op);
||
alignof; op = ; e = sizeof-expression (op);
||
e = new-expression;
||
e = delete-expression;
};
/*
* CAST EXPRESSIONS
*
* This rule describes the traditional style cast expressions, consisting
* of a bracketed type identifier followed by an expression. The ignore
* keyword is an extension which is semantically equivalent to casting
* to void.
*/
: (:EXP) -> (:EXP);
cast-expression: () -> (e: EXP) = {
e = unary-expression;
||
open-round; (t, n) = type-id-false; close-round;
a = cast-expression;
e = (t, a, n);
||
discard; a = cast-expression;
e = (a);
};
/*
* POINTER MEMBER EXPRESSIONS
*
* This rule describes the pointer to member expressions, consisting of
* the '.*' and '->*' operators.
*/
: () -> ();
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
pm-expression: () -> (e: EXP) = {
e = cast-expression;
||
a = pm-expression; dot-star;
;
b = cast-expression;
e = (a, b);
||
a = pm-expression; arrow-star;
;
b = cast-expression;
e = (a, b);
};
/*
* MULTIPLICATIVE EXPRESSIONS
*
* This rule describes the multiplicative expressions. These include
* the division and remainder operations, as well as multiplication.
*/
: (:EXP, :EXP) -> (:EXP);