2 |
7u83 |
1 |
/*
|
|
|
2 |
Crown Copyright (c) 1997
|
|
|
3 |
|
|
|
4 |
This TenDRA(r) Computer Program is subject to Copyright
|
|
|
5 |
owned by the United Kingdom Secretary of State for Defence
|
|
|
6 |
acting through the Defence Evaluation and Research Agency
|
|
|
7 |
(DERA). It is made available to Recipients with a
|
|
|
8 |
royalty-free licence for its use, reproduction, transfer
|
|
|
9 |
to other parties and amendment for any purpose not excluding
|
|
|
10 |
product development provided that any such use et cetera
|
|
|
11 |
shall be deemed to be acceptance of the following conditions:-
|
|
|
12 |
|
|
|
13 |
(1) Its Recipients shall ensure that this Notice is
|
|
|
14 |
reproduced upon any copies or amended versions of it;
|
|
|
15 |
|
|
|
16 |
(2) Any amended version of it shall be clearly marked to
|
|
|
17 |
show both the nature of and the organisation responsible
|
|
|
18 |
for the relevant amendment or amendments;
|
|
|
19 |
|
|
|
20 |
(3) Its onward transfer from a recipient to another
|
|
|
21 |
party shall be deemed to be that party's acceptance of
|
|
|
22 |
these conditions;
|
|
|
23 |
|
|
|
24 |
(4) DERA gives no warranty or assurance as to its
|
|
|
25 |
quality or suitability for any purpose and DERA accepts
|
|
|
26 |
no liability whatsoever in relation to any use to which
|
|
|
27 |
it may be put.
|
|
|
28 |
*/
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
%types%
|
|
|
32 |
|
|
|
33 |
/*
|
|
|
34 |
TYPES
|
|
|
35 |
|
|
|
36 |
The types are fairly self-explanitory. Note that distinctions are
|
|
|
37 |
made in the parser type system which do not exist in the underlying
|
|
|
38 |
program.
|
|
|
39 |
*/
|
|
|
40 |
|
|
|
41 |
BOOLEAN ;
|
|
|
42 |
COMMAND ;
|
|
|
43 |
COMMAND_KEY ;
|
|
|
44 |
IDENTIFIER ;
|
|
|
45 |
STRING ;
|
|
|
46 |
SUBSET_KEY ;
|
|
|
47 |
TYPE ;
|
|
|
48 |
TYPE_KEY ;
|
|
|
49 |
TYPE_LIST ;
|
|
|
50 |
TYPE_QUAL ;
|
|
|
51 |
TYPE_SPEC ;
|
|
|
52 |
VERSION ;
|
|
|
53 |
|
|
|
54 |
|
|
|
55 |
%terminals%
|
|
|
56 |
|
|
|
57 |
/*
|
|
|
58 |
TERMINALS
|
|
|
59 |
|
|
|
60 |
The terminals are arranged in five groups; the names and strings, the
|
|
|
61 |
commands (beginning with '+'), the types, the special macro names
|
|
|
62 |
(beginning with '~'), and the punctuators and operators.
|
|
|
63 |
*/
|
|
|
64 |
|
|
|
65 |
name : () -> ( :STRING ) ;
|
|
|
66 |
number : () -> ( :STRING ) ;
|
|
|
67 |
string : () -> ( :STRING ) ;
|
|
|
68 |
variable : () -> ( :STRING ) ;
|
|
|
69 |
comment : () -> ( :STRING ) ;
|
|
|
70 |
insert : () -> ( :STRING ) ;
|
|
|
71 |
build-insert : () -> ( :STRING ) ;
|
|
|
72 |
|
|
|
73 |
base-api ; constant ; define ; else ; endif ; enumerate ; exp ;
|
|
|
74 |
field ; func ; if ; ifdef ; ifndef ; implement ; info ; macro ; nat ;
|
|
|
75 |
set ; statement ; !subset ; token ; type ; typedef ; use ;
|
|
|
76 |
|
|
|
77 |
arith ; char ; const ; double ; enum ; extern ; float ; int ; long ;
|
|
|
78 |
lvalue ; scalar ; short ; signed ; struct ; union ; unsigned ; void ;
|
|
|
79 |
volatile ; weak ;
|
|
|
80 |
|
|
|
81 |
building ; promote ; protect ; special ;
|
|
|
82 |
|
|
|
83 |
open-brace ; close-brace ; open-round ; close-round ; open-square ;
|
|
|
84 |
close-square ; assign ; colon ; comma ; dot ; !dot-dot ; ellipsis ;
|
|
|
85 |
equal ; exclaim ; minus ; or ; question ; semicolon ; star ; eof ;
|
|
|
86 |
!unknown ;
|
|
|
87 |
|
|
|
88 |
|
|
|
89 |
%productions%
|
|
|
90 |
|
|
|
91 |
|
|
|
92 |
/*
|
|
|
93 |
BUILT-IN TYPES
|
|
|
94 |
|
|
|
95 |
These rules describe the built-in types. Illegal combinations of
|
|
|
96 |
keywords are detected by the action <type_builtin>.
|
|
|
97 |
*/
|
|
|
98 |
|
|
|
99 |
<btype_char> : () -> ( :TYPE_SPEC ) ;
|
|
|
100 |
<btype_short> : () -> ( :TYPE_SPEC ) ;
|
|
|
101 |
<btype_int> : () -> ( :TYPE_SPEC ) ;
|
|
|
102 |
<btype_long> : () -> ( :TYPE_SPEC ) ;
|
|
|
103 |
<btype_signed> : () -> ( :TYPE_SPEC ) ;
|
|
|
104 |
<btype_unsigned> : () -> ( :TYPE_SPEC ) ;
|
|
|
105 |
<btype_float> : () -> ( :TYPE_SPEC ) ;
|
|
|
106 |
<btype_double> : () -> ( :TYPE_SPEC ) ;
|
|
|
107 |
<btype_void> : () -> ( :TYPE_SPEC ) ;
|
|
|
108 |
<btype_join> : ( :TYPE_SPEC, :TYPE_SPEC ) -> ( :TYPE_SPEC ) ;
|
|
|
109 |
|
|
|
110 |
type-keyword : () -> ( b : TYPE_SPEC ) = {
|
|
|
111 |
char ; b = <btype_char> ;
|
|
|
112 |
|| short ; b = <btype_short> ;
|
|
|
113 |
|| int ; b = <btype_int> ;
|
|
|
114 |
|| long ; b = <btype_long> ;
|
|
|
115 |
|| signed ; b = <btype_signed> ;
|
|
|
116 |
|| unsigned ; b = <btype_unsigned> ;
|
|
|
117 |
|| float ; b = <btype_float> ;
|
|
|
118 |
|| double ; b = <btype_double> ;
|
|
|
119 |
|| void ; b = <btype_void> ;
|
|
|
120 |
} ;
|
|
|
121 |
|
|
|
122 |
builtin-type : () -> ( b : TYPE_SPEC ) = {
|
|
|
123 |
a = type-keyword ;
|
|
|
124 |
{
|
|
|
125 |
d = builtin-type ; c = <btype_join> ( a, d ) ;
|
|
|
126 |
|| c = a ;
|
|
|
127 |
} ;
|
|
|
128 |
b = c ;
|
|
|
129 |
} ;
|
|
|
130 |
|
|
|
131 |
|
|
|
132 |
/*
|
|
|
133 |
SIMPLE TYPES
|
|
|
134 |
|
|
|
135 |
These rules describes the simple, unqualified, types.
|
|
|
136 |
*/
|
|
|
137 |
|
|
|
138 |
<type_builtin> : ( :TYPE_SPEC ) -> ( :TYPE ) ;
|
|
|
139 |
<type_name> : ( :STRING, :TYPE_KEY ) -> ( :TYPE ) ;
|
|
|
140 |
<key_type> : () -> ( :TYPE_KEY ) ;
|
|
|
141 |
<key_struct_tag> : () -> ( :TYPE_KEY ) ;
|
|
|
142 |
<key_union_tag> : () -> ( :TYPE_KEY ) ;
|
|
|
143 |
<key_enum_tag> : () -> ( :TYPE_KEY ) ;
|
|
|
144 |
|
|
|
145 |
type-key : () -> ( tag : TYPE_KEY ) = {
|
|
|
146 |
tag = <key_type> ;
|
|
|
147 |
|| struct ; tag = <key_struct_tag> ;
|
|
|
148 |
|| union ; tag = <key_union_tag> ;
|
|
|
149 |
|| enum ; tag = <key_enum_tag> ;
|
|
|
150 |
} ;
|
|
|
151 |
|
|
|
152 |
simple-type : () -> ( t : TYPE ) = {
|
|
|
153 |
b = builtin-type ;
|
|
|
154 |
t = <type_builtin> ( b ) ;
|
|
|
155 |
||
|
|
|
156 |
tag = type-key ; nm = name ;
|
|
|
157 |
t = <type_name> ( nm, tag ) ;
|
|
|
158 |
} ;
|
|
|
159 |
|
|
|
160 |
|
|
|
161 |
/*
|
|
|
162 |
QUALIFIED TYPES
|
|
|
163 |
|
|
|
164 |
These rules describe the type qualifiers and the qualified types.
|
|
|
165 |
*/
|
|
|
166 |
|
|
|
167 |
<cv_none> : () -> ( :TYPE_QUAL ) ;
|
|
|
168 |
<cv_const> : ( :TYPE_QUAL ) -> ( :TYPE_QUAL ) ;
|
|
|
169 |
<cv_volatile> : ( :TYPE_QUAL ) -> ( :TYPE_QUAL ) ;
|
|
|
170 |
<type_qualify> : ( :TYPE, :TYPE_QUAL ) -> ( :TYPE ) ;
|
|
|
171 |
|
|
|
172 |
type-qualifier : () -> ( :TYPE_QUAL ) ;
|
|
|
173 |
|
|
|
174 |
type-qualifier-opt : () -> ( cv : TYPE_QUAL ) = {
|
|
|
175 |
cv = <cv_none> ;
|
|
|
176 |
|| cv = type-qualifier ;
|
|
|
177 |
} ;
|
|
|
178 |
|
|
|
179 |
type-qualifier : () -> ( cv : TYPE_QUAL ) = {
|
|
|
180 |
const ; a = type-qualifier-opt ;
|
|
|
181 |
cv = <cv_const> ( a ) ;
|
|
|
182 |
||
|
|
|
183 |
volatile ; a = type-qualifier-opt ;
|
|
|
184 |
cv = <cv_volatile> ( a ) ;
|
|
|
185 |
} ;
|
|
|
186 |
|
|
|
187 |
qualified-type : () -> ( t : TYPE ) = {
|
|
|
188 |
t = simple-type ;
|
|
|
189 |
||
|
|
|
190 |
cv = type-qualifier ; s = simple-type ;
|
|
|
191 |
t = <type_qualify> ( s, cv ) ;
|
|
|
192 |
||
|
|
|
193 |
s = simple-type ; cv = type-qualifier ;
|
|
|
194 |
t = <type_qualify> ( s, cv ) ;
|
|
|
195 |
} ;
|
|
|
196 |
|
|
|
197 |
|
|
|
198 |
/*
|
|
|
199 |
LVALUE QUALIFIERS
|
|
|
200 |
|
|
|
201 |
This rule describes the lvalue and rvalue type qualifiers.
|
|
|
202 |
*/
|
|
|
203 |
|
|
|
204 |
<key_rvalue> : () -> ( :TYPE_KEY ) ;
|
|
|
205 |
<key_lvalue> : () -> ( :TYPE_KEY ) ;
|
|
|
206 |
|
|
|
207 |
object-qualifier : () -> ( lv : TYPE_KEY ) = {
|
|
|
208 |
lvalue ; lv = <key_lvalue> ;
|
|
|
209 |
|| lv = <key_rvalue> ;
|
|
|
210 |
} ;
|
|
|
211 |
|
|
|
212 |
|
|
|
213 |
/*
|
|
|
214 |
CONSTANT EXPRESSIONS
|
|
|
215 |
|
|
|
216 |
This rule describes the constant expressions. These comprise the
|
|
|
217 |
numbers, the NAT token names, plus some simple operations on these
|
|
|
218 |
values. More complex expressions can be expressed using an insert.
|
|
|
219 |
*/
|
|
|
220 |
|
|
|
221 |
<value_none> : () -> ( :STRING ) ;
|
|
|
222 |
<value_nat> : ( :STRING ) -> ( :STRING ) ;
|
|
|
223 |
<value_not> : ( :STRING ) -> ( :STRING ) ;
|
|
|
224 |
<value_negate> : ( :STRING ) -> ( :STRING ) ;
|
|
|
225 |
|
|
|
226 |
constant-value : () -> ( s : STRING ) = {
|
|
|
227 |
s = number ;
|
|
|
228 |
|| s = insert ;
|
|
|
229 |
|| a = name ; s = <value_nat> ( a ) ;
|
|
|
230 |
|| minus ; a = constant-value ; s = <value_negate> ( a ) ;
|
|
|
231 |
|| exclaim ; a = constant-value ; s = <value_not> ( a ) ;
|
|
|
232 |
} ;
|
|
|
233 |
|
|
|
234 |
|
|
|
235 |
/*
|
|
|
236 |
POINTER TYPE OPERATOR
|
|
|
237 |
|
|
|
238 |
This rule describes the pointer type operator.
|
|
|
239 |
*/
|
|
|
240 |
|
|
|
241 |
<type_ptr> : ( :TYPE_QUAL ) -> ( :TYPE ) ;
|
|
|
242 |
|
|
|
243 |
ptr-operator : () -> ( t : TYPE ) = {
|
|
|
244 |
star ; cv = type-qualifier-opt ;
|
|
|
245 |
t = <type_ptr> ( cv ) ;
|
|
|
246 |
} ;
|
|
|
247 |
|
|
|
248 |
|
|
|
249 |
/*
|
|
|
250 |
ARRAY TYPE OPERATOR
|
|
|
251 |
|
|
|
252 |
This rule describes the array type operator.
|
|
|
253 |
*/
|
|
|
254 |
|
|
|
255 |
<type_array> : ( :STRING ) -> ( :TYPE ) ;
|
|
|
256 |
|
|
|
257 |
array-operator : () -> ( t : TYPE ) = {
|
|
|
258 |
open-square ;
|
|
|
259 |
{
|
|
|
260 |
a = constant-value ;
|
|
|
261 |
|| a = <value_none> ;
|
|
|
262 |
} ;
|
|
|
263 |
close-square ;
|
|
|
264 |
t = <type_array> ( a ) ;
|
|
|
265 |
} ;
|
|
|
266 |
|
|
|
267 |
|
|
|
268 |
/*
|
|
|
269 |
BITFIELD TYPE OPERATOR
|
|
|
270 |
|
|
|
271 |
This rule describes the bitfield type operator.
|
|
|
272 |
*/
|
|
|
273 |
|
|
|
274 |
<type_bitfield> : ( :STRING ) -> ( :TYPE ) ;
|
|
|
275 |
|
|
|
276 |
bitfield-operator : () -> ( t : TYPE ) = {
|
|
|
277 |
colon ; a = constant-value ;
|
|
|
278 |
t = <type_bitfield> ( a ) ;
|
|
|
279 |
} ;
|
|
|
280 |
|
|
|
281 |
|
|
|
282 |
/*
|
|
|
283 |
FUNCTION TYPE OPERATOR
|
|
|
284 |
|
|
|
285 |
These rules describe the function type operator.
|
|
|
286 |
*/
|
|
|
287 |
|
|
|
288 |
<type_func> : ( :TYPE_LIST ) -> ( :TYPE ) ;
|
|
|
289 |
<type_inject> : ( :TYPE, :TYPE ) -> ( :TYPE ) ;
|
|
|
290 |
<type_list_none> : () -> ( :TYPE_LIST ) ;
|
|
|
291 |
<type_list_empty> : () -> ( :TYPE_LIST ) ;
|
|
|
292 |
<type_list_ellipsis> : () -> ( :TYPE_LIST ) ;
|
|
|
293 |
<type_list_cons> : ( :TYPE, :TYPE_LIST ) -> ( :TYPE_LIST ) ;
|
|
|
294 |
<param_name> : ( :STRING ) -> () ;
|
|
|
295 |
abstract-declarator : () -> ( :STRING, :TYPE ) ;
|
|
|
296 |
|
|
|
297 |
parameter-declaration : () -> ( t : TYPE ) = {
|
|
|
298 |
s = qualified-type ; ( nm, p ) = abstract-declarator ;
|
|
|
299 |
t = <type_inject> ( p, s ) ;
|
|
|
300 |
<param_name> ( nm ) ;
|
|
|
301 |
} ;
|
|
|
302 |
|
|
|
303 |
parameter-list : () -> ( p : TYPE_LIST ) = {
|
|
|
304 |
t = parameter-declaration ;
|
|
|
305 |
{
|
|
|
306 |
comma ; q = parameter-list ;
|
|
|
307 |
|| comma ; ellipsis ; q = <type_list_ellipsis> ;
|
|
|
308 |
|| q = <type_list_none> ;
|
|
|
309 |
} ;
|
|
|
310 |
p = <type_list_cons> ( t, q ) ;
|
|
|
311 |
} ;
|
|
|
312 |
|
|
|
313 |
function-operator : () -> ( t : TYPE ) = {
|
|
|
314 |
open-round ; p = parameter-list ; close-round ;
|
|
|
315 |
t = <type_func> ( p ) ;
|
|
|
316 |
||
|
|
|
317 |
open-round ; close-round ;
|
|
|
318 |
p = <type_list_empty> ;
|
|
|
319 |
t = <type_func> ( p ) ;
|
|
|
320 |
} ;
|
|
|
321 |
|
|
|
322 |
|
|
|
323 |
/*
|
|
|
324 |
MACRO TYPE OPERATOR
|
|
|
325 |
|
|
|
326 |
These rules describe the macro type operator. This is similar to the
|
|
|
327 |
function type operator except that each parameter may be specified
|
|
|
328 |
as an lvalue and there are no ellipsis parameters.
|
|
|
329 |
*/
|
|
|
330 |
|
|
|
331 |
<type_lvalue> : ( :TYPE, :TYPE_KEY ) -> ( :TYPE ) ;
|
|
|
332 |
<type_macro> : ( :TYPE_LIST ) -> ( :TYPE ) ;
|
|
|
333 |
|
|
|
334 |
macro-param-declaration : () -> ( t : TYPE ) = {
|
|
|
335 |
lv = object-qualifier ;
|
|
|
336 |
s = qualified-type ; ( nm, p ) = abstract-declarator ;
|
|
|
337 |
u = <type_inject> ( p, s ) ;
|
|
|
338 |
t = <type_lvalue> ( u, lv ) ;
|
|
|
339 |
<param_name> ( nm ) ;
|
|
|
340 |
} ;
|
|
|
341 |
|
|
|
342 |
macro-param-list : () -> ( p : TYPE_LIST ) = {
|
|
|
343 |
t = macro-param-declaration ;
|
|
|
344 |
{
|
|
|
345 |
comma ; q = macro-param-list ;
|
|
|
346 |
|| q = <type_list_none> ;
|
|
|
347 |
} ;
|
|
|
348 |
p = <type_list_cons> ( t, q ) ;
|
|
|
349 |
} ;
|
|
|
350 |
|
|
|
351 |
macro-operator : () -> ( t : TYPE ) = {
|
|
|
352 |
open-round ; p = macro-param-list ; close-round ;
|
|
|
353 |
t = <type_macro> ( p ) ;
|
|
|
354 |
||
|
|
|
355 |
open-round ; close-round ;
|
|
|
356 |
p = <type_list_none> ;
|
|
|
357 |
t = <type_macro> ( p ) ;
|
|
|
358 |
} ;
|
|
|
359 |
|
|
|
360 |
|
|
|
361 |
/*
|
|
|
362 |
MACRO DEFINITION PARAMETER LISTS
|
|
|
363 |
|
|
|
364 |
These rules describe the macro definition parameter lists. These
|
|
|
365 |
comprise a simple list of identifier names.
|
|
|
366 |
*/
|
|
|
367 |
|
|
|
368 |
<param_none> : () -> ( :STRING ) ;
|
|
|
369 |
<param_empty> : () -> ( :STRING ) ;
|
|
|
370 |
<param_join> : ( :STRING, :STRING ) -> ( :STRING ) ;
|
|
|
371 |
|
|
|
372 |
define-param-list : () -> ( p : STRING ) = {
|
|
|
373 |
n = name ; comma ; q = define-param-list ;
|
|
|
374 |
p = <param_join> ( n, q ) ;
|
|
|
375 |
||
|
|
|
376 |
p = name ;
|
|
|
377 |
} ;
|
|
|
378 |
|
|
|
379 |
define-param-clause : () -> ( p : STRING ) = {
|
|
|
380 |
open-round ; p = define-param-list ; close-round ;
|
|
|
381 |
|| open-round ; close-round ; p = <param_empty> ;
|
|
|
382 |
|| p = <param_none> ;
|
|
|
383 |
} ;
|
|
|
384 |
|
|
|
385 |
|
|
|
386 |
/*
|
|
|
387 |
OBJECT DECLARATORS
|
|
|
388 |
|
|
|
389 |
These rules describe the object declarators. These consist of an
|
|
|
390 |
identifier qualified using pointer, array and function type
|
|
|
391 |
operators.
|
|
|
392 |
*/
|
|
|
393 |
|
|
|
394 |
<type_none> : () -> ( :TYPE ) ;
|
|
|
395 |
declarator : () -> ( :IDENTIFIER, :TYPE ) ;
|
|
|
396 |
identifier : () -> ( :IDENTIFIER ) ;
|
|
|
397 |
|
|
|
398 |
direct-declarator : () -> ( id : IDENTIFIER, t : TYPE ) = {
|
|
|
399 |
id = identifier ; t = <type_none> ;
|
|
|
400 |
||
|
|
|
401 |
( id, p ) = direct-declarator ; s = function-operator ;
|
|
|
402 |
t = <type_inject> ( p, s ) ;
|
|
|
403 |
||
|
|
|
404 |
( id, p ) = direct-declarator ; s = array-operator ;
|
|
|
405 |
t = <type_inject> ( p, s ) ;
|
|
|
406 |
||
|
|
|
407 |
open-round ; ( id, t ) = declarator ; close-round ;
|
|
|
408 |
} ;
|
|
|
409 |
|
|
|
410 |
declarator : () -> ( id : IDENTIFIER, t : TYPE ) = {
|
|
|
411 |
( id, t ) = direct-declarator ;
|
|
|
412 |
||
|
|
|
413 |
p = ptr-operator ; ( id, s ) = declarator ;
|
|
|
414 |
t = <type_inject> ( s, p ) ;
|
|
|
415 |
} ;
|
|
|
416 |
|
|
|
417 |
|
|
|
418 |
/*
|
|
|
419 |
MACRO DECLARATORS
|
|
|
420 |
|
|
|
421 |
These rules describe the macro declarators. These are a restricted
|
|
|
422 |
subset of the declarators in which only pointer operators are allowed.
|
|
|
423 |
*/
|
|
|
424 |
|
|
|
425 |
macro-declarator : () -> ( id : IDENTIFIER, t : TYPE ) = {
|
|
|
426 |
id = identifier ; t = <type_none> ;
|
|
|
427 |
||
|
|
|
428 |
p = ptr-operator ; ( id, s ) = macro-declarator ;
|
|
|
429 |
t = <type_inject> ( s, p ) ;
|
|
|
430 |
} ;
|
|
|
431 |
|
|
|
432 |
|
|
|
433 |
/*
|
|
|
434 |
ABSTRACT DECLARATORS
|
|
|
435 |
|
|
|
436 |
These rules describe the abstract declarators, as used in function
|
|
|
437 |
parameter declarations. For simplicity, the case of a list of
|
|
|
438 |
function parameters without a declarator has been omitted; function
|
|
|
439 |
parameters should be pointers to functions, rather than functions,
|
|
|
440 |
anyway.
|
|
|
441 |
*/
|
|
|
442 |
|
|
|
443 |
<name_none> : () -> ( :STRING ) ;
|
|
|
444 |
|
|
|
445 |
direct-abstract-declarator : () -> ( nm : STRING, t : TYPE ) = {
|
|
|
446 |
nm = <name_none> ; t = <type_none> ;
|
|
|
447 |
||
|
|
|
448 |
nm = name ; t = <type_none> ;
|
|
|
449 |
||
|
|
|
450 |
( nm, p ) = direct-abstract-declarator ; s = array-operator ;
|
|
|
451 |
t = <type_inject> ( p, s ) ;
|
|
|
452 |
||
|
|
|
453 |
open-round ; ( nm, t ) = abstract-declarator ; close-round ;
|
|
|
454 |
||
|
|
|
455 |
open-round ; ( nm, p ) = abstract-declarator ; close-round ;
|
|
|
456 |
s = function-operator ;
|
|
|
457 |
t = <type_inject> ( p, s ) ;
|
|
|
458 |
} ;
|
|
|
459 |
|
|
|
460 |
abstract-declarator : () -> ( nm : STRING, t : TYPE ) = {
|
|
|
461 |
( nm, t ) = direct-abstract-declarator ;
|
|
|
462 |
||
|
|
|
463 |
p = ptr-operator ; ( nm, s ) = abstract-declarator ;
|
|
|
464 |
t = <type_inject> ( s, p ) ;
|
|
|
465 |
} ;
|
|
|
466 |
|
|
|
467 |
|
|
|
468 |
/*
|
|
|
469 |
IDENTIFIER NAMES
|
|
|
470 |
|
|
|
471 |
These rules describe the identifier names. These comprise the actual
|
|
|
472 |
internal name, plus an optional external name (the external and internal
|
|
|
473 |
names are equal if this is not given). Either name may have an
|
|
|
474 |
associated version number.
|
|
|
475 |
*/
|
|
|
476 |
|
|
|
477 |
<field_name> : ( :STRING ) -> ( :STRING ) ;
|
|
|
478 |
<token_name> : ( :STRING ) -> ( :STRING ) ;
|
|
|
479 |
<version_none> : () -> ( :VERSION ) ;
|
|
|
480 |
<version_number> : ( :STRING ) -> ( :VERSION ) ;
|
|
|
481 |
<make_id> : ( :STRING, :VERSION, :STRING, :VERSION ) -> ( :IDENTIFIER ) ;
|
|
|
482 |
|
|
|
483 |
name-version : () -> ( v : VERSION ) = {
|
|
|
484 |
dot ; n = number ; v = <version_number> ( n ) ;
|
|
|
485 |
|| v = <version_none> ;
|
|
|
486 |
} ;
|
|
|
487 |
|
|
|
488 |
internal-name : () -> ( nm : STRING, v : VERSION ) = {
|
|
|
489 |
a = name ; v = name-version ;
|
|
|
490 |
nm = <field_name> ( a ) ;
|
|
|
491 |
} ;
|
|
|
492 |
|
|
|
493 |
external-name : () -> ( nm : STRING, v : VERSION ) = {
|
|
|
494 |
a = name ; v = name-version ;
|
|
|
495 |
b = <field_name> ( a ) ;
|
|
|
496 |
nm = <token_name> ( b ) ;
|
|
|
497 |
||
|
|
|
498 |
nm = string ; v = name-version ;
|
|
|
499 |
} ;
|
|
|
500 |
|
|
|
501 |
identifier : () -> ( id : IDENTIFIER ) = {
|
|
|
502 |
( nm, v ) = internal-name ;
|
|
|
503 |
tnm = <token_name> ( nm ) ;
|
|
|
504 |
id = <make_id> ( nm, v, tnm, v ) ;
|
|
|
505 |
||
|
|
|
506 |
( nm, v ) = internal-name ; or ; ( tnm, tv ) = external-name ;
|
|
|
507 |
id = <make_id> ( nm, v, tnm, tv ) ;
|
|
|
508 |
} ;
|
|
|
509 |
|
|
|
510 |
|
|
|
511 |
/*
|
|
|
512 |
SUBSET NAMES
|
|
|
513 |
|
|
|
514 |
These rules describe the specification subset names. These consist
|
|
|
515 |
of between one and three components, giving the API name, the header
|
|
|
516 |
file within that API, and the subset of that header.
|
|
|
517 |
*/
|
|
|
518 |
|
|
|
519 |
<cmd_implement> : () -> ( :COMMAND_KEY ) ;
|
|
|
520 |
<cmd_use> : () -> ( :COMMAND_KEY ) ;
|
|
|
521 |
<api_name> : ( :STRING ) -> ( :STRING ) ;
|
|
|
522 |
<file_name> : ( :STRING, :STRING ) -> ( :STRING ) ;
|
|
|
523 |
<subset_name> : ( :STRING, :STRING, :STRING ) -> ( :STRING ) ;
|
|
|
524 |
|
|
|
525 |
implement-command : () -> ( cmd : COMMAND_KEY ) = {
|
|
|
526 |
implement ; cmd = <cmd_implement> ;
|
|
|
527 |
|| use ; cmd = <cmd_use> ;
|
|
|
528 |
} ;
|
|
|
529 |
|
|
|
530 |
subset-name : () -> ( s : STRING ) = {
|
|
|
531 |
a = string ;
|
|
|
532 |
s = <api_name> ( a ) ;
|
|
|
533 |
||
|
|
|
534 |
a = string ; comma ; b = string ;
|
|
|
535 |
s = <file_name> ( a, b ) ;
|
|
|
536 |
||
|
|
|
537 |
a = string ; comma ; b = string ; comma ; c = string ;
|
|
|
538 |
s = <subset_name> ( a, b, c ) ;
|
|
|
539 |
} ;
|
|
|
540 |
|
|
|
541 |
use-subset-name : () -> ( s : STRING ) = {
|
|
|
542 |
open-round ; a = string ; close-round ; comma ; b = string ;
|
|
|
543 |
s = <file_name> ( a, b ) ;
|
|
|
544 |
} ;
|
|
|
545 |
|
|
|
546 |
|
|
|
547 |
/*
|
|
|
548 |
SUBSET USAGE KEYS
|
|
|
549 |
|
|
|
550 |
This rule describes the subset usage keys. These are used to indicate
|
|
|
551 |
whether a file inclusion refers to the specification output, the
|
|
|
552 |
library building output, or both.
|
|
|
553 |
*/
|
|
|
554 |
|
|
|
555 |
<subset_none> : () -> ( :SUBSET_KEY ) ;
|
|
|
556 |
<subset_first> : () -> ( :SUBSET_KEY ) ;
|
|
|
557 |
<subset_second> : () -> ( :SUBSET_KEY ) ;
|
|
|
558 |
<subset_both> : () -> ( :SUBSET_KEY ) ;
|
|
|
559 |
<subset_next> : ( :SUBSET_KEY ) -> ( :SUBSET_KEY ) ;
|
|
|
560 |
|
|
|
561 |
subset-key : () -> ( key : SUBSET_KEY ) = {
|
|
|
562 |
key = <subset_both> ;
|
|
|
563 |
||
|
|
|
564 |
open-round ; question ; question ; close-round ;
|
|
|
565 |
key = <subset_none> ;
|
|
|
566 |
||
|
|
|
567 |
open-round ; exclaim ; question ; close-round ;
|
|
|
568 |
key = <subset_first> ;
|
|
|
569 |
||
|
|
|
570 |
open-round ; question ; exclaim ; close-round ;
|
|
|
571 |
key = <subset_second> ;
|
|
|
572 |
||
|
|
|
573 |
open-round ; exclaim ; exclaim ; close-round ;
|
|
|
574 |
key = <subset_both> ;
|
|
|
575 |
} ;
|
|
|
576 |
|
|
|
577 |
|
|
|
578 |
/*
|
|
|
579 |
CONDITIONAL COMPILATION COMMANDS
|
|
|
580 |
|
|
|
581 |
These rules describe the conditional compilation commands.
|
|
|
582 |
*/
|
|
|
583 |
|
|
|
584 |
<cond_building> : () -> ( :STRING ) ;
|
|
|
585 |
<cond_protect> : ( :STRING, :STRING ) -> ( :STRING ) ;
|
|
|
586 |
<command_if> : ( :STRING ) -> ( :COMMAND ) ;
|
|
|
587 |
<command_ifdef> : ( :STRING ) -> ( :COMMAND ) ;
|
|
|
588 |
<command_ifndef> : ( :STRING ) -> ( :COMMAND ) ;
|
|
|
589 |
<command_endif> : ( :COMMAND, :STRING, :COMMAND, :COMMAND ) -> ( :COMMAND ) ;
|
|
|
590 |
|
|
|
591 |
ifdef-macro-name : () -> ( c : STRING ) = {
|
|
|
592 |
c = name ;
|
|
|
593 |
||
|
|
|
594 |
building ;
|
|
|
595 |
c = <cond_building> ;
|
|
|
596 |
||
|
|
|
597 |
protect ;
|
|
|
598 |
open-round ; a = string ; comma ; b = string ; close-round ;
|
|
|
599 |
c = <cond_protect> ( a, b ) ;
|
|
|
600 |
} ;
|
|
|
601 |
|
|
|
602 |
if-command : () -> ( c : COMMAND, s : STRING ) = {
|
|
|
603 |
if ; s = constant-value ;
|
|
|
604 |
c = <command_if> ( s ) ;
|
|
|
605 |
||
|
|
|
606 |
ifdef ; s = ifdef-macro-name ;
|
|
|
607 |
c = <command_ifdef> ( s ) ;
|
|
|
608 |
||
|
|
|
609 |
ifndef ; s = ifdef-macro-name ;
|
|
|
610 |
c = <command_ifndef> ( s ) ;
|
|
|
611 |
} ;
|
|
|
612 |
|
|
|
613 |
|
|
|
614 |
/*
|
|
|
615 |
ENUMERATION COMMANDS
|
|
|
616 |
|
|
|
617 |
These rules describe the enumeration commands. Each enumeration type
|
|
|
618 |
consists of a list of enumerator namess, each of which may be associated
|
|
|
619 |
with a value.
|
|
|
620 |
*/
|
|
|
621 |
|
|
|
622 |
<command_none> : () -> ( :COMMAND ) ;
|
|
|
623 |
<command_join> : ( :COMMAND, :COMMAND ) -> ( :COMMAND ) ;
|
|
|
624 |
<declare_enumerator> : ( :IDENTIFIER, :STRING ) -> ( :COMMAND ) ;
|
|
|
625 |
<key_enum> : () -> ( :TYPE_KEY ) ;
|
|
|
626 |
|
|
|
627 |
enum-command : () -> ( tag : TYPE_KEY ) = {
|
|
|
628 |
tag = <key_enum> ;
|
|
|
629 |
|| enum ; tag = <key_enum_tag> ;
|
|
|
630 |
} ;
|
|
|
631 |
|
|
|
632 |
enumerator : () -> ( c : COMMAND ) = {
|
|
|
633 |
id = identifier ;
|
|
|
634 |
{
|
|
|
635 |
equal ; s = constant-value ;
|
|
|
636 |
|| s = <value_none> ;
|
|
|
637 |
} ;
|
|
|
638 |
c = <declare_enumerator> ( id, s ) ;
|
|
|
639 |
} ;
|
|
|
640 |
|
|
|
641 |
enumerator-list : () -> ( c : COMMAND ) = {
|
|
|
642 |
a = enumerator ;
|
|
|
643 |
{
|
|
|
644 |
comma ; b = enumerator-list ;
|
|
|
645 |
|| b = <command_none> ;
|
|
|
646 |
} ;
|
|
|
647 |
c = <command_join> ( a, b ) ;
|
|
|
648 |
} ;
|
|
|
649 |
|
|
|
650 |
|
|
|
651 |
/*
|
|
|
652 |
EXPRESSION COMMANDS
|
|
|
653 |
|
|
|
654 |
These rules describe the expression commands. Each expression command
|
|
|
655 |
consists of an lvalue specifier, a qualified type plus a list of
|
|
|
656 |
declarators.
|
|
|
657 |
*/
|
|
|
658 |
|
|
|
659 |
<cmd_constant> : () -> ( :COMMAND_KEY ) ;
|
|
|
660 |
<cmd_exp> : () -> ( :COMMAND_KEY ) ;
|
|
|
661 |
<cmd_exp_extern> : () -> ( :COMMAND_KEY ) ;
|
|
|
662 |
<declare_exp> : ( :COMMAND_KEY, :IDENTIFIER, :TYPE ) -> ( :COMMAND ) ;
|
|
|
663 |
|
|
|
664 |
exp-command : () -> ( cmd : COMMAND_KEY ) = {
|
|
|
665 |
constant ; cmd = <cmd_constant> ;
|
|
|
666 |
|| exp ; cmd = <cmd_exp> ;
|
|
|
667 |
|| exp ; open-round ; const ; close-round ; cmd = <cmd_constant> ;
|
|
|
668 |
|| exp ; open-round ; extern ; close-round ; cmd = <cmd_exp_extern> ;
|
|
|
669 |
} ;
|
|
|
670 |
|
|
|
671 |
exp-declarator-list : ( cmd : COMMAND_KEY, s : TYPE, lv : TYPE_KEY )
|
|
|
672 |
-> ( c : COMMAND ) = {
|
|
|
673 |
( id, p ) = declarator ;
|
|
|
674 |
u = <type_inject> ( p, s ) ;
|
|
|
675 |
t = <type_lvalue> ( u, lv ) ;
|
|
|
676 |
a = <declare_exp> ( cmd, id, t ) ;
|
|
|
677 |
{
|
|
|
678 |
comma ; b = exp-declarator-list ( cmd, s, lv ) ;
|
|
|
679 |
|| b = <command_none> ;
|
|
|
680 |
} ;
|
|
|
681 |
c = <command_join> ( a, b ) ;
|
|
|
682 |
} ;
|
|
|
683 |
|
|
|
684 |
|
|
|
685 |
/*
|
|
|
686 |
FIELD COMMANDS
|
|
|
687 |
|
|
|
688 |
These rules describe the field commands. Each field consists of a
|
|
|
689 |
qualified type and a list of declarators. Conditional compilation
|
|
|
690 |
of fields is allowed.
|
|
|
691 |
*/
|
|
|
692 |
|
|
|
693 |
<bool_true> : () -> ( :BOOLEAN ) ;
|
|
|
694 |
<bool_false> : () -> ( :BOOLEAN ) ;
|
|
|
695 |
<id_anon> : () -> ( :IDENTIFIER ) ;
|
|
|
696 |
<declare_field> : ( :IDENTIFIER, :TYPE, :TYPE ) -> ( :COMMAND ) ;
|
|
|
697 |
|
|
|
698 |
field-exact : () -> ( e : BOOLEAN ) = {
|
|
|
699 |
assign ; e = <bool_true> ;
|
|
|
700 |
|| e = <bool_false> ;
|
|
|
701 |
} ;
|
|
|
702 |
|
|
|
703 |
field-declarator : () -> ( id : IDENTIFIER, t : TYPE ) = {
|
|
|
704 |
( id, t ) = declarator ;
|
|
|
705 |
||
|
|
|
706 |
id = identifier ; t = bitfield-operator ;
|
|
|
707 |
||
|
|
|
708 |
t = bitfield-operator ; id = <id_anon> ;
|
|
|
709 |
} ;
|
|
|
710 |
|
|
|
711 |
field-declarator-list : ( m : TYPE, s : TYPE ) -> ( c : COMMAND ) = {
|
|
|
712 |
( id, p ) = field-declarator ;
|
|
|
713 |
t = <type_inject> ( p, s ) ;
|
|
|
714 |
a = <declare_field> ( id, m, t ) ;
|
|
|
715 |
{
|
|
|
716 |
comma ; b = field-declarator-list ( m, s ) ;
|
|
|
717 |
|| b = <command_none> ;
|
|
|
718 |
} ;
|
|
|
719 |
c = <command_join> ( a, b ) ;
|
|
|
720 |
} ;
|
|
|
721 |
|
|
|
722 |
field-list : ( m : TYPE ) -> ( c : COMMAND ) = {
|
|
|
723 |
c = <command_none> ;
|
|
|
724 |
||
|
|
|
725 |
t = qualified-type ;
|
|
|
726 |
a = field-declarator-list ( m, t ) ; semicolon ;
|
|
|
727 |
b = field-list ( m ) ;
|
|
|
728 |
c = <command_join> ( a, b ) ;
|
|
|
729 |
||
|
|
|
730 |
( i, s ) = if-command ;
|
|
|
731 |
a = field-list ( m ) ;
|
|
|
732 |
{
|
|
|
733 |
else ; b = field-list ( m ) ;
|
|
|
734 |
|| b = <command_none> ;
|
|
|
735 |
} ;
|
|
|
736 |
endif ;
|
|
|
737 |
c1 = <command_endif> ( i, s, a, b ) ;
|
|
|
738 |
c2 = field-list ( m ) ;
|
|
|
739 |
c = <command_join> ( c1, c2 ) ;
|
|
|
740 |
} ;
|
|
|
741 |
|
|
|
742 |
|
|
|
743 |
/*
|
|
|
744 |
FUNCTION COMMANDS
|
|
|
745 |
|
|
|
746 |
This rule describes the various function command keys.
|
|
|
747 |
*/
|
|
|
748 |
|
|
|
749 |
<cmd_func> : () -> ( :COMMAND_KEY ) ;
|
|
|
750 |
<cmd_func_extern> : () -> ( :COMMAND_KEY ) ;
|
|
|
751 |
<cmd_func_weak> : () -> ( :COMMAND_KEY ) ;
|
|
|
752 |
|
|
|
753 |
func-command : () -> ( cmd : COMMAND_KEY ) = {
|
|
|
754 |
func ; cmd = <cmd_func> ;
|
|
|
755 |
||
|
|
|
756 |
func ; open-round ; extern ; close-round ;
|
|
|
757 |
cmd = <cmd_func_extern> ;
|
|
|
758 |
||
|
|
|
759 |
func ; open-round ; weak ; close-round ;
|
|
|
760 |
cmd = <cmd_func_weak> ;
|
|
|
761 |
} ;
|
|
|
762 |
|
|
|
763 |
|
|
|
764 |
/*
|
|
|
765 |
INTEGER CONSTANT COMMANDS
|
|
|
766 |
|
|
|
767 |
This rule describes the integer constant commands. This consists of
|
|
|
768 |
a simple list of identifiers.
|
|
|
769 |
*/
|
|
|
770 |
|
|
|
771 |
<declare_nat> : ( :IDENTIFIER ) -> ( :COMMAND ) ;
|
|
|
772 |
|
|
|
773 |
nat-declarator-list : () -> ( c : COMMAND ) = {
|
|
|
774 |
id = identifier ;
|
|
|
775 |
a = <declare_nat> ( id ) ;
|
|
|
776 |
{
|
|
|
777 |
comma ; b = nat-declarator-list ;
|
|
|
778 |
|| b = <command_none> ;
|
|
|
779 |
} ;
|
|
|
780 |
c = <command_join> ( a, b ) ;
|
|
|
781 |
} ;
|
|
|
782 |
|
|
|
783 |
|
|
|
784 |
/*
|
|
|
785 |
TYPE COMMANDS
|
|
|
786 |
|
|
|
787 |
These rules describe the type commands. These comprise a list of
|
|
|
788 |
identifiers, each preceeded by an optional type command key.
|
|
|
789 |
*/
|
|
|
790 |
|
|
|
791 |
<key_int> : () -> ( :TYPE_KEY ) ;
|
|
|
792 |
<key_signed> : () -> ( :TYPE_KEY ) ;
|
|
|
793 |
<key_unsigned> : () -> ( :TYPE_KEY ) ;
|
|
|
794 |
<key_float> : () -> ( :TYPE_KEY ) ;
|
|
|
795 |
<key_arith> : () -> ( :TYPE_KEY ) ;
|
|
|
796 |
<key_scalar> : () -> ( :TYPE_KEY ) ;
|
|
|
797 |
<key_struct> : () -> ( :TYPE_KEY ) ;
|
|
|
798 |
<key_union> : () -> ( :TYPE_KEY ) ;
|
|
|
799 |
<declare_type> : ( :TYPE_KEY, :IDENTIFIER ) -> ( :COMMAND ) ;
|
|
|
800 |
|
|
|
801 |
type-command : () -> ( tag : TYPE_KEY ) = {
|
|
|
802 |
tag = <key_type> ;
|
|
|
803 |
|| open-round ; int ; close-round ; tag = <key_int> ;
|
|
|
804 |
|| open-round ; signed ; close-round ; tag = <key_signed> ;
|
|
|
805 |
|| open-round ; unsigned ; close-round ; tag = <key_unsigned> ;
|
|
|
806 |
|| open-round ; float ; close-round ; tag = <key_float> ;
|
|
|
807 |
|| open-round ; arith ; close-round ; tag = <key_arith> ;
|
|
|
808 |
|| open-round ; scalar ; close-round ; tag = <key_scalar> ;
|
|
|
809 |
|| open-round ; struct ; close-round ; tag = <key_struct> ;
|
|
|
810 |
|| open-round ; union ; close-round ; tag = <key_union> ;
|
|
|
811 |
|| struct ; tag = <key_struct_tag> ;
|
|
|
812 |
|| union ; tag = <key_union_tag> ;
|
|
|
813 |
} ;
|
|
|
814 |
|
|
|
815 |
type-declarator-list : () -> ( c : COMMAND ) = {
|
|
|
816 |
tag = type-command ; id = identifier ;
|
|
|
817 |
a = <declare_type> ( tag, id ) ;
|
|
|
818 |
{
|
|
|
819 |
comma ; b = type-declarator-list ;
|
|
|
820 |
|| b = <command_none> ;
|
|
|
821 |
} ;
|
|
|
822 |
c = <command_join> ( a, b ) ;
|
|
|
823 |
} ;
|
|
|
824 |
|
|
|
825 |
|
|
|
826 |
/*
|
|
|
827 |
SUBSET COMMAND
|
|
|
828 |
|
|
|
829 |
These rules describes the subset command. This is the main entry point
|
|
|
830 |
into the grammar.
|
|
|
831 |
*/
|
|
|
832 |
|
|
|
833 |
<begin_subset> : ( :STRING ) -> ( :COMMAND ) ;
|
|
|
834 |
<end_subset> : ( :COMMAND, :COMMAND ) -> ( :COMMAND ) ;
|
|
|
835 |
<syntax_error> : () -> () ;
|
|
|
836 |
command-list : () -> ( :COMMAND ) ;
|
|
|
837 |
|
|
|
838 |
subset-command : () -> ( c : COMMAND ) = {
|
|
|
839 |
set ; s = subset-name ; assign ;
|
|
|
840 |
a = <begin_subset> ( s ) ;
|
|
|
841 |
open-brace ; b = command-list ; close-brace ;
|
|
|
842 |
c = <end_subset> ( a, b ) ;
|
|
|
843 |
} ;
|
|
|
844 |
|
|
|
845 |
specification : () -> ( c : COMMAND ) = {
|
|
|
846 |
c = subset-command ;
|
|
|
847 |
semicolon ; eof ;
|
|
|
848 |
##
|
|
|
849 |
<syntax_error> ;
|
|
|
850 |
c = <command_none> ;
|
|
|
851 |
} ;
|
|
|
852 |
|
|
|
853 |
|
|
|
854 |
/*
|
|
|
855 |
SPECIFICATION COMMANDS
|
|
|
856 |
|
|
|
857 |
This rule describes the main group of commands; those which introduce
|
|
|
858 |
a specification item.
|
|
|
859 |
*/
|
|
|
860 |
|
|
|
861 |
<declare_base> : () -> ( :COMMAND ) ;
|
|
|
862 |
<declare_define> : ( :IDENTIFIER, :STRING, :STRING ) -> ( :COMMAND ) ;
|
|
|
863 |
<declare_enum> : ( :TYPE_KEY, :IDENTIFIER, :COMMAND ) -> ( :COMMAND ) ;
|
|
|
864 |
<declare_func> : ( :COMMAND_KEY, :IDENTIFIER, :TYPE ) -> ( :COMMAND ) ;
|
|
|
865 |
<declare_macro> : ( :IDENTIFIER, :TYPE ) -> ( :COMMAND ) ;
|
|
|
866 |
<declare_promote> : ( :IDENTIFIER, :TYPE ) -> ( :COMMAND ) ;
|
|
|
867 |
<declare_stmt> : ( :IDENTIFIER, :TYPE ) -> ( :COMMAND ) ;
|
|
|
868 |
<declare_token> : ( :IDENTIFIER, :STRING ) -> ( :COMMAND ) ;
|
|
|
869 |
<declare_typedef> : ( :IDENTIFIER, :TYPE ) -> ( :COMMAND ) ;
|
|
|
870 |
<include_subset> : ( :COMMAND_KEY, :STRING, :SUBSET_KEY ) -> ( :COMMAND ) ;
|
|
|
871 |
<begin_field> : ( :IDENTIFIER, :TYPE_KEY ) -> ( :TYPE, :COMMAND ) ;
|
|
|
872 |
<end_field> : ( :TYPE, :COMMAND, :COMMAND, :BOOLEAN ) -> ( :COMMAND ) ;
|
|
|
873 |
<type_special> : ( :STRING ) -> ( :TYPE ) ;
|
|
|
874 |
<key_exp> : ( :COMMAND_KEY, :TYPE_KEY ) -> ( :TYPE_KEY ) ;
|
|
|
875 |
|
|
|
876 |
spec-command : () -> ( c : COMMAND ) = {
|
|
|
877 |
base-api ;
|
|
|
878 |
c = <declare_base> ;
|
|
|
879 |
||
|
|
|
880 |
define ; id = identifier ; p = define-param-clause ;
|
|
|
881 |
s = constant-value ;
|
|
|
882 |
c = <declare_define> ( id, p, s ) ;
|
|
|
883 |
||
|
|
|
884 |
enumerate ; tag = enum-command ; id = identifier ; assign ;
|
|
|
885 |
open-brace ; e = enumerator-list ; close-brace ;
|
|
|
886 |
c = <declare_enum> ( tag, id, e ) ;
|
|
|
887 |
||
|
|
|
888 |
cmd = exp-command ; lv1 = object-qualifier ;
|
|
|
889 |
lv = <key_exp> ( cmd, lv1 ) ;
|
|
|
890 |
t = qualified-type ;
|
|
|
891 |
c = exp-declarator-list ( cmd, t, lv ) ;
|
|
|
892 |
||
|
|
|
893 |
field ; tag = type-command ; id = identifier ; e = field-exact ;
|
|
|
894 |
( t, a ) = <begin_field> ( id, tag ) ;
|
|
|
895 |
open-brace ; b = field-list ( t ) ; close-brace ;
|
|
|
896 |
c = <end_field> ( t, a, b, e ) ;
|
|
|
897 |
||
|
|
|
898 |
cmd = func-command ; s = qualified-type ;
|
|
|
899 |
( id, p ) = declarator ;
|
|
|
900 |
t = <type_inject> ( p, s ) ;
|
|
|
901 |
c = <declare_func> ( cmd, id, t ) ;
|
|
|
902 |
||
|
|
|
903 |
macro ; lv = object-qualifier ;
|
|
|
904 |
s = qualified-type ;
|
|
|
905 |
( id, p ) = macro-declarator ;
|
|
|
906 |
u = <type_inject> ( p, s ) ;
|
|
|
907 |
v = <type_lvalue> ( u, lv ) ;
|
|
|
908 |
{
|
|
|
909 |
q = macro-operator ;
|
|
|
910 |
|| q = <type_none> ;
|
|
|
911 |
} ;
|
|
|
912 |
t = <type_inject> ( q, v ) ;
|
|
|
913 |
c = <declare_macro> ( id, t ) ;
|
|
|
914 |
||
|
|
|
915 |
nat ; c = nat-declarator-list ;
|
|
|
916 |
||
|
|
|
917 |
statement ; id = identifier ;
|
|
|
918 |
{
|
|
|
919 |
t = macro-operator ;
|
|
|
920 |
|| t = <type_none> ;
|
|
|
921 |
} ;
|
|
|
922 |
c = <declare_stmt> ( id, t ) ;
|
|
|
923 |
||
|
|
|
924 |
token ; id = identifier ; s = insert ;
|
|
|
925 |
c = <declare_token> ( id, s ) ;
|
|
|
926 |
||
|
|
|
927 |
type ; c = type-declarator-list ;
|
|
|
928 |
||
|
|
|
929 |
typedef ;
|
|
|
930 |
s = qualified-type ; ( id, p ) = declarator ;
|
|
|
931 |
t = <type_inject> ( p, s ) ;
|
|
|
932 |
c = <declare_typedef> ( id, t ) ;
|
|
|
933 |
||
|
|
|
934 |
typedef ;
|
|
|
935 |
promote ; open-round ; t = qualified-type ; close-round ;
|
|
|
936 |
id = identifier ;
|
|
|
937 |
c = <declare_promote> ( id, t ) ;
|
|
|
938 |
||
|
|
|
939 |
typedef ;
|
|
|
940 |
special ; open-round ; s = string ; close-round ;
|
|
|
941 |
t = <type_special> ( s ) ;
|
|
|
942 |
id = identifier ;
|
|
|
943 |
c = <declare_typedef> ( id, t ) ;
|
|
|
944 |
||
|
|
|
945 |
cmd = implement-command ;
|
|
|
946 |
s = subset-name ; key = subset-key ;
|
|
|
947 |
c = <include_subset> ( cmd, s, key ) ;
|
|
|
948 |
||
|
|
|
949 |
use ; cmd = <cmd_use> ;
|
|
|
950 |
s = use-subset-name ; key1 = subset-key ;
|
|
|
951 |
key = <subset_next> ( key1 ) ;
|
|
|
952 |
c = <include_subset> ( cmd, s, key ) ;
|
|
|
953 |
||
|
|
|
954 |
c = subset-command ;
|
|
|
955 |
} ;
|
|
|
956 |
|
|
|
957 |
|
|
|
958 |
/*
|
|
|
959 |
TEXTUAL COMMANDS
|
|
|
960 |
|
|
|
961 |
This rule describes the second group of commands; those which are
|
|
|
962 |
concerned with textual substitution.
|
|
|
963 |
*/
|
|
|
964 |
|
|
|
965 |
<declare_comment> : ( :STRING ) -> ( :COMMAND ) ;
|
|
|
966 |
<declare_insert> : ( :STRING ) -> ( :COMMAND ) ;
|
|
|
967 |
<declare_build_insert> : ( :STRING ) -> ( :COMMAND ) ;
|
|
|
968 |
|
|
|
969 |
text-command : () -> ( c : COMMAND ) = {
|
|
|
970 |
( i, s ) = if-command ;
|
|
|
971 |
a = command-list ;
|
|
|
972 |
{
|
|
|
973 |
else ; b = command-list ;
|
|
|
974 |
|| b = <command_none> ;
|
|
|
975 |
} ;
|
|
|
976 |
endif ;
|
|
|
977 |
c = <command_endif> ( i, s, a, b ) ;
|
|
|
978 |
||
|
|
|
979 |
s = comment ;
|
|
|
980 |
c = <declare_comment> ( s ) ;
|
|
|
981 |
||
|
|
|
982 |
s = insert ;
|
|
|
983 |
c = <declare_insert> ( s ) ;
|
|
|
984 |
||
|
|
|
985 |
s = build-insert ;
|
|
|
986 |
c = <declare_build_insert> ( s ) ;
|
|
|
987 |
} ;
|
|
|
988 |
|
|
|
989 |
|
|
|
990 |
/*
|
|
|
991 |
VARIABLE COMMANDS
|
|
|
992 |
|
|
|
993 |
This rule describes the third group of commands; those which affect the
|
|
|
994 |
program environment, but do not actually introduce a specified item.
|
|
|
995 |
*/
|
|
|
996 |
|
|
|
997 |
<variable_string> : ( :STRING, :STRING ) -> () ;
|
|
|
998 |
<variable_plus> : ( :STRING, :STRING ) -> () ;
|
|
|
999 |
<variable_minus> : ( :STRING, :STRING ) -> () ;
|
|
|
1000 |
|
|
|
1001 |
variable-command : () -> () = {
|
|
|
1002 |
info ; s = string ;
|
|
|
1003 |
||
|
|
|
1004 |
nm = variable ; equal ; s = string ;
|
|
|
1005 |
<variable_string> ( nm, s ) ;
|
|
|
1006 |
||
|
|
|
1007 |
nm = variable ; equal ; s = number ;
|
|
|
1008 |
<variable_plus> ( nm, s ) ;
|
|
|
1009 |
||
|
|
|
1010 |
nm = variable ; equal ; minus ; s = number ;
|
|
|
1011 |
<variable_minus> ( nm, s ) ;
|
|
|
1012 |
} ;
|
|
|
1013 |
|
|
|
1014 |
|
|
|
1015 |
/*
|
|
|
1016 |
COMMAND LISTS
|
|
|
1017 |
|
|
|
1018 |
These rules describe the lists of commands.
|
|
|
1019 |
*/
|
|
|
1020 |
|
|
|
1021 |
command-list : () -> ( c : COMMAND ) = {
|
|
|
1022 |
c = <command_none> ;
|
|
|
1023 |
||
|
|
|
1024 |
a = spec-command ; semicolon ;
|
|
|
1025 |
b = command-list ;
|
|
|
1026 |
c = <command_join> ( a, b ) ;
|
|
|
1027 |
||
|
|
|
1028 |
a = text-command ;
|
|
|
1029 |
b = command-list ;
|
|
|
1030 |
c = <command_join> ( a, b ) ;
|
|
|
1031 |
||
|
|
|
1032 |
variable-command ; semicolon ;
|
|
|
1033 |
c = command-list ;
|
|
|
1034 |
} ;
|
|
|
1035 |
|
|
|
1036 |
|
|
|
1037 |
%entry% specification ;
|