/*
* 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/c/syntax/syntax.sid,v 1.16 2005/10/16 07:47:45 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%
BOOL;
BTYPE;
CONDITION;
COUNT;
CV;
DECL;
DSPEC;
EXP;
IDENTIFIER;
KEY;
LEX;
LIST-EXP;
NAMESPACE;
NUMBER;
OFFSET;
TYPE;
/*
* LIST OF TERMINALS
*
* This list of terminals corresponds to that given in symbols.h. It can
* be automatically generated using the routine sid_terminals defined in
* debug.c (q.v).
*/
%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; };
/*
* LEXICAL TOKENS
*
* These actions give the lexical token numbers for various symbols.
*/
: () -> (: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) -> ();
: () -> ();
: () -> ();
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.
*/
: () -> (:IDENTIFIER);
: () -> (:IDENTIFIER);
any-identifier: () -> (id: IDENTIFIER) = {
id = identifier;
|| id = type-name;
|| id = statement-name;
};
any-identifier-opt: () -> (id: IDENTIFIER) = {
id = any-identifier;
|| id = ;
};
id-entry: () -> (id: IDENTIFIER) = {
id = any-identifier;
##
;
id = ;
};
operator-id: () -> (id: IDENTIFIER) = {
;
id = ;
};
/*
* LITERAL EXPRESSIONS
*
* These rules describe the literal expressions. These are the integer
* and floating point literals and the character and string literals.
* Concatenation of adjacent string literals has already been performed.
*/
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;
};
literal: () -> (e: EXP) = {
e = integer-literal;
|| e = character-literal;
|| e = floating-literal;
|| e = string-literal;
};
/*
* 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);
: (:IDENTIFIER) -> (:EXP);
expression: () -> (:EXP);
primary-expression: () -> (e: EXP) = {
e = literal;
||
id = identifier;
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 = ;
};
/*
* 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.
*/
: (:NAMESPACE, :IDENTIFIER) -> (:IDENTIFIER);
field-id-expression: (ns: NAMESPACE) -> (id: IDENTIFIER) = {
uid = any-identifier;
id = (ns, uid);
};
/*
* 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);
: (:EXP) -> (:EXP, :TYPE, :NAMESPACE);
: (:EXP, :TYPE, :NAMESPACE, :IDENTIFIER) -> (:EXP);
: (:EXP) -> (:EXP, :TYPE, :NAMESPACE);
: (:EXP, :TYPE, :NAMESPACE, :IDENTIFIER) -> (:EXP);
: () -> ();
: () -> (:COUNT);
: () -> (:COUNT);
: (:COUNT) -> (:COUNT);
: (:COUNT) -> (:COUNT);
: () -> ();
: () -> ();
type-id: () -> (:TYPE, :COUNT);
type-id-false: () -> (:TYPE, :COUNT);
type-id-true: () -> (:TYPE, :COUNT);
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;
e = (a, p);
close-round;
||
a = postfix-expression;
(b, t, ns) = (a);
dot; id = field-id-expression (ns);
e = (b, t, ns, id);
;
||
a = postfix-expression;
(b, t, ns) = (a);
arrow; id = field-id-expression (ns);
e = (b, t, ns, id);
;
||
a = postfix-expression; plus-plus;
e = (a);
||
a = postfix-expression; minus-minus;
e = (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);
: () -> (:EXP);
: (:LEX, :TYPE, :EXP, :COUNT) -> (:EXP);
: (:LEX, :EXP, :COUNT) -> (:TYPE);
unary-expression: () -> (:EXP);
cast-expression: () -> (:EXP);
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 = unary-expression;
e = (a);
||
minus-minus; a = unary-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);
};
/*
* 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.
*/
: (:TYPE, :EXP, :COUNT) -> (:EXP);
: (: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);
};
/*
* MULTIPLICATIVE EXPRESSIONS
*
* This rule describes the multiplicative expressions. These include
* the division and remainder operations, as well as multiplication.
*/
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
multiplicative-expression: () -> (e: EXP) = {
e = cast-expression;
||
a = multiplicative-expression; star; b = cast-expression;
e = (a, b);
||
a = multiplicative-expression; div; b = cast-expression;
e = (a, b);
||
a = multiplicative-expression; rem; b = cast-expression;
e = (a, b);
};
/*
* ADDITIVE EXPRESSIONS
*
* This rule describes the additive expressions. These include both the
* addition and the subtraction operations.
*/
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
additive-expression: () -> (e: EXP) = {
e = multiplicative-expression;
||
a = additive-expression; plus; b = multiplicative-expression;
e = (a, b);
||
a = additive-expression; minus; b = multiplicative-expression;
e = (a, b);
};
/*
* SHIFT EXPRESSIONS
*
* This rule describes the shift expressions. Both left and right shifts
* are included.
*/
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
shift-expression: () -> (e: EXP) = {
e = additive-expression;
||
a = shift-expression; lshift; b = additive-expression;
e = (a, b);
||
a = shift-expression; rshift; b = additive-expression;
e = (a, b);
};
/*
* RELATIONAL EXPRESSIONS
*
* These rules describe the relational expressions, less than, greater
* than, less than or equal and greater than or equal.
*/
: (:LEX, :EXP, :EXP) -> (:EXP);
relational-operator: () -> () = {
less;
|| greater;
|| less-eq;
|| greater-eq;
};
relational-expression: () -> (e: EXP) = {
e = shift-expression;
||
a = relational-expression;
op = ; relational-operator;
b = shift-expression;
e = (op, a, b);
};
/*
* EQUALITY EXPRESSIONS
*
* These rules describe the equality expressions, equal and not equal.
*/
: (:LEX, :EXP, :EXP) -> (:EXP);
equality-operator: () -> () = {
eq;
|| not-eq;
};
equality-expression: () -> (e: EXP) = {
e = relational-expression;
||
a = equality-expression;
op = ; equality-operator;
b = relational-expression;
e = (op, a, b);
};
/*
* MAXIMUM AND MINIMUM EXPRESSIONS (EXTENSION)
*
* These rules describes the maximum and minimum expressions.
*/
: (:LEX, :EXP, :EXP) -> (:EXP);
maxmin-operator: () -> () = {
max;
|| min;
};
maxmin-expression: () -> (e: EXP) = {
e = equality-expression;
||
a = maxmin-expression;
op = ; maxmin-operator;
b = equality-expression;
e = (op, a, b);
};
/*
* AND EXPRESSIONS
*
* This rule describes the bitwise and expressions.
*/
: (:EXP, :EXP) -> (:EXP);
and-expression: () -> (e: EXP) = {
e = maxmin-expression;
||
a = and-expression; and; b = maxmin-expression;
e = (a, b);
};
/*
* EXCLUSIVE OR EXPRESSIONS
*
* This rule describes the bitwise exclusive or expressions.
*/
: (:EXP, :EXP) -> (:EXP);
exclusive-or-expression: () -> (e: EXP) = {
e = and-expression;
||
a = exclusive-or-expression; xor; b = and-expression;
e = (a, b);
};
/*
* INCLUSIVE OR EXPRESSIONS
*
* This rule describes the bitwise inclusive or expressions.
*/
: (:EXP, :EXP) -> (:EXP);
inclusive-or-expression: () -> (e: EXP) = {
e = exclusive-or-expression;
||
a = inclusive-or-expression; or; b = exclusive-or-expression;
e = (a, b);
};
/*
* LOGICAL AND EXPRESSIONS
*
* This rule describes the logical and expressions.
*/
: (:EXP, :EXP) -> (:EXP);
logical-and-expression: () -> (e: EXP) = {
e = inclusive-or-expression;
||
a = logical-and-expression;
logical-and; b = inclusive-or-expression;
e = (a, b);
};
/*
* LOGICAL OR EXPRESSIONS
*
* This rule describes the logical or expressions.
*/
: (:EXP, :EXP) -> (:EXP);
logical-or-expression: () -> (e: EXP) = {
e = logical-and-expression;
||
a = logical-or-expression;
logical-or; b = logical-and-expression;
e = (a, b);
};
/*
* CONDITIONAL EXPRESSIONS
*
* This rule describes the conditional expressions, consisting of the
* '?:' operator.
*/
: (:EXP, :EXP, :EXP) -> (:EXP);
conditional-expression: () -> (e: EXP) = {
e = logical-or-expression;
||
c = logical-or-expression;
question; a = expression;
colon; b = conditional-expression;
e = (c, a, b);
};
/*
* ASSIGNMENT EXPRESSIONS
*
* These rules describe the assignment expressions. These include both
* simple assignment and the 'operate and becomes' operators like '+='.
*/
: (:EXP, :EXP) -> (:EXP);
: (:LEX, :EXP, :EXP) -> (:EXP);
assignment-operator: () -> () = {
and-eq;
|| div-eq;
|| lshift-eq;
|| minus-eq;
|| or-eq;
|| plus-eq;
|| rem-eq;
|| rshift-eq;
|| star-eq;
|| xor-eq;
};
assignment-expression: () -> (e: EXP) = {
e = conditional-expression;
||
a = unary-expression;
assign; b = assignment-expression;
e = (a, b);
||
a = unary-expression;
op = ; assignment-operator;
b = assignment-expression;
e = (op, a, b);
};
expression-entry: () -> (e: EXP) = {
e = assignment-expression;
##
;
e = ;
};
/*
* FLOW ANALYSIS EXPRESSIONS (EXTENSION)
*
* This rule describes the flow analysis expressions, which are an
* extension to the standard syntax. These consist of the assignment
* expressions, plus operations for setting and discarding values.
*/
: (:EXP) -> (:EXP);
: (:EXP) -> (:EXP);
flow-expression: () -> (e: EXP) = {
set; open-round; a = expression;
e = (a);
close-round;
||
unused; open-round; a = expression;
e = (a);
close-round;
};
inset-flow-expression: () -> (e: EXP) = {
inset-start; set; a = expression;
e = (a);
inset-end;
||
inset-start; unused; a = expression;
e = (a);
inset-end;
};
inset-flow-statement: () -> (e: EXP) = {
inset-start; set; a = expression;
e = (a);
semicolon; inset-end;
||
inset-start; unused; a = expression;
e = (a);
semicolon; inset-end;
};
/*
* EXPRESSIONS
*
* This rule describes the top level expressions. These are derived
* from the flow-expressions by the addition of the comma operator.
*/
: (:LIST-EXP) -> (:EXP);
comma-expression-head: () -> (e: EXP) = {
e = assignment-expression; comma;
||
e = flow-expression;
||
e = inset-flow-expression;
};
comma-expression-tail: () -> (p: LIST-EXP) = {
a = assignment-expression;
q = ;
p = (a, q);
||
a = comma-expression-head; q = comma-expression-tail;
p = (a, q);
};
expression: () -> (e: EXP) = {
e = assignment-expression;
||
a = comma-expression-head; q = comma-expression-tail;
p = (a, q);
e = (p);
};
/*
* INITIALISER EXPRESSIONS
*
* An initialiser expression consists of an assignment expression
* with all its temporary variables bound to it.
*/
initialiser-expression: () -> (e: EXP) = {
e = assignment-expression;
};
/*
* CONSTANT EXPRESSIONS
*
* This rule describes the constant expressions. Lexically these are
* identical to the conditional-expressions, but with restrictions on
* the permitted operands. Constant expressions are identified by
* evaluation - whenever a valid constant expression is encountered it
* is evaluated to give an integer literal expression.
*/
: (:EXP) -> (:EXP);
constant-expression: () -> (e: EXP) = {
a = conditional-expression;
e = (a);
};
/*
* LABELLED STATEMENTS
*
* This rule describes the labelled statements. These include the case
* and default statements as well as the simple labels. Note that the
* statements following the labels are only the first component of the
* label body. Actually imposing some structure on the labelled statements
* is the most difficult part of the statement processing.
*/
: (:EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: () -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: (:IDENTIFIER) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: () -> ();
: () -> ();
: () -> ();
statement: () -> (:EXP);
fall-check: () -> () = {
fall; ;
|| fall; semicolon; ;
|| $;
};
labelled-statement: () -> (e: EXP) = {
fall-check;
case; c = constant-expression;
a = (c);
;
colon; b = statement;
e = (a, b);
||
fall-check;
default;
a = ;
;
colon; b = statement;
e = (a, b);
||
id = any-identifier;
;
a = (id);
colon; b = statement;
e = (a, b);
};
/*
* EXPRESSION STATEMENTS
*
* This rule describes the expression statements, consisting of an optional
* expression followed by a semicolon.
*/
: (:EXP) -> (:EXP);
: () -> (:EXP);
: () -> (:BOOL);
: (:BOOL) -> ();
block-expression: () -> (e: EXP) = {
e = expression;
|| e = flow-expression;
};
expression-statement: () -> (e: EXP) = {
a = block-expression;
r = ;
e = (a);
;
semicolon;
||
a = inset-flow-statement;
r = ;
e = (a);
;
||
semicolon;
e = ;
};
/*
* COMPOUND STATEMENTS
*
* These rules describe the compound statements, consisting of a list of
* statements enclosed within braces. Note that compound statements
* automatically define a local scope.
*/
: () -> (:EXP);
: (:EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: (:EXP) -> (:BOOL);
: (:EXP) -> ();
: () -> (:EXP);
: () -> (:BOOL);
: () -> (:BOOL);
: () -> ();
declaration-statement: (:BOOL) -> (:EXP);
statement-seq-opt: (c: EXP, d: BOOL) -> (e: EXP) = {
a = statement;
b = (c, a);
db = ;
e = statement-seq-opt (b, db);
||
a = declaration-statement (d);
b = (c, a);
e = statement-seq-opt (b, d);
||
e = c;
};
compound-statement: () -> (e: EXP) = {
c = ;
open-brace;
d = (c);
a = statement-seq-opt (c, d);
close-brace;
e = (a);
;
};
function-body: () -> (e: EXP) = {
c = ;
;
open-brace;
d = (c);
b = statement-seq-opt (c, d);
r = ;
a = (b, r);
close-brace;
e = (a);
;
};
function-definition-entry: () -> (e: EXP) = {
e = function-body;
##
;
e = ;
};
/*
* LOCAL STATEMENT SCOPES
*
* Several statements, in addition to the compound statements, form local
* scopes (for example, the body of an iteration statement). This rule
* describes such scopes, the initial scope expression begin passed in as
* c to avoid predicate problems. Note that local scopes which are also
* compound statements are treated differently from other (simple)
* statements.
*/
simple-statement: () -> (:EXP);
scoped-stmt-body: (c: EXP) -> (e: EXP) = {
open-brace;
d = (c);
e = statement-seq-opt (c, d);
close-brace;
||
a = simple-statement;
e = (c, a);
};
scoped-statement: (c: EXP) -> (e: EXP) = {
a = scoped-stmt-body (c);
e = (a);
;
##
;
e = (c);
;
};
/*
* DECLARATION STATEMENTS
*
* This rule describes the (non-empty) declaration statements, consisting
* of just a declaration. See expression-statement for a discussion of
* empty statements. The look-ahead required to distinguish declaration-
* statements from expression-statements is implemented using the predicate
* is_decl_statement.
*/
: (:BOOL) -> (:BOOL);
: () -> (:EXP);
declaration: () -> ();
declaration-statement: (d: BOOL) -> (e: EXP) = {
? = (d);
declaration;
e = ;
;
};
/*
* TARGET DEPENDENT CONDITIONAL COMPILATIONS
*
* These rules describe the unresolved target dependent conditional
* compilations. Note that these must be structured, as opposed to the
* normal unstructured preprocessing directives. Any braces required
* to make the lists of statements in target dependent conditional
* bodies into compound statements are automatically inserted by the
* preprocessor.
*/
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :EXP, :EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: (:EXP) -> (:EXP);
: (:EXP) -> ();
: () -> ();
: (:EXP) -> ();
target-condition-head: () -> (e: EXP, p: EXP, r: BOOL) = {
c = hash-if;
p = (c);
r = ;
a = compound-statement;
(r);
e = (c, a);
||
(a, p, r) = target-condition-head;
c = hash-elif;
(c);
s = ;
b = compound-statement;
(r);
e = (a, c, b);
};
target-condition: () -> (e: EXP) = {
(a, p, r) = target-condition-head;
{
hash-else;
;
s = ;
b = compound-statement;
||
b = ;
};
(p);
hash-endif;
(r);
e = (a, b);
};
/*
* SELECTION STATEMENTS
*
* These rules describe the selection statements, consisting of the if
* and switch statements, plus the target dependent conditionals above.
* The way that the dangling else problem is dealt with is interesting.
* A simple optional else-block leads to an ambiguity, however an
* exception handler gives precisely what is required. To paraphrase,
* an if statement always has an associated else, except when it doesn't.
*/
: (:EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: (:EXP, :EXP) -> (:EXP);
: () -> ();
: () -> (:EXP);
: (:EXP) -> (:EXP);
: (:EXP, :EXP, :BOOL) -> (:EXP);
: () -> (:CONDITION);
: (:CONDITION) -> ();
selection-statement: () -> (e: EXP) = {
if;
x = ;
r = ;
open-round-x; c = expression;
a = (c);
close-round;
bs = ;
b = scoped-statement (bs);
(r);
d = (a, b);
{
else;
;
fs =