Initial revision
[charm.git] / src / xlat++ / xp-t.bison
1 %{
2
3 /*  Copyright (C) 1989-1991 James A. Roskind, All rights reserved. 
4     This grammar was developed  and  written  by  James  A.  Roskind. 
5     Copying  of  this  grammar  description, as a whole, is permitted 
6     providing this notice is intact and applicable  in  all  complete 
7     copies.   Translations as a whole to other parser generator input 
8     languages  (or  grammar  description  languages)   is   permitted 
9     provided  that  this  notice is intact and applicable in all such 
10     copies,  along  with  a  disclaimer  that  the  contents  are   a 
11     translation.   The reproduction of derived text, such as modified 
12     versions of this grammar, or the output of parser generators,  is 
13     permitted,  provided  the  resulting  work includes the copyright 
14     notice "Portions Copyright (c)  1989,  1990  James  A.  Roskind". 
15     Derived products, such as compilers, translators, browsers, etc., 
16     that  use  this  grammar,  must also provide the notice "Portions 
17     Copyright  (c)  1989,  1990  James  A.  Roskind"  in   a   manner 
18     appropriate  to  the  utility,  and in keeping with copyright law 
19     (e.g.: EITHER displayed when first invoked/executed; OR displayed 
20     continuously on display terminal; OR via placement in the  object 
21     code  in  form  readable in a printout, with or near the title of 
22     the work, or at the end of the file).  No royalties, licenses  or 
23     commissions  of  any  kind are required to copy this grammar, its 
24     translations, or derivative products, when the copies are made in 
25     compliance with this notice. Persons or corporations that do make 
26     copies in compliance with this notice may charge  whatever  price 
27     is  agreeable  to  a  buyer, for such copies or derivative works. 
28     THIS GRAMMAR IS PROVIDED ``AS IS'' AND  WITHOUT  ANY  EXPRESS  OR 
29     IMPLIED  WARRANTIES,  INCLUDING,  WITHOUT LIMITATION, THE IMPLIED 
30     WARRANTIES  OF  MERCHANTABILITY  AND  FITNESS  FOR  A  PARTICULAR 
31     PURPOSE.
32
33     James A. Roskind
34     Independent Consultant
35     516 Latania Palm Drive
36     Indialantic FL, 32903
37     (407)729-4348
38     jar@hq.ileaf.com
39
40
41     ---end of copyright notice---
42 */
43
44 /*
45
46 1) template support: Not  done:  pending  syntax  specification  from 
47 ANSI.  (This looks like a major effort, as ANSI has decided to extend 
48 the  "TYPEDEFname"-feedback-to-the-lexer-hack  to  support   template 
49 names as a new kind of terminal token.)
50
51 2)  exception  handling:  Not done: pending syntax specification from 
52 ANSI (but it doesn't look hard)
53
54 done: 3) Support nested types, including identifier::name,  where  we 
55 realize  that  identifier was a hidden type.  Force the lexer to keep 
56 pace in this situation.   This  will  require  an  extension  of  the 
57 yacc-lex feedback loop.
58
59 done: 4) Support nested types even when derivations are used in class 
60 definitions.
61
62 done: 6) Allow declaration specifiers to be left out of  declarations 
63 at file and structure scope so that operator conversion functions can 
64 be  declared and/or defined.  Note that checking to see that it was a 
65 function type that does not require declaration_specifiers is  now  a 
66 constraint  check,  and  not  a  syntax  issue.  Within function body 
67 scopes, declaration specifiers are required, and this is critical  to 
68 distinguishing expressions.
69
70 */
71
72 %}
73
74 /*
75
76 Interesting ambiguity:
77 Usually
78         typename ( typename2 ) ...
79 or
80         typename ( typename2 [4] ) ...
81 etc.
82 is a redeclaration of typename2.
83
84 Inside  a structure elaboration, it is sometimes the declaration of a 
85 constructor!  Note, this only  counts  if  typename  IS  the  current 
86 containing  class name. (Note this can't conflict with ANSI C because 
87 ANSI C would call it a redefinition, but  claim  it  is  semantically 
88 illegal because you can't have a member declared the same type as the 
89 containing struct!) Since the ambiguity is only reached when a ';' is 
90 found,   there  is  no  problem  with  the  fact  that  the  semantic 
91 interpretation  is  providing  the  true  resolution.   As  currently 
92 implemented, the constructor semantic actions must be able to process 
93 an  ordinary  declaration.  I may reverse this in the future, to ease 
94 semantic implementation.
95
96 */
97
98
99
100 /*
101
102 INTRO TO ANSI C GRAMMAR (provided in a separate file):
103
104 The refined grammar resolves several typedef ambiguities in the draft 
105 proposed ANSI C standard syntax down to 1 shift/reduce  conflict,  as 
106 reported by a YACC process.  Note that the one shift reduce conflicts 
107 is  the  traditional  if-if-else conflict that is not resolved by the 
108 grammar.  This ambiguity can be removed using the method described in 
109 the Dragon Book (2nd edition), but this does  not  appear  worth  the 
110 effort.
111
112 There  was quite a bit of effort made to reduce the conflicts to this 
113 level, and an additional effort was made to make  the  grammar  quite 
114 similar  to  the  C++ grammar being developed in parallel.  Note that 
115 this grammar resolves the following ANSI C ambiguities:
116
117 ANSI C section 3.5.6, "If the [typedef  name]  is  redeclared  at  an 
118 inner  scope,  the  type specifiers shall not be omitted in the inner 
119 declaration".  Supplying type specifiers prevents consideration of  T 
120 as a typedef name in this grammar.  Failure to supply type specifiers 
121 forced the use of the TYPEDEFname as a type specifier.  This is taken 
122 to an (unnecessary) extreme by this implementation.  The ambiguity is 
123 only  a  problem  with  the first declarator in a declaration, but we 
124 restrict  ALL  declarators  whenever  the  users  fails  to   use   a 
125 type_specifier.
126
127 ANSI C section 3.5.4.3, "In a parameter declaration, a single typedef 
128 name  in  parentheses  is  taken  to  be  an abstract declarator that 
129 specifies a function  with  a  single  parameter,  not  as  redundant 
130 parentheses  around  the  identifier".  This is extended to cover the 
131 following cases:
132
133 typedef float T;
134 int noo(const (T[5]));
135 int moo(const (T(int)));
136 ...
137
138 Where again the '(' immediately to the left of 'T' is interpreted  as 
139 being  the  start  of  a  parameter type list, and not as a redundant 
140 paren around a redeclaration of T.  Hence an equivalent code fragment 
141 is:
142
143 typedef float T;
144 int noo(const int identifier1 (T identifier2 [5]));
145 int moo(const int identifier1 (T identifier2 (int identifier3)));
146 ...
147
148 */
149
150
151 %{
152 /*************** Includes and Defines *****************************/
153 #define YYDEBUG_LEXER_TEXT (yylval) /* our lexer loads this up each time.
154                                      We are telling the graphical debugger
155                                      where to find the spelling of the 
156                                      tokens.*/
157 #define YYDEBUG 1        /* get the pretty debugging code to compile*/
158 #define YYSTYPE  char *  /* interface with flex: should be in header file */
159
160
161
162 #include "xp-lexer.h" 
163
164 StackStruct *StackTop=NULL ;
165 StackStruct *GlobalStack=NULL ;
166
167 AggState *PermanentAggTable[MAXAGGS] ;  
168 int PermanentAggTableSize = 0 ;
169 /* this table is only added to, never deleted from. It stores the objects
170    defined in an aggregate type.                                          */
171                                         
172
173 /* These tables just hold lists of Chares,BOCs,Accs ... */
174 ChareInfo * ChareTable[MAXCHARES] ;
175 ChareInfo * BOCTable[MAXCHARES] ;
176 MsgStruct MessageTable[MAXMSGS] ;
177 AccStruct * AccTable[MAXACCS] ;
178 AccStruct * MonoTable[MAXACCS] ;
179 char * DTableTable[MAXDTABLES] ;
180 char * ReadTable[MAXREADS] ;
181 char * ReadMsgTable[MAXREADS] ;
182 FunctionStruct FunctionTable[MAX_FUNCTIONS] ;
183 int charecount = -1 ;
184 int boccount = -1 ;
185 int TotalEntries = 0 ;
186 int TotalMsgs = 0 ;
187 int TotalAccs = 0 ;
188 int TotalMonos = 0 ;
189 int TotalDTables = 0 ;
190 int TotalReadMsgs = 0 ;
191 int TotalReads = 0 ;
192 int TotalFns = 0 ;
193
194 /* This table is used to distinguish between typedefs and idents */
195 SymEntry SymTable[MAXSYMBOLS] ;
196 int TotalSyms = 0 ;
197
198 /* the following three tables store all handle identifiers and their types */
199 HandleEntry ChareHandleTable[MAXIDENTS] ;
200 HandleEntry BOCHandleTable[MAXIDENTS] ;
201 HandleEntry AccHandleTable[MAXIDENTS] ;
202 HandleEntry MonoHandleTable[MAXIDENTS] ;
203 HandleEntry WrOnHandleTable[MAXIDENTS] ;
204 int ChareHandleTableSize = 0 ;
205 int BOCHandleTableSize = 0 ;
206 int AccHandleTableSize = 0 ;
207 int MonoHandleTableSize = 0 ;
208 int WrOnHandleTableSize = 0 ;
209
210 /* char modname[MAX_NAME_LENGTH] ;  */
211
212 char OutBuf[MAX_OUTBUF_SIZE] ;
213
214 int CurrentLine=1 ;
215 int CurrentScope = 0 ;  /* 1 means file scope, > 1 means inside a block */
216 char CurrentFileName[MAX_NAME_LENGTH] = {'\0'} ;
217 int CurrentAccess = -1, CurrentAggType = -1, CurrentStorage = -1 ;
218 int CurrentCharmType = -1 ;
219 int CurrentCharmNameIndex = -1 ;
220 char CurrentTypedef[MAX_NAME_LENGTH] = {'\0'} ;
221 char CurrentDeclType[MAX_NAME_LENGTH] = {'\0'} ;
222 char CurrentAggName[MAX_NAME_LENGTH] = {'\0'} ;
223 char CurrentChare[MAX_NAME_LENGTH] = {'\0'} ; 
224 char CurrentEP[MAX_NAME_LENGTH] = {'\0'} ;
225 char CurrentFn[MAX_NAME_LENGTH] = {'\0'} ;
226 char CurrentMsgParm[MAX_NAME_LENGTH] = {'\0'} ;
227 char CurrentSharedHandle[MAX_NAME_LENGTH] = {'_','C','K','_','N','O','T','A','C','C','H','A','N','D','L','E'} ;
228 AccStruct *CurrentAcc ;
229 ChareInfo *CurrentCharePtr ;
230 char CurrentAssOp[5] ;
231 char CurrentAsterisk[MAX_NAME_LENGTH] ;
232 char *EpMsg=NULL ;
233 char SendEP[MAX_NAME_LENGTH] ;
234 char SendChare[MAX_NAME_LENGTH] ;
235 char SendPe[MAX_NAME_LENGTH] ;
236 char LastChare[MAX_NAME_LENGTH] ;
237 char LastEP[MAX_NAME_LENGTH] ;
238 char LastArg[MAX_NAME_LENGTH] ;
239 char *ParentArray[MAX_PARENTS] ;
240 int SendType = -1 ;
241 int main_argc_argv = FALSE ;
242 int foundargs = FALSE ;
243 int numparents = 0 ;
244 int SendMsgBranchPoss = FALSE ;
245 int FoundHandle = -1 ;
246 int FilledAccMsg = FALSE ;
247 int FoundConstructorBody = FALSE ;
248 int IsMonoCall = FALSE ;
249 int IsAccCall = FALSE ;
250 int FoundParms = FALSE ;
251 int FoundLocalBranch = FALSE ;
252 int AddedScope = 0 ;
253 int FoundGlobalScope = 0 ;
254 int FoundTable = FALSE ;
255 int FoundVarSize = FALSE ;
256 int FoundReadOnly = FALSE ;
257 int StructScope = FALSE ;
258 int AccFnScope = -1 ;
259 int FoundAccFnDef = FALSE ;
260 int MakeGraph = FALSE ;
261 int InsideChareCode = FALSE ;
262 int NewOpType = -1 ;
263 char *NewType ;
264 int FoundDeclarator=FALSE ; 
265 int CurrentFnIsInline=FALSE ;
266 int FoundChareEPPair=0 ;
267
268 int ErrVal = FALSE ;
269
270 char CoreName[MAX_NAME_LENGTH] ;
271 int shouldprint=1 ;
272 char prevtoken[MAX_TOKEN_SIZE] ;
273 FILE *outfile, *headerfile, *graphfile ;
274
275 extern int FoundLBrace, FoundRBrace ;
276
277 extern char *CheckSendError() ;
278 extern char *Mystrstr() ;
279 extern EP *SearchEPList() ;
280 extern char *Concat2() ;
281 extern char *Concat3() ;
282
283 %}
284
285 /******************************************************************/
286
287 /* These are the CHARM++ tokens */
288 %token CHARE           BRANCHED        MESSAGE
289 /* Note: BRANCHED is no longer a token returned by lex, it is used just
290    as a #defined constant so that a lot of older code doesnt break */
291
292 %token HANDLE          GROUP           ENTRY
293 /* %token MODULE          INTERFACE  */
294 %token DOUBLEARROW     ALL_NODES       LOCAL
295 %token ACCUMULATOR     MONOTONIC       READONLY        WRITEONCE
296 %token NEWCHARE        NEWGROUP
297
298
299 /* This group is used by the C/C++ language parser */
300 %token AUTO            DOUBLE          INT             STRUCT
301 %token BREAK           ELSE            LONG            SWITCH
302 %token CASE            ENUM            REGISTER        TYPEDEF
303 %token CHAR            EXTERN          RETURN          UNION
304 %token CONST           FLOAT           SHORT           UNSIGNED
305 %token WCHAR_TOKEN     __WCHAR_TOKEN   PTRDIFF_TOKEN
306 %token CONTINUE        FOR             SIGNED          VOID
307 %token DEFAULT         GOTO            SIZEOF          VOLATILE
308 %token DO              IF              STATIC          WHILE
309
310 /* The following are used in C++ only.  ANSI C would call these IDENTIFIERs */
311 %token NEW             DELETE
312 %token THIS
313 %token OPERATOR
314 %token CLASS
315 %token PUBLIC          PROTECTED       PRIVATE
316 %token VIRTUAL         FRIEND
317 %token INLINE          UNDERSCORE_INLINE         OVERLOAD
318 /* the underscore_inline above is __inline__ used in byteorder.h in 
319    G++'s include files for Solaris */
320
321 /* ANSI C Grammar suggestions */
322 %token IDENTIFIER              STRINGliteral
323 %token FLOATINGconstant        INTEGERconstant        CHARACTERconstant
324 %token OCTALconstant           HEXconstant
325
326 /* New Lexical element, whereas ANSI C suggested non-terminal */
327 %token TYPEDEFname
328
329 /* Multi-Character operators */
330 %token  ARROW            /*    ->                              */
331 %token  ICR DECR         /*    ++      --                      */
332 %token  LS RS            /*    <<      >>                      */
333 %token  LE GE EQ NE      /*    <=      >=      ==      !=      */
334 %token  ANDAND OROR      /*    &&      ||                      */
335 %token  ELLIPSIS         /*    ...                             */
336                  /* Following are used in C++, not ANSI C        */
337 %token  CLCL             /*    ::                              */
338 %token  DOTstar ARROWstar/*    .*       ->*                    */
339
340 /* modifying assignment operators */
341 %token MULTassign  DIVassign    MODassign   /*   *=      /=      %=      */
342 %token PLUSassign  MINUSassign              /*   +=      -=              */
343 %token LSassign    RSassign                 /*   <<=     >>=             */
344 %token ANDassign   ERassign     ORassign    /*   &=      ^=      |=      */
345
346 /*************************************************************************/
347
348 %start translation_unit
349
350 /*************************************************************************/
351
352 %%
353
354 /*********************** CONSTANTS *********************************/
355 constant:
356         INTEGERconstant         { $$ = $1 ; }
357         | FLOATINGconstant      { $$ = $1 ; }
358         /*  We  are not including ENUMERATIONconstant here because we 
359           are treating it like a variable with a type of "enumeration 
360           constant".  */
361         | OCTALconstant         { $$ = $1 ; }
362         | HEXconstant           { $$ = $1 ; }
363         | CHARACTERconstant     { $$ = $1 ; }
364         ;
365
366 string_literal_list:
367                 STRINGliteral
368                 | string_literal_list STRINGliteral
369                 ;
370
371
372 /************************* EXPRESSIONS ********************************/
373
374
375 /* Note that I provide  a  "scope_opt_identifier"  that  *cannot* 
376     begin  with ::.  This guarantees we have a viable declarator, and 
377     helps to disambiguate :: based uses in the grammar.  For example:
378
379             ...
380             {
381             int (* ::b()); // must be an expression
382             int (T::b); // officially a declaration, which fails on constraint grounds
383
384     This *syntax* restriction reflects the current syntax in the ANSI 
385     C++ Working Papers.   This  means  that  it  is  *incorrect*  for 
386     parsers to misparse the example:
387
388             int (* ::b()); // must be an expression
389
390     as a declaration, and then report a constraint error.
391
392     In contrast, declarations such as:
393
394         class T;
395         class A;
396         class B;
397         main(){
398               T( F());  // constraint error: cannot declare local function
399               T (A::B::a); // constraint error: cannot declare member as a local value
400
401     are  *parsed*  as  declarations,  and *then* given semantic error 
402     reports.  It is incorrect for a parser to "change its mind" based 
403     on constraints.  If your C++ compiler claims  that  the  above  2 
404     lines are expressions, then *I* claim that they are wrong. 
405 */
406
407 paren_identifier_declarator:
408         scope_opt_identifier     {  $$ = $1 ; }
409         | scope_opt_complex_name   { $$ = $1 ; }
410         | '(' paren_identifier_declarator ')'
411         ;
412
413
414 /* Note that CLCL IDENTIFIER is NOT part of scope_opt_identifier, 
415     but  it  is  part of global_opt_scope_opt_identifier.  It is ONLY 
416     valid for referring to an identifier, and NOT valid for declaring 
417     (or importing an external declaration of)  an  identifier.   This 
418     disambiguates  the  following  code,  which  would  otherwise  be 
419     syntactically and semantically ambiguous:
420
421             class base {
422                 static int i; // element i;
423                 float member_function(void);
424                 };
425             base i; // global i
426             float base::member_function(void) {
427                 i; // refers to static int element "i" of base
428                 ::i; // refers to global "i", with type "base"
429                     {
430                     base :: i; // import of global "i", like "base (::i);"?
431                                 // OR reference to global??
432                     }
433                 }
434 */
435
436 primary_expression:
437         global_opt_scope_opt_identifier { $$ = $1 ; }
438         | global_opt_scope_opt_complex_name
439         | THIS   /* C++, not ANSI C */  { $$ = (char *)malloc(sizeof(char)*5);
440                                           strcpy($$,"this") ;
441                                         }
442         | constant                      { $$ = $1 ; }
443         | string_literal_list
444         | '(' comma_expression ')'      { $$ = Concat3("(",$2,")") ; }
445         ;
446
447
448     /* I had to disallow struct, union, or enum  elaborations  during 
449     operator_function_name.   The  ANSI  C++  Working  paper is vague 
450     about whether this should be part of the syntax, or a constraint.  
451     The ambiguities that resulted were more than LALR  could  handle, 
452     so  the  easiest  fix was to be more specific.  This means that I 
453     had to in-line expand type_specifier_or_name far  enough  that  I 
454     would  be  able to exclude elaborations.  This need is what drove 
455     me to distinguish a whole series of tokens based on whether  they 
456     include elaborations:
457
458          struct A { ... }
459
460     or simply a reference to an aggregate or enumeration:
461
462          enum A
463
464     The  latter,  as  well  an  non-aggregate  types are what make up 
465     non_elaborating_type_specifier */
466
467     /* Note that the following does not include  type_qualifier_list. 
468     Hence,   whenever   non_elaborating_type_specifier  is  used,  an 
469     adjacent rule is supplied containing type_qualifier_list.  It  is 
470     not  generally  possible  to  know  immediately  (i_e., reduce) a 
471     type_qualifier_list, as a TYPEDEFname that follows might  not  be 
472     part of a type specifier, but might instead be "TYPEDEFname ::*".  
473     */
474
475 non_elaborating_type_specifier:
476         sue_type_specifier
477         | basic_type_specifier
478         | typedef_type_specifier
479
480         | basic_type_name
481         | TYPEDEFname   
482         | global_or_scoped_typedefname
483         ;
484
485
486     /*  The  following  introduces  MANY  conflicts.   Requiring  and 
487     allowing '(' ')' around the `type' when the type is complex would 
488     help a lot. */
489
490 operator_function_name:
491         OPERATOR any_operator   
492         {       $$ = (char *)malloc(sizeof(char)*(9+strlen($2))) ;
493                 sprintf($$,"operator %s",$2) ;  
494         }
495         | OPERATOR type_qualifier_list            operator_function_ptr_opt
496         | OPERATOR non_elaborating_type_specifier operator_function_ptr_opt
497         ;
498
499
500     /* The following causes several ambiguities on *  and  &.   These 
501     conflicts  would also be removed if parens around the `type' were 
502     required in the derivations for operator_function_name */
503
504     /*  Interesting  aside:  The  use  of  right  recursion  in   the 
505     production  for  operator_function_ptr_opt gives both the correct 
506     parsing, AND removes a conflict!   Right  recursion  permits  the 
507     parser  to  defer  reductions  (a.k.a.:  delay  resolution),  and 
508     effectively make a second pass! */
509
510 operator_function_ptr_opt:
511         /* nothing */
512         | unary_modifier        operator_function_ptr_opt
513         | asterisk_or_ampersand operator_function_ptr_opt
514         ;
515
516
517     /* List of operators we can overload */
518 any_operator:
519         '+'
520         | '-'
521         | '*'
522         | '/'
523         | '%'
524         | '^'
525         | '&'
526         | '|'
527         | '~'
528         | '!'
529         | '<'
530         | '>'
531         | LS
532         | RS
533         | ANDAND
534         | OROR
535         | ARROW
536         | ARROWstar
537         | '.'
538         | DOTstar
539         | ICR
540         | DECR
541         | LE
542         | GE
543         | EQ
544         | NE
545         | assignment_operator
546         | '(' ')'
547         | '[' ']'
548         | NEW
549         | DELETE
550         | ','
551         ;
552
553
554     /* The following production for type_qualifier_list was specially 
555     placed BEFORE the definition of postfix_expression to  resolve  a 
556     reduce-reduce    conflict    set    correctly.    Note   that   a 
557     type_qualifier_list is only used  in  a  declaration,  whereas  a 
558     postfix_expression is clearly an example of an expression.  Hence 
559     we  are helping with the "if it can be a declaration, then it is" 
560     rule.  The reduce conflicts are on ')', ',' and '='.  Do not move 
561     the following productions */
562
563 type_qualifier_list_opt:
564         /* Nothing */
565         | type_qualifier_list
566         ;
567
568
569     /*  Note  that  the next set of productions in this grammar gives 
570     post-increment a higher precedence that pre-increment.   This  is 
571     not  clearly  stated  in  the  C++  Reference manual, and is only 
572     implied by the grammar in the ANSI C Standard. */
573
574     /* I *DON'T* use  argument_expression_list_opt  to  simplify  the 
575     grammar  shown  below.   I am deliberately deferring any decision 
576     until    *after*     the     closing     paren,     and     using 
577     "argument_expression_list_opt" would commit prematurely.  This is 
578     critical to proper conflict resolution. */
579
580     /*  The  {}  in  the following rules allow the parser to tell the 
581     lexer to search for the member name  in  the  appropriate  scope, 
582     much the way the CLCL operator works.*/
583
584 postfix_expression:
585         primary_expression { $$ = $1 ; }
586         | postfix_expression '[' comma_expression ']'   
587           {     char *temp ;    
588                 strcpy(SendPe,$3);
589                 strcpy(SendChare,$1) ;
590                 SendMsgBranchPoss = TRUE ;
591                 temp = Concat3($1,"[",$3) ;
592                 $$ = Concat2(temp,"]") ;
593           }
594         | postfix_expression '(' ')'
595           { $$ = Concat3($1,"(",")") ; 
596             if ( MakeGraph && ( InsideChareCode || CurrentAggType==CHARE 
597                                 || CurrentAggType==BRANCHED) )
598                 Graph_OutputPrivateCall($1) ; 
599           }
600         | postfix_expression '(' argument_expression_list ')'
601           { char *charename, *scopestr, *temp ; 
602
603             /***
604             if ( MakeGraph && ( strcmp($1,"_CK_CreateBoc") == 0 
605                                 || strcmp($1,"_CK_CreateChare") == 0)  ) 
606                 Graph_OutputCreate($1,LastArg,LastChare,LastEP) ;
607             ***/
608             if ( SendType != -1 ) {
609                 char *sptr = Mystrstr(OutBuf,$3) ;
610                 if ( sptr != NULL ) 
611                         *sptr = '\0' ;
612                 else 
613                         fprintf(stderr,"TRANSLATOR ERROR : %s, line %d : couldnt discard => etc.\n",CurrentFileName,CurrentLine) ;
614                 FLUSHBUF() ;
615         
616             /* Now output the Send functions */
617                 scopestr = CheckSendError(SendChare,SendEP,$3,SendType,
618                                                                 &charename) ;
619                 OutputSend(SendChare,SendEP,$3,SendType,charename,scopestr,
620                                                                 SendPe) ;
621
622                 SendType = -1 ;
623             }
624             else if ( MakeGraph && ( InsideChareCode || CurrentAggType==CHARE 
625                                      || CurrentAggType==BRANCHED) )
626                 Graph_OutputPrivateCall($1) ; 
627
628             temp = Concat3($1,"(",$3) ;
629             $$ = Concat2(temp,")") ;
630           }
631
632         | postfix_expression {StructScope=1;} '.'   member_name
633           { $$ = Concat3($1,".",$4) ;StructScope=0; }
634         | postfix_expression {StructScope=1;} ARROW 
635           { if ( strcmp(CurrentSharedHandle,"_CK_NOTACCHANDLE") != 0 ) {
636                 int handleindex ;
637                 char *sptr = Mystrstr(OutBuf,CurrentSharedHandle) ;
638
639                 if ( sptr != NULL ) 
640                     *sptr = '\0' ;
641                 else 
642                     fprintf(stderr,"TRANSLATOR ERROR in shared object handle use: %s, line %d: \n",CurrentFileName,CurrentLine) ;
643                 FLUSHBUF() ;
644                 handleindex = SearchHandleTable(AccHandleTable,
645                                 AccHandleTableSize,CurrentSharedHandle) ;
646                 if ( handleindex != -1 ) {
647                     fprintf(outfile,"((%s *)(_CK_9GetAccDataPtr(GetBocDataPtr(%s))))",AccHandleTable[handleindex].typestr,CurrentSharedHandle) ;
648                     IsAccCall = TRUE ;
649                 }
650                 else if ( (handleindex = SearchHandleTable(MonoHandleTable,
651                               MonoHandleTableSize,CurrentSharedHandle)) != -1 )
652                 {   fprintf(outfile,"((%s *)(_CK_9GetMonoDataPtr(GetBocDataPtr(%s))))",MonoHandleTable[handleindex].typestr,CurrentSharedHandle) ;
653                     IsMonoCall = TRUE ;
654                 }
655                 else if ( SearchHandleTable(WrOnHandleTable,
656                                 WrOnHandleTableSize,CurrentSharedHandle) != -1)
657                         ;  /* action taken at end of this rule */ 
658                 else 
659                     fprintf(stderr,"TRANSLATOR ERROR: %s, line %d, couldnt find acc/mono handle in table.\n",CurrentFileName,CurrentLine) ;
660
661
662                 strcat(OutBuf,prevtoken) ; /* prevtoken now is "->" */
663                 strcpy(prevtoken,"") ;  
664             }
665           } 
666           member_name
667           {     char *wovid ;
668                 StructScope = 0 ;
669                 if ( SearchHandleTable(WrOnHandleTable,
670                                 WrOnHandleTableSize,CurrentSharedHandle) != -1 )
671                 {       if ( strcmp($5,"DerefWriteOnce") != 0 )
672                                 CharmError("writeonce variables have only the DerefWriteOnce method") ;
673                         else {  
674                                 wovid = Mystrstr(OutBuf,CurrentSharedHandle) ;
675                                 *wovid = '\0' ;
676                                 strcat(OutBuf,"DerefWriteOnce(") ;
677                                 strcat(OutBuf,CurrentSharedHandle) ;
678                                 strcat(OutBuf,")") ;
679                         /*      strcpy(prevtoken,"") ;  */
680                         }
681                 }
682                 strcpy(CurrentSharedHandle,"_CK_NOTACCHANDLE") ;        
683                 $$ = Concat3($1,"->",$5) ;
684           }
685         | postfix_expression ICR
686           { $$ = Concat2($1,"++") ; }
687         | postfix_expression DECR
688           { $$ = Concat2($1,"--") ; }
689
690 /* The next 3 are CHARM++ rules for SendMsg, SendMsgBranch, Broadcast */
691
692         | postfix_expression '[' LOCAL ']' 
693           {     char *sptr ; int i ; char str[64] ;
694                 sptr = Mystrstr(OutBuf,$1) ;
695                 if ( sptr != NULL ) 
696                         *sptr = '\0' ;
697                 else 
698                         fprintf(stderr,"TRANSLATOR ERROR : %s, line %d : couldnt discard [LOCAL] etc.\n",CurrentFileName,CurrentLine) ;
699                 i = SearchHandleTable(BOCHandleTable,BOCHandleTableSize,$1) ;
700                 if ( i == -1 ) {
701                         fprintf(stderr,"ERROR : %s, line %d : %s is not a branched chare group id.\n",CurrentFileName,CurrentLine,$1) ;
702                 }
703                 sprintf(str,"((%s *)GetBocDataPtr(%s))",BOCHandleTable[i].typestr,$1);
704                 strcat(OutBuf,str) ;
705                 strcpy(prevtoken,"") ;   /* prevtoken is ']' */
706                 FLUSHBUF() ;
707
708                 if ( MakeGraph ) {
709                         fprintf(graphfile,"CALLBOC %s %s : %s", CurrentChare, 
710                                         CurrentEP, BOCHandleTable[i].typestr) ;
711                 }
712           }
713           ARROW member_name
714           {
715                 if ( MakeGraph ) 
716                         fprintf(graphfile," %s\n",$7) ;
717           }
718         | postfix_expression DOUBLEARROW 
719           {     if ( !SendMsgBranchPoss ) {
720                         SendType = SIMPLE ;
721                         strcpy(SendChare,$1) ;
722                 }
723                 else {
724                         SendType = BRANCH ;
725                         SendMsgBranchPoss = FALSE ;
726                 }
727           }
728           member_name   
729           {     char *sptr ;    
730                 strcpy(SendEP,$4) ; 
731                 /* discard all the CHARM++ `=>' stuff */
732                 sptr = Mystrstr(OutBuf,$4) ;
733                 if ( sptr != NULL ) 
734                         *sptr = '\0' ;
735                 sptr = Mystrstr(OutBuf,SendChare) ;
736                 if ( sptr != NULL ) 
737                         *sptr = '\0' ;
738                 else 
739                         fprintf(stderr,"TRANSLATOR ERROR : %s, line %d : couldnt discard => etc.\n",CurrentFileName,CurrentLine) ;
740                 strcpy(prevtoken,"") ;
741                 FLUSHBUF() ;
742           }
743
744         | postfix_expression '[' ALL_NODES ']' DOUBLEARROW 
745           {     strcpy(SendChare,$1) ;
746                 SendType = BROADCAST ;
747           }
748           member_name   
749           {     char *sptr ;
750                 strcpy(SendEP,$7) ; 
751                 /* discard all the CHARM++ `=>' stuff */
752                 sptr = Mystrstr(OutBuf,$7) ;
753                 if ( sptr != NULL ) 
754                         *sptr = '\0' ;
755                 sptr = Mystrstr(OutBuf,SendChare) ;
756                 if ( sptr != NULL ) 
757                         *sptr = '\0' ;
758                 else 
759                         fprintf(stderr,"TRANSLATOR ERROR : %s, line %d : couldnt discard => etc.\n",CurrentFileName,CurrentLine) ;
760                 strcpy(prevtoken,"") ;
761                 FLUSHBUF() ;
762           }
763
764 /* NOTE: the SendMsgBranch rule : Chare[PEnum]=>EP() is a special case
765    of the SendMsg rule. Adding it explicitly causes a Shift reduce conflict
766    because of the "postfix_expression '[' comma_expression ']'" rule above.
767    - SANJEEV
768 */
769
770                 /* The next 4 rules are the source of cast ambiguity */
771         | TYPEDEFname                  '(' ')'
772           { $$ = Concat3($1,"(",")") ; }
773         | global_or_scoped_typedefname '(' ')'
774           { $$ = Concat3($1,"(",")") ; }
775         | TYPEDEFname                  '(' argument_expression_list ')'
776           { char *temp ;
777             temp = Concat3($1,"(",$3) ;
778             $$ = Concat2(temp,")") ;
779           }
780         | global_or_scoped_typedefname '(' argument_expression_list ')'
781           { char *temp ;
782             temp = Concat3($1,"(",$3) ;
783             $$ = Concat2(temp,")") ;
784           }
785         | basic_type_name '(' assignment_expression ')'
786           { char *temp ;
787             temp = Concat3($1,"(",$3) ;
788             $$ = Concat2(temp,")") ;
789           }
790             /* If the following rule is added to the  grammar,  there 
791             will  be 3 additional reduce-reduce conflicts.  They will 
792             all be resolved in favor of NOT using the following rule, 
793             so no harm will be done.   However,  since  the  rule  is 
794             semantically  illegal  we  will  omit  it  until  we  are 
795             enhancing the grammar for error recovery */
796 /*      | basic_type_name '(' ')'  /* Illegal: no such constructor*/
797         ;
798
799
800     /* The last two productions in the next set are questionable, but 
801     do not induce any conflicts.  I need to ask X3J16 :  Having  them 
802     means that we have complex member function deletes like:
803
804           const unsigned int :: ~ const unsigned int
805     */
806
807 member_name:
808         scope_opt_identifier    
809         {       char *str ;     
810                 if ( IsMonoCall && strcmp($1,"Update")==0 ) {
811                         str=Mystrstr(OutBuf,"Update") ;
812                         *str = '\0' ;
813                         strcat(OutBuf,"_CK_Update") ;
814                 }
815                 else 
816                         $$ = $1;
817                 IsMonoCall = FALSE ;
818                 IsAccCall = FALSE ;
819         }
820         | scope_opt_complex_name
821         | basic_type_name CLCL '~' basic_type_name  /* C++, not ANSI C */
822
823         | declaration_qualifier_list  CLCL '~'   declaration_qualifier_list
824         | type_qualifier_list         CLCL '~'   type_qualifier_list
825         ;
826
827 argument_expression_list:
828         assignment_expression   { $$ = $1 ; /* FLUSHBUF() ;*/ }
829         | argument_expression_list ',' assignment_expression
830           { $$ = Concat3($1,",",$3) ; 
831             strcpy(LastArg,$3) ;
832           }
833         ;
834
835 unary_expression:
836         postfix_expression 
837         {       $$ = $1 ; 
838                 strcpy(CurrentSharedHandle,"_CK_NOTACCHANDLE") ; 
839                 SendMsgBranchPoss = FALSE ;
840         }
841         | ICR  unary_expression         { $$ = Concat2("++",$2) ; }
842         | DECR unary_expression         { $$ = Concat2("--",$2) ; }
843         | asterisk_or_ampersand cast_expression 
844           {  if ( ! FoundChareEPPair ) 
845                 $$ = Concat2(CurrentAsterisk,$2) ; 
846              else
847                 $$ = $2 ;
848              FoundChareEPPair = 0 ;
849           }
850         | '-'                   cast_expression { $$ = Concat2("-",$2) ; }
851         | '+'                   cast_expression { $$ = Concat2("+",$2) ; }
852         | '~'                   cast_expression { $$ = Concat2("~",$2) ; }
853         | '!'                   cast_expression { $$ = Concat2("!",$2) ; }
854         | SIZEOF unary_expression       { $$ = Concat2("sizeof",$2) ; }
855         | SIZEOF '(' type_name ')'      { char *temp = Concat3("sizeof","(",$3) ;
856                                           $$ = Concat2(temp,")") ;
857                                         }
858         | allocation_expression         { $$ = $1 ; }
859         ;
860
861
862     /* Note that I could have moved the  newstore  productions  to  a 
863     lower  precedence  level  than  multiplication  (binary '*'), and 
864     lower than bitwise AND (binary '&').  These moves  are  the  nice 
865     way  to  disambiguate a trailing unary '*' or '&' at the end of a 
866     freestore expression.  Since the freestore expression (with  such 
867     a  grammar  and  hence  precedence  given)  can never be the left 
868     operand of a binary '*' or '&', the ambiguity would  be  removed. 
869     These  problems  really  surface when the binary operators '*' or 
870     '&' are overloaded, but this must be syntactically  disambiguated 
871     before the semantic checking is performed...  Unfortunately, I am 
872     not  creating  the language, only writing a grammar that reflects 
873     its specification, and  hence  I  cannot  change  its  precedence 
874     assignments.   If  I  had  my  druthers,  I would probably prefer 
875     surrounding the type with parens all the time, and  avoiding  the 
876     dangling * and & problem all together.*/
877
878        /* Following are C++, not ANSI C */
879 allocation_expression:
880         global_opt_scope_opt_operator_new '(' type_name ')'
881                 operator_new_initializer_opt
882         {       OutputNewChareMsg($3, $5, NULL) ; }
883
884         | global_opt_scope_opt_operator_new '(' argument_expression_list ')' '(' type_name ')' operator_new_initializer_opt
885           {     OutputNewChareMsg($6, $8, $3) ; }
886
887                 /* next two rules are the source of * and & ambiguities */
888         | global_opt_scope_opt_operator_new operator_new_type
889           {     OutputNewChareMsg(NewType, $2, NULL) ;}
890
891         | global_opt_scope_opt_operator_new '(' argument_expression_list ')' operator_new_type
892           {     OutputNewChareMsg(NewType, $5, $3) ; }
893         ;
894
895
896        /* Following are C++, not ANSI C */
897 global_opt_scope_opt_operator_new:
898         NEW                     { NewOpType = NEW ; }
899         | NEWCHARE              { NewOpType = NEWCHARE ; }
900         | NEWGROUP              { NewOpType = NEWGROUP ; }
901         | global_or_scope NEW   { NewOpType = NEW ; }
902         ;
903
904 operator_new_type:
905         type_qualifier_list              operator_new_declarator_opt
906                         operator_new_initializer_opt
907
908         | non_elaborating_type_specifier operator_new_declarator_opt
909                         operator_new_initializer_opt
910           {     NewType = (char *)malloc(strlen($1)+1) ;
911                 strcpy(NewType, $1) ;
912                 $$ = $3 ;
913           }
914                 
915         ;
916
917     
918     /*  Right  recursion  is critical in the following productions to 
919     avoid a conflict on TYPEDEFname */
920
921 operator_new_declarator_opt:
922         /* Nothing */ { FoundDeclarator = FALSE; }
923         | operator_new_array_declarator         
924           { FoundDeclarator = TRUE; }
925         | asterisk_or_ampersand operator_new_declarator_opt             
926           { FoundDeclarator = TRUE; }
927         | unary_modifier        operator_new_declarator_opt             
928           { FoundDeclarator = TRUE; }
929         ;
930
931 operator_new_array_declarator:
932                                         '['                  ']'
933         |                               '[' comma_expression ']'
934         | operator_new_array_declarator '[' comma_expression ']'
935         ;
936
937 operator_new_initializer_opt:
938         /* Nothing */                           { $$ = NULL ; }
939         | '('                          ')'      { $$ = NULL ; }
940         | '(' argument_expression_list ')'      { $$ = $2 ; }
941         ;
942
943 cast_expression:
944         unary_expression        { $$=$1 ; }
945         | '(' type_name ')' cast_expression
946           { char *temp = Concat3("(",$2,")") ; 
947             $$ = Concat2(temp,$4) ;
948           }
949         ;
950
951
952     /* Following are C++, not ANSI C */
953 deallocation_expression:
954         cast_expression { $$=$1 ; }
955         | global_opt_scope_opt_delete deallocation_expression
956         | global_opt_scope_opt_delete '[' comma_expression ']' deallocation_expression  /* archaic C++, what a concept */
957         | global_opt_scope_opt_delete '[' ']' deallocation_expression
958         ;
959
960
961     /* Following are C++, not ANSI C */
962 global_opt_scope_opt_delete:
963         DELETE
964         | global_or_scope DELETE
965         ;
966
967
968     /* Following are C++, not ANSI C */
969 point_member_expression:
970         deallocation_expression { $$=$1 ; }
971         | point_member_expression DOTstar  deallocation_expression
972           { $$ = Concat3($1,".*",$3) ; }
973         | point_member_expression ARROWstar  deallocation_expression
974           { $$ = Concat3($1,"->*",$3) ; }
975         ;
976
977 multiplicative_expression:
978         point_member_expression { $$=$1 ; }
979         | multiplicative_expression '*' point_member_expression
980           { $$ = Concat3($1,"*",$3) ; }
981         | multiplicative_expression '/' point_member_expression
982           { $$ = Concat3($1,"/",$3) ; }
983         | multiplicative_expression '%' point_member_expression
984           { $$ = Concat3($1,"%",$3) ; }
985         ;
986
987 additive_expression:
988         multiplicative_expression       { $$=$1 ; }
989         | additive_expression '+' multiplicative_expression
990           { $$ = Concat3($1,"+",$3) ; }
991         | additive_expression '-' multiplicative_expression
992           { $$ = Concat3($1,"-",$3) ; }
993         ;
994
995 shift_expression:
996         additive_expression     { $$=$1 ; }
997         | shift_expression LS additive_expression
998           { $$ = Concat3($1,"<<",$3) ; }
999         | shift_expression RS additive_expression
1000           { $$ = Concat3($1,">>",$3) ; }
1001         ;
1002
1003 relational_expression:
1004         shift_expression        { $$=$1 ; }
1005         | relational_expression '<' shift_expression
1006           { $$ = Concat3($1,"<",$3) ; }
1007         | relational_expression '>' shift_expression
1008           { $$ = Concat3($1,">",$3) ; }
1009         | relational_expression LE  shift_expression
1010           { $$ = Concat3($1,"<=",$3) ; }
1011         | relational_expression GE  shift_expression
1012           { $$ = Concat3($1,">=",$3) ; }
1013         ;
1014
1015 equality_expression:
1016         relational_expression   { $$=$1 ; }
1017         | equality_expression EQ relational_expression
1018           { $$ = Concat3($1,"==",$3) ; }
1019         | equality_expression NE relational_expression
1020           { $$ = Concat3($1,"!=",$3) ; }
1021         ;
1022
1023 AND_expression:
1024         equality_expression     { $$=$1 ; }
1025         | AND_expression '&' equality_expression
1026           { $$ = Concat3($1,"&",$3) ; }
1027         ;
1028
1029 exclusive_OR_expression:
1030         AND_expression  { $$=$1 ; }
1031         | exclusive_OR_expression '^' AND_expression
1032           { $$ = Concat3($1,"^",$3) ; }
1033         ;
1034
1035 inclusive_OR_expression:
1036         exclusive_OR_expression { $$=$1 ; }
1037         | inclusive_OR_expression '|' exclusive_OR_expression
1038           { $$ = Concat3($1,"|",$3) ; }
1039         ;
1040
1041 logical_AND_expression:
1042         inclusive_OR_expression { $$=$1 ; }
1043         | logical_AND_expression ANDAND inclusive_OR_expression
1044           { $$ = Concat3($1,"&&",$3) ; }
1045         ;
1046
1047 logical_OR_expression:
1048         logical_AND_expression  { $$=$1 ; }
1049         | logical_OR_expression OROR logical_AND_expression
1050           { $$ = Concat3($1,"||",$3) ; }
1051         ;
1052
1053 conditional_expression:
1054         logical_OR_expression   { $$=$1 ; }
1055
1056         | logical_OR_expression '?' comma_expression ':'
1057                 conditional_expression
1058           { char *temp = Concat3($1,"?",$3) ;
1059             $$ = Concat3(temp,":",$5) ;
1060           }
1061         ;
1062
1063 assignment_expression:
1064         conditional_expression  { $$=$1 ; }
1065         | unary_expression assignment_operator assignment_expression
1066           { $$ = Concat3($1,CurrentAssOp,$3) ; }
1067         ;
1068
1069 assignment_operator:
1070         '='                     { $$ = $1 ; strcpy(CurrentAssOp,"=") ;}
1071         | MULTassign            { $$ = $1 ; strcpy(CurrentAssOp,"*=") ;}
1072         | DIVassign             { $$ = $1 ; strcpy(CurrentAssOp,"/=") ;}
1073         | MODassign             { $$ = $1 ; strcpy(CurrentAssOp,"%=") ;}
1074         | PLUSassign            { $$ = $1 ; strcpy(CurrentAssOp,"+=") ;}
1075         | MINUSassign           { $$ = $1 ; strcpy(CurrentAssOp,"-=") ;}
1076         | LSassign              { $$ = $1 ; strcpy(CurrentAssOp,"<<=") ;}
1077         | RSassign              { $$ = $1 ; strcpy(CurrentAssOp,">>=") ;}
1078         | ANDassign             { $$ = $1 ; strcpy(CurrentAssOp,"&=") ;}
1079         | ERassign              { $$ = $1 ; strcpy(CurrentAssOp,"^=") ;}
1080         | ORassign              { $$ = $1 ; strcpy(CurrentAssOp,"|=") ;}
1081         ;
1082
1083 comma_expression:
1084         assignment_expression   { $$=$1 ; }
1085         | comma_expression ',' assignment_expression
1086           { $$ = Concat3($1,",",$3) ; }
1087         ;
1088
1089 constant_expression:
1090         conditional_expression
1091         ;
1092
1093
1094     /* The following was used for clarity */
1095 comma_expression_opt:
1096         /* Nothing */
1097         | comma_expression
1098         ;
1099
1100
1101 /******************************* DECLARATIONS ********************************/
1102
1103
1104     /*  The  following are notably different from the ANSI C Standard 
1105     specified grammar, but  are  present  in  my  ANSI  C  compatible 
1106     grammar.  The changes were made to disambiguate typedefs presence 
1107     in   declaration_specifiers   (vs.    in   the   declarator   for 
1108     redefinition); to allow struct/union/enum/class tag  declarations 
1109     without  declarators,  and  to  better  reflect  the  parsing  of 
1110     declarations    (declarators    must     be     combined     with 
1111     declaration_specifiers  ASAP, so that they can immediately become 
1112     visible in the current scope). */
1113
1114 declaration:
1115         declaring_list ';'      
1116           {     
1117                 strcpy(CurrentDeclType,"") ;
1118                 FoundReadOnly = FALSE ;
1119           }
1120                                   
1121         | default_declaring_list ';'
1122           {     
1123                 strcpy(CurrentDeclType,"") ;
1124                 FoundReadOnly = FALSE ;
1125           }
1126         | sue_declaration_specifier ';' { /* this is constraint error, as it
1127                                         includes a storage class!?!*/ }
1128         | sue_type_specifier ';'
1129         | sue_type_specifier_elaboration ';'
1130         | error  ';'    { FLUSHBUF() ; }
1131         ;
1132
1133
1134     /* Note that if a typedef were  redeclared,  then  a  declaration 
1135     specifier  must be supplied (re: ANSI C spec).  The following are 
1136     declarations wherein no declaration_specifier  is  supplied,  and 
1137     hence the 'default' must be used.  An example of this is
1138
1139         const a;
1140
1141     which by default, is the same as:
1142
1143         const int a;
1144
1145     `a' must NOT be a typedef in the above example. */
1146
1147
1148     /*  The  presence of `{}' in the following rules indicates points 
1149     at which the symbol table MUST be updated so that  the  tokenizer 
1150     can  IMMEDIATELY  continue  to  maintain  the  proper distinction 
1151     between a TYPEDEFname and an IDENTIFIER. */
1152
1153 default_declaring_list:  /* Can't  redeclare typedef names */
1154         declaration_qualifier_list   identifier_declarator {} initializer_opt
1155         | type_qualifier_list        identifier_declarator {} initializer_opt
1156         | default_declaring_list ',' identifier_declarator {} initializer_opt
1157
1158         | declaration_qualifier_list constructed_identifier_declarator
1159         | type_qualifier_list        constructed_identifier_declarator
1160         | default_declaring_list ',' constructed_identifier_declarator
1161         ;
1162
1163
1164     /* Note how type_qualifier_list is  NOT  used  in  the  following 
1165     productions.    Qualifiers   are   NOT   sufficient  to  redefine 
1166     typedef-names (as prescribed by the ANSI C standard).*/
1167
1168 declaring_list:
1169         declaration_specifier          declarator 
1170         {       strcpy(CurrentDeclType,$1) ;
1171                 if ( CurrentStorage == TYPEDEF ) {
1172                         InsertSymTable($2) ;
1173                 }
1174                 else if ( CurrentStorage == EXTERN && CurrentScope == 0 
1175                           && FoundParms )
1176                         InsertFunctionTable($2,FALSE) ;
1177                 else if ( FoundReadOnly && CurrentStorage != EXTERN ) {
1178                         if ( FoundInMsgTable($1) != -1 )
1179                                 CurrentAggType = READMSG ;
1180                         else 
1181                                 CurrentAggType = READONLY ;
1182                         InsertObjTable($2) ;
1183                 }
1184                 CurrentStorage = -1 ;
1185         } 
1186         initializer_opt
1187         | type_specifier               declarator 
1188           {     strcpy(CurrentDeclType,$1) ; 
1189                 if ( FoundReadOnly && CurrentStorage != EXTERN ) {
1190                         if ( FoundInMsgTable($1) != -1 )
1191                                 CurrentAggType = READMSG ;
1192                         else
1193                                 CurrentAggType = READONLY ;
1194                         InsertObjTable($2) ;
1195                 }
1196                 CurrentStorage = -1 ;
1197           } initializer_opt
1198         | basic_type_name              declarator 
1199           {strcpy(CurrentDeclType,$1) ;} initializer_opt
1200         | TYPEDEFname                  declarator 
1201           {     strcpy(CurrentDeclType,$1) ;
1202                 if ( strcmp($1,"table")==0 ) {
1203                         CurrentAggType = DTABLE ;
1204                         InsertObjTable($2) ;
1205                 }
1206           }
1207           initializer_opt
1208         | global_or_scoped_typedefname declarator 
1209           {strcpy(CurrentDeclType,$1) ;} initializer_opt
1210         | declaring_list ','           declarator 
1211           {     if ( FoundReadOnly && CurrentStorage != EXTERN ) {
1212                         if ( FoundInMsgTable(CurrentDeclType) != -1 )
1213                                 CurrentAggType = READMSG ;
1214                         else
1215                                 CurrentAggType = READONLY ;
1216                         InsertObjTable($3) ;
1217                 }
1218                 else if ( strcmp(CurrentDeclType,"table")==0 ) {
1219                         CurrentAggType = DTABLE ;
1220                         InsertObjTable($3) ;
1221                 }
1222                 CurrentStorage = -1 ;
1223           } initializer_opt
1224
1225         | declaration_specifier        constructed_declarator
1226         | type_specifier               constructed_declarator
1227         | basic_type_name              constructed_declarator
1228         | TYPEDEFname                  constructed_declarator
1229         | global_or_scoped_typedefname constructed_declarator
1230         | declaring_list ','           constructed_declarator
1231         ;
1232
1233
1234     /* Declarators with  parenthesized  initializers  present  a  big 
1235     problem.  Typically  a  declarator  that looks like: "*a(...)" is 
1236     supposed to bind FIRST to the "(...)", and then to the "*".  This 
1237     binding  presumes  that  the  "(...)" stuff is a prototype.  With 
1238     constructed declarators, we must (officially) finish the  binding 
1239     to the "*" (finishing forming a good declarator) and THEN connect 
1240     with  the argument list. Unfortunately, by the time we realize it 
1241     is an argument list (and not a  prototype)  we  have  pushed  the 
1242     separate  declarator  tokens  "*"  and  "a"  onto  the yacc stack 
1243     WITHOUT combining them. The solution is to use odd productions to 
1244     carry  the  incomplete  declarator  along  with   the   "argument 
1245     expression  list" back up the yacc stack.  We would then actually 
1246     instantiate the symbol table after we have  fully  decorated  the 
1247     symbol  with all the leading "*" stuff.  Actually, since we don't 
1248     have all the type information in one spot till  we  reduce  to  a 
1249     declaring_list,  this delay is not a problem.  Note that ordinary 
1250     initializers REQUIRE (ANSI C Standard) that the symbol be  placed 
1251     into  the symbol table BEFORE its initializer is read, but in the 
1252     case of parenthesized initializers,  this  is  not  possible  (we 
1253     don't  even  know  we  have  an  initializer till have passed the 
1254     opening "(". ) */
1255
1256 constructed_declarator:
1257         nonunary_constructed_identifier_declarator
1258         | constructed_paren_typedef_declarator
1259         | simple_paren_typedef_declarator '(' argument_expression_list ')'
1260
1261         | simple_paren_typedef_declarator postfixing_abstract_declarator
1262                                           '(' argument_expression_list ')'  /* constraint error */
1263
1264         | constructed_parameter_typedef_declarator
1265         | asterisk_or_ampersand constructed_declarator
1266         | unary_modifier        constructed_declarator
1267         ;
1268
1269 constructed_paren_typedef_declarator:
1270         '(' paren_typedef_declarator ')'
1271                     '(' argument_expression_list ')'
1272
1273         | '(' paren_typedef_declarator ')' postfixing_abstract_declarator
1274                    '(' argument_expression_list ')'
1275
1276         | '(' simple_paren_typedef_declarator postfixing_abstract_declarator ')'
1277                    '(' argument_expression_list ')'
1278
1279         | '(' TYPEDEFname postfixing_abstract_declarator ')'
1280                    '(' argument_expression_list ')'
1281         ;
1282
1283
1284 constructed_parameter_typedef_declarator:
1285         TYPEDEFname    '(' argument_expression_list ')'
1286
1287         | TYPEDEFname  postfixing_abstract_declarator
1288                        '(' argument_expression_list ')'  /* constraint error */
1289
1290         | '(' clean_typedef_declarator ')'
1291                        '(' argument_expression_list ')'
1292
1293         | '(' clean_typedef_declarator ')'  postfixing_abstract_declarator
1294                        '(' argument_expression_list ')'
1295         ;
1296
1297
1298 constructed_identifier_declarator:
1299         nonunary_constructed_identifier_declarator
1300         | asterisk_or_ampersand constructed_identifier_declarator
1301         | unary_modifier        constructed_identifier_declarator
1302         ;
1303
1304
1305     /* The following are restricted to NOT  begin  with  any  pointer 
1306     operators.   This  includes both "*" and "T::*" modifiers.  Aside 
1307     from  this  restriction,   the   following   would   have   been: 
1308     identifier_declarator '(' argument_expression_list ')' */
1309
1310 nonunary_constructed_identifier_declarator:
1311         paren_identifier_declarator   '(' argument_expression_list ')'
1312
1313         | paren_identifier_declarator postfixing_abstract_declarator
1314                        '(' argument_expression_list ')'  /* constraint error*/
1315
1316         | '(' unary_identifier_declarator ')'
1317                        '(' argument_expression_list ')'
1318
1319         | '(' unary_identifier_declarator ')' postfixing_abstract_declarator
1320                        '(' argument_expression_list ')'
1321         ;
1322
1323
1324 declaration_specifier:
1325         basic_declaration_specifier  {$$=$1;}     /* Arithmetic or void */
1326         | sue_declaration_specifier               /* struct/union/enum/class */
1327           { $$ = (char *)malloc(sizeof(char)*2) ;
1328             strcpy($$,"") ; 
1329           }
1330         | typedef_declaration_specifier {$$=$1;}  /* typedef*/
1331         ;
1332
1333 type_specifier:
1334         basic_type_specifier   {$$ = $1;}    /* Arithmetic or void */
1335         | sue_type_specifier                 /* Struct/Union/Enum/Class */
1336         | sue_type_specifier_elaboration     /* elaborated Struct/Union/Enum/Class */
1337         | typedef_type_specifier  {$$ = $1;} /* Typedef */
1338         ;
1339
1340 declaration_qualifier_list:  /* storage class and optional const/volatile */
1341         storage_class
1342         | type_qualifier_list storage_class
1343         | declaration_qualifier_list declaration_qualifier
1344         ;
1345
1346 type_qualifier_list:
1347         type_qualifier
1348         | type_qualifier_list type_qualifier
1349         ;
1350
1351 declaration_qualifier:
1352         storage_class
1353         | type_qualifier                  /* const or volatile */
1354         ;
1355
1356 type_qualifier:
1357         CONST
1358         | VOLATILE
1359         | READONLY      
1360         { if ( CurrentScope > 0 ) 
1361                 CharmError("readonly variables allowed only at file scope") ;
1362           else 
1363                 FoundReadOnly = TRUE ;
1364         }
1365         ;
1366
1367 basic_declaration_specifier:      /*Storage Class+Arithmetic or void*/
1368         declaration_qualifier_list    basic_type_name   { $$ = $2 ; }
1369         | basic_type_specifier        storage_class     { $$ = $1 ; }
1370         | basic_type_name             storage_class     { $$ = $1 ; }
1371         | basic_declaration_specifier declaration_qualifier     { $$ = $1 ; }
1372         | basic_declaration_specifier basic_type_name   { $$ = $1 ; }
1373         ;
1374
1375 basic_type_specifier:
1376         type_qualifier_list    basic_type_name /* Arithmetic or void */ 
1377           { $$ = $1 ; }
1378         | basic_type_name      basic_type_name  { $$ = $1 ; }
1379         | basic_type_name      type_qualifier   { $$ = $1 ; }
1380         | basic_type_specifier type_qualifier   { $$ = $1 ; }
1381         | basic_type_specifier basic_type_name  { $$ = $1 ; }
1382         ;
1383
1384 sue_declaration_specifier:          /* Storage Class + struct/union/enum/class */
1385         declaration_qualifier_list       elaborated_type_name
1386         | declaration_qualifier_list     elaborated_type_name_elaboration
1387         | sue_type_specifier             storage_class
1388         | sue_type_specifier_elaboration storage_class
1389         | sue_declaration_specifier      declaration_qualifier
1390         ;
1391
1392 sue_type_specifier_elaboration:
1393         elaborated_type_name_elaboration     /* elaborated struct/union/enum/class */
1394         | type_qualifier_list elaborated_type_name_elaboration
1395         | sue_type_specifier_elaboration type_qualifier
1396         ;
1397
1398 sue_type_specifier:
1399         elaborated_type_name              /* struct/union/enum/class */
1400         | type_qualifier_list elaborated_type_name
1401         | sue_type_specifier type_qualifier
1402         ;
1403
1404 typedef_declaration_specifier:       /*Storage Class + typedef types */
1405         declaration_qualifier_list   TYPEDEFname        { $$ = $2; }
1406         | declaration_qualifier_list global_or_scoped_typedefname  { $$ = $2; }
1407         | typedef_type_specifier       storage_class    { $$ = $1; }
1408         | TYPEDEFname                  storage_class    { $$ = $1; }
1409         | global_or_scoped_typedefname storage_class    { $$ = $1; }
1410         | typedef_declaration_specifier declaration_qualifier  { $$ = $1; }
1411         ;
1412
1413 typedef_type_specifier:              /* typedef types */
1414         type_qualifier_list      TYPEDEFname                    { $$ = $2 ; }
1415         | type_qualifier_list    global_or_scoped_typedefname   { $$ = $2 ; }
1416
1417         | TYPEDEFname                  type_qualifier           { $$ = $1 ; }
1418         | global_or_scoped_typedefname type_qualifier           { $$ = $1 ; }
1419
1420         | typedef_type_specifier type_qualifier                 { $$ = $1 ; }
1421         ;
1422
1423
1424 /*  There  are  really  several distinct sets of storage_classes. The 
1425 sets vary depending on whether the declaration is at file scope, is a 
1426 declaration within a struct/class, is within a function body, or in a 
1427 function declaration/definition (prototype  parameter  declarations).  
1428 They   are   grouped  here  to  simplify  the  grammar,  and  can  be 
1429 semantically checked.  Note that this  approach  tends  to  ease  the 
1430 syntactic restrictions in the grammar slightly, but allows for future 
1431 language  development,  and tends to provide superior diagnostics and 
1432 error recovery (i_e.: a syntax error does not disrupt the parse).
1433
1434
1435                 File    File    Member  Member  Local   Local  Formal
1436                 Var     Funct   Var     Funct   Var     Funct  Params
1437 TYPEDEF         x       x       x       x       x       x
1438 EXTERN          x       x                       x       x
1439 STATIC          x       x       x       x       x
1440 AUTO                                            x              x
1441 REGISTER                                        x              x
1442 FRIEND                                  x
1443 OVERLOAD                x               x               x
1444 INLINE                  x               x               x
1445 VIRTUAL                                 x               x
1446 */
1447
1448 storage_class:
1449         EXTERN          { CurrentStorage = EXTERN ; }
1450         | TYPEDEF       { CurrentStorage = TYPEDEF ; }
1451         | STATIC        { CurrentStorage = STATIC ; }
1452         | AUTO          { CurrentStorage = AUTO ; }
1453         | REGISTER      { CurrentStorage = REGISTER ; }
1454         | FRIEND   /* C++, not ANSI C */        { CurrentStorage = FRIEND ; }
1455         | OVERLOAD /* C++, not ANSI C */        { CurrentStorage = OVERLOAD ; }
1456         | INLINE   /* C++, not ANSI C */        { CurrentStorage = INLINE ; 
1457                                                   CurrentFnIsInline = TRUE ;
1458                                                 }
1459         | UNDERSCORE_INLINE   /* C++, not ANSI C */     { CurrentStorage = INLINE ; }
1460         | VIRTUAL  /* C++, not ANSI C */        { CurrentStorage = VIRTUAL ; }
1461         ;
1462
1463 basic_type_name:
1464         INT             { $$ = (char *)malloc(4) ; 
1465                           strcpy($$,"int") ;       }
1466         | CHAR          { $$ = (char *)malloc(5) ; 
1467                           strcpy($$,"char") ;      }
1468         | SHORT         { $$ = (char *)malloc(6) ; 
1469                           strcpy($$,"short") ;     }
1470         | LONG          { $$ = (char *)malloc(5) ; 
1471                           strcpy($$,"long") ;      }
1472         | FLOAT         { $$ = (char *)malloc(6) ; 
1473                           strcpy($$,"float") ;     }
1474         | PTRDIFF_TOKEN { $$ = (char *)malloc(10) ; 
1475                           strcpy($$,"ptrdiff_t") ; }
1476         | WCHAR_TOKEN   { $$ = (char *)malloc(10) ; 
1477                           strcpy($$,"wchar_t") ; }
1478         | __WCHAR_TOKEN { $$ = (char *)malloc(10) ; 
1479                           strcpy($$,"__wchar_t") ; }
1480         | DOUBLE        { $$ = (char *)malloc(7) ; 
1481                           strcpy($$,"double") ;    }
1482         | SIGNED        { $$ = (char *)malloc(7) ; 
1483                           strcpy($$,"signed") ;    }
1484         | UNSIGNED      { $$ = (char *)malloc(9) ; 
1485                           strcpy($$,"unsigned") ;  }
1486         | VOID          { $$ = (char *)malloc(5) ; 
1487                           strcpy($$,"void") ;      }
1488         ;
1489
1490 elaborated_type_name_elaboration:
1491         aggregate_name_elaboration
1492         | enum_name_elaboration
1493         ;
1494
1495 elaborated_type_name:
1496         aggregate_name
1497         | enum_name
1498         ;
1499
1500
1501     /* Since the expression "new type_name" MIGHT use  an  elaborated 
1502     type  and a derivation, it MIGHT have a ':'.  This fact conflicts 
1503     with the requirement that a new expression can be placed  between 
1504     a '?' and a ':' in a conditional expression (at least it confuses 
1505     LR(1)   parsers).   Hence   the   aggregate_name_elaboration   is 
1506     responsible for a series of SR conflicts on ':'.*/
1507
1508     /* The intermediate actions {}  represent  points  at  which  the 
1509     database  of  typedef  names  must  be  updated  in C++.  This is 
1510     critical to the lexer, which must begin to tokenize based on this 
1511     new information. */
1512
1513 aggregate_name_elaboration:
1514         aggregate_name derivation_opt  
1515         {       if ( CurrentAggType == CHARE ) {
1516                         FLUSHBUF() ;    
1517                         if ( numparents == 0  )
1518                                 fprintf(outfile," : public _CK_Object ") ;
1519                 }
1520                 /*
1521                 else if ( CurrentAggType == BRANCHED ) {
1522                         FLUSHBUF() ;    
1523                         if ( numparents == 0  )
1524                                 fprintf(outfile," : public _CK_BOC ") ;
1525                 }
1526                 */
1527                 else if ( CurrentAggType == ACCUMULATOR ) {
1528                         FLUSHBUF() ;    
1529                         if ( numparents == 0  )
1530                                 fprintf(outfile," : public _CK_Accumulator ") ;
1531                 }
1532                 else if ( CurrentAggType == MONOTONIC ) {
1533                         FLUSHBUF() ;    
1534                         if ( numparents == 0  )
1535                                 fprintf(outfile," : public _CK_Monotonic ") ;
1536                 }
1537                 else if ( CurrentAggType == MESSAGE ) {
1538                         FLUSHBUF() ;    
1539                         if ( numparents == 0  )
1540                                 fprintf(outfile," : public comm_object ") ;
1541                 }
1542         } 
1543         '{' 
1544         {       int num, i ;    
1545                 ChareInfo *chare ;
1546                 char *mymsg ;
1547                 char *myacc ;
1548
1549                 FLUSHBUF() ;
1550
1551                 
1552                 if ( CurrentAggType != CHARE )
1553                         InsertObjTable($1) ;
1554                 else {
1555                         /* First find out if this is a normal chare or a BOC */
1556                         if ( numparents > 0 ) {
1557                             /* Find if any parent is "groupmember" or a BOC */
1558                             for ( i=0; i<numparents; i++ ) {
1559                                 if (strcmp(ParentArray[i], "groupmember")==0) {
1560                                     CurrentAggType = BRANCHED ;
1561                                     break ;
1562                                 }
1563                                 else if ( FoundInChareTable(BOCTable,boccount+1,ParentArray[i]) != -1 ) {
1564                                     CurrentAggType = BRANCHED ;
1565                                     break ;
1566                                 }
1567                             }
1568                         }
1569
1570                         InsertObjTable($1) ;
1571
1572
1573                         if ( shouldprint ) fprintf(outfile,"%s",prevtoken) ;
1574                         strcpy(prevtoken,"") ;
1575
1576 /***** Sanjeev 10/10/95
1577                         if ( numparents == 0 ) { * got to be a chare *
1578                             fprintf(outfile,"\n\tpublic: %s(CHARE_BLOCK *c) : _CK_Object(c) {}\n",CurrentChare) ;   
1579                         }
1580                         else {
1581                             fprintf(outfile,"\n\tpublic: %s(CHARE_BLOCK *c) : ",CurrentChare) ;   
1582                             for ( i=0; i<numparents-1; i++ ) 
1583                                 fprintf(outfile,"%s(c), ",ParentArray[i]) ;
1584                             fprintf(outfile,"%s(c) {}\n",
1585                                                    ParentArray[numparents-1]) ;
1586                         }
1587                         if ( strcmp(CurrentChare,"main") != 0 )
1588                             fprintf(outfile,"\n\t        %s() {}\n",CurrentChare) ;   
1589                         fprintf(outfile,"private:\n") ;
1590                         fprintf(outfile,"#line %d \"%s\"\n",CurrentLine,
1591                                                         CurrentFileName) ;
1592 ******/
1593
1594                          
1595                         if ( CurrentAggType == CHARE )
1596                                 chare = ChareTable[FoundInChareTable(ChareTable,charecount+1,CurrentChare)] ;
1597                         else
1598                                 chare = BOCTable[FoundInChareTable(BOCTable,boccount+1,CurrentChare)] ;
1599
1600                         for ( i=0; i<numparents; i++ ) {
1601                             if ( CurrentAggType == CHARE )
1602                                 InsertParent(chare,ParentArray[i],ChareTable,charecount+1) ;
1603                             else
1604                                 InsertParent(chare,ParentArray[i],BOCTable,boccount+1) ;
1605                         }
1606                         AddInheritedEps(chare) ;
1607                 }
1608                 numparents = 0 ; /* so that sequential class derivations dont
1609                                     affect us */
1610
1611                 CurrentAccess = PRIVATE ;
1612         } 
1613         member_declaration_list_opt     { FillPermanentAggTable($1) ; }
1614         '}'   
1615         {   FLUSHBUF() ;        
1616             if ( CurrentAggType == ACCUMULATOR || CurrentAggType == MONOTONIC )
1617             {   if ( !FilledAccMsg ) 
1618                     CharmError("Unable to detect message in accumulator/monotonic class") ;
1619                 else {
1620                     fprintf(outfile,"\npublic:void * _CK_GetMsgPtr() {\n");
1621                     fprintf(outfile,"\t\treturn((void *)%s) ;\n\t}\n",
1622                                                              CurrentAcc->msg) ;
1623                     if ( CurrentAggType == ACCUMULATOR ) {
1624                         fprintf(outfile,"\n       void _CK_Combine(void *msg) {\n");
1625                         fprintf(outfile,"\t\tCombine((%s *)msg) ;\n\t}\n",
1626                                                          CurrentAcc->msgtype) ;
1627                     }
1628                     else { /*  MONOTONIC  */
1629                         fprintf(outfile,"\n       void _CK_SysUpdate(void *msg) {\n");
1630                         fprintf(outfile,"\t\tUpdate((%s *)msg) ;\n\t}\n",
1631                                                          CurrentAcc->msgtype) ;
1632                         fprintf(outfile,"\n       %s *MonoValue() {\n",
1633                                                          CurrentAcc->msgtype) ;
1634                         fprintf(outfile,"\t\treturn( (%s *)(::MonoValue(_CK_MyId)) ) ;\n\t}\n",CurrentAcc->msgtype) ;
1635
1636
1637                         fprintf(outfile,"\n      int _CK_Update(%s *msg) {\n",
1638                                                          CurrentAcc->msgtype) ;
1639                         fprintf(outfile,"\t\tint v ;\n") ;
1640                         /* Locking not needed anymore 
1641                         fprintf(outfile,"\t\t_CK_9LockMonoDataArea(GetBocDataPtr(_CK_MyId)) ;\n") ;
1642                         */
1643                         fprintf(outfile,"\t\tv = Update(msg) ;\n") ;
1644                         /* Locking not needed anymore 
1645                         fprintf(outfile,"\t\t_CK_9UnlockMonoDataArea(GetBocDataPtr(_CK_MyId)) ;\n") ;
1646                         */
1647                         fprintf(outfile,"\t\tif ( v )\n") ;
1648                         fprintf(outfile,"\t\t\t_CK_BroadcastMono((void *)%s,_CK_MyId) ;\n",CurrentAcc->msg) ;
1649                         fprintf(outfile,"\t\treturn v ;\n\t}\n") ;
1650
1651                     }
1652                     fprintf(outfile,"\n#line %d \"%s\"\n",CurrentLine,CurrentFileName) ;
1653                 }
1654             }
1655             else if ( CurrentAggType == MESSAGE && 
1656                                      MessageTable[TotalMsgs-1].numvarsize!=0 ) 
1657             { /* Output the pack and unpack and alloc functions for varSize */
1658                 int i ;
1659
1660                 MsgStruct *thismsg = &(MessageTable[TotalMsgs-1]) ;
1661                 VarSizeStruct *vs = thismsg->varsizearray ;
1662
1663                 fprintf(outfile,"\nvoid *pack(int *length) \n\t{\n") ;
1664
1665               /*fprintf(outfile,"\n\t*length = _CK_3GetSizeOfMsg(this) ;\n");
1666                 the length (size) parm is no longer used in the PACK macro
1667                 in common/headers/communication.h : Sanjeev, 1 Sep 94 */
1668                 fprintf(outfile,"\n\t*length = 0 ;\n") ;
1669
1670                 for ( i=0; i<thismsg->numvarsize; i++ ) 
1671                         fprintf(outfile,"\n\t%s = (%s *) ((char *)%s - ((char *)&(%s)));\n",vs[i].name,vs[i].type,vs[i].name,vs[i].name) ;
1672                 fprintf(outfile,"\treturn((void *)this) ;\n}\n") ;
1673
1674                 fprintf(outfile,"\nvoid unpack() \n\t{\n") ;
1675                 for ( i=0; i<thismsg->numvarsize; i++ ) 
1676                         fprintf(outfile,"\n\t%s = (%s *) ((char *)(&%s) + (int)(%s));\n",vs[i].name,vs[i].type,vs[i].name,vs[i].name) ;
1677                 fprintf(outfile,"}\n") ;
1678
1679                 /* Output the operator delete */
1680                 fprintf(outfile,"\nvoid operator delete(void *msg) {\n") ;
1681                 fprintf(outfile,"\tCkFreeMsg(msg) ;\n}\n") ;
1682
1683                 fprintf(outfile,"#line %d \"%s\"\n",CurrentLine,CurrentFileName) ;
1684             }
1685                 
1686                 
1687             CurrentAggType = -1 ; 
1688             CurrentAccess = -1 ; 
1689             strcpy(CurrentAggName,"") ;
1690             strcpy(CurrentChare,"_CK_NOTACHARE") ;
1691             CurrentCharePtr = NULL ;
1692             InsideChareCode = 0 ;
1693         }
1694         | aggregate_key derivation_opt '{' member_declaration_list_opt '}'
1695         ;
1696
1697     /* We distinguish between the above, which  support  elaboration, 
1698     and  this  set  of  productions  so  that  we can provide special 
1699     declaration specifiers for operator_new_type, and for  conversion 
1700     functions.  Note that without this restriction a large variety of 
1701     conflicts  appear  when  processing  operator_new and conversions 
1702     operators (which can be  followed  by  a  ':'  in  a  ternary  ?: 
1703     expression) */
1704
1705     /*  Note that at the end of each of the following rules we should 
1706     be sure that the tag name is  in,  or  placed  in  the  indicated 
1707     scope.   If  no  scope  is  specified, then we must add it to our 
1708     current scope IFF it cannot  be  found  in  an  external  lexical 
1709     scope. */
1710
1711 aggregate_name:
1712                              aggregate_key tag_name 
1713           {     strcpy(CurrentAggName,$2);
1714                 InsertSymTable($2) ;
1715                 $$ = $2 ;
1716           }
1717         | global_scope scope aggregate_key tag_name 
1718           {     if ( AddedScope > 0 ) {
1719                         PopStack() ;    
1720                         AddedScope = 0 ;
1721                 }
1722                 strcpy(CurrentAggName,$4);
1723                 InsertSymTable($4) ;
1724                 $$ = $4 ;
1725           }
1726         | global_scope       aggregate_key tag_name 
1727           {     strcpy(CurrentAggName,$3);
1728                 InsertSymTable($3) ;
1729                 $$ = $3 ;
1730           }
1731         | scope              aggregate_key tag_name 
1732           {     if ( AddedScope > 0 ) {
1733                         PopStack() ;    
1734                         AddedScope = 0 ;
1735                 }
1736                 strcpy(CurrentAggName,$3);
1737                 InsertSymTable($3) ;
1738                 $$ = $3 ;
1739           }
1740         ;
1741
1742 derivation_opt:
1743         /* nothing */
1744         | ':' derivation_list
1745         | ':' error             {FLUSHBUF(); SyntaxError("class defn header");}
1746         ;
1747
1748 derivation_list:
1749         parent_class    
1750         {       ParentArray[numparents] = (char *)malloc(strlen($1)+1) ;
1751                 strcpy(ParentArray[numparents],$1) ;
1752                 numparents++ ;
1753         }                        
1754         | derivation_list ',' parent_class
1755         {       ParentArray[numparents] = (char *)malloc(strlen($3)+1) ;
1756                 strcpy(ParentArray[numparents],$3) ;
1757                 numparents++ ;
1758         }                        
1759         ;
1760
1761 parent_class:
1762                                        global_opt_scope_opt_typedefname{$$=$1;}
1763         | VIRTUAL access_specifier_opt global_opt_scope_opt_typedefname{$$=$3;}
1764         | access_specifier virtual_opt global_opt_scope_opt_typedefname{$$=$3;}
1765         ;
1766
1767 virtual_opt:
1768         /* nothing */
1769         | VIRTUAL
1770         ;
1771
1772 access_specifier_opt:
1773         /* nothing */
1774         | access_specifier
1775         ;
1776
1777 access_specifier:
1778         PUBLIC                  { CurrentAccess = PUBLIC ; }
1779         | PRIVATE               { CurrentAccess = PRIVATE ; }
1780         | PROTECTED             { CurrentAccess = PROTECTED ; }
1781         | ENTRY                 { CurrentAccess = ENTRY ; }
1782         ;
1783
1784 aggregate_key:
1785         STRUCT                  { CurrentAggType = STRUCT ; }
1786         | UNION                 { CurrentAggType = UNION ; }
1787         | CLASS /* C++, not ANSI C */   { CurrentAggType = CLASS ; }
1788         | CHARE CLASS           { CurrentAggType = CHARE ; }
1789 /*      | BRANCHED CHARE CLASS  { CurrentAggType = BRANCHED ; }         */
1790         | MESSAGE CLASS         { CurrentAggType = MESSAGE ; }
1791         | ACCUMULATOR CLASS     { CurrentAggType = ACCUMULATOR ; 
1792                                   FilledAccMsg=FALSE; }
1793         | MONOTONIC CLASS       { CurrentAggType = MONOTONIC ; 
1794                                   FilledAccMsg=FALSE; }
1795         ;
1796
1797
1798     /* Note that an empty list is ONLY allowed under C++. The grammar 
1799     can  be modified so that this stands out.  The trick is to define 
1800     member_declaration_list, and have that referenced for non-trivial 
1801     lists. */
1802
1803 member_declaration_list_opt:
1804         /* nothing */
1805         | member_declaration_list_opt member_declaration 
1806           { FLUSHBUF() ;}
1807         ;
1808
1809 member_declaration:
1810         member_declaring_list ';'               { strcpy(CurrentDeclType,"") ;}
1811         | member_default_declaring_list ';'     { strcpy(CurrentDeclType,"") ;}
1812
1813         | access_specifier ':'               /* C++, not ANSI C */
1814
1815         | new_function_definition            /* C++, not ANSI C */
1816         | constructor_function_in_class      /* C++, not ANSI C */
1817
1818         | sue_type_specifier             ';' /* C++, not ANSI C */
1819         | sue_type_specifier_elaboration ';' /* C++, not ANSI C */
1820         | identifier_declarator          ';' /* C++, not ANSI C
1821                                                 access modification
1822                                                 conversion functions,
1823                                                 unscoped destructors */
1824
1825         | typedef_declaration_specifier ';' /* friend T */       /* C++, not ANSI C */
1826         | sue_declaration_specifier ';'     /* friend class C*/  /* C++, not ANSI C */
1827         ;
1828
1829 member_default_declaring_list:        /* doesn't redeclare typedef*/
1830         type_qualifier_list
1831                 identifier_declarator member_pure_opt
1832
1833         | declaration_qualifier_list
1834                 identifier_declarator member_pure_opt /* C++, not ANSI C */
1835
1836         | member_default_declaring_list ','
1837                 identifier_declarator member_pure_opt
1838
1839         | type_qualifier_list                bit_field_identifier_declarator
1840         | declaration_qualifier_list         bit_field_identifier_declarator /* C++, not ANSI C */
1841         | member_default_declaring_list ','  bit_field_identifier_declarator
1842         ;
1843
1844
1845     /* There is a conflict when "struct A" is used as  a  declaration 
1846     specifier,  and  there  is a chance that a bit field name will be 
1847     provided.  To fix this syntactically would require distinguishing 
1848     non_elaborating_declaration_specifiers   the   way   I    handled 
1849     non_elaborating_type_specifiers.   I   think  this  should  be  a 
1850     constraint error anyway :-). */
1851
1852 member_declaring_list:        /* Can possibly redeclare typedefs */
1853         type_specifier                 declarator member_pure_opt
1854           {strcpy(CurrentDeclType,$1) ; 
1855            if (FoundParms&&(CurrentAggType==CHARE||CurrentAggType==BRANCHED)) {
1856                 if ( CurrentAccess == PRIVATE || CurrentAccess == PUBLIC )
1857                     ProcessFn($2) ;
1858            }
1859           }
1860         | basic_type_name              declarator 
1861           {int ind ;
1862            if ( FoundParms ) {
1863              if (CurrentAggType==CHARE || CurrentAggType==BRANCHED) {
1864                 if ( CurrentAccess == ENTRY )
1865                     ProcessEP($2,FALSE);
1866                 else if ( CurrentAccess == PRIVATE||CurrentAccess == PUBLIC ) 
1867                     ProcessFn($2) ;
1868              }
1869              else if ( CurrentAggType == MESSAGE ) {
1870                 if ( strcmp($2,"pack")==0 || strcmp($2,"unpack")==0 ) {
1871                     if ( (ind=FoundInMsgTable(CurrentAggName)) != -1 )
1872                         MessageTable[ind].pack = TRUE ; 
1873                     else 
1874                         CharmError("TRANSLATOR : did not find message type in message table") ;
1875                 }                       
1876                 else 
1877                         CharmError("Messages are allowed to have only pack or unpack functions") ;
1878              }
1879              FoundParms = FALSE ;
1880            }
1881            else if ( CurrentAggType == MESSAGE && FoundVarSize ) {
1882                 char *varname = Mystrstr(OutBuf,$2) ;
1883                 *varname = '*' ;
1884                 *(varname+1) = '\0' ;
1885                 strcat(OutBuf,$2) ;
1886                 
1887                 InsertVarSize($1,$2) ;
1888                 FoundVarSize = FALSE ;
1889            } 
1890           }     
1891           member_pure_opt
1892
1893         | global_or_scoped_typedefname declarator member_pure_opt
1894           {strcpy(CurrentDeclType,$1) ; 
1895            if (FoundParms&&(CurrentAggType==CHARE||CurrentAggType==BRANCHED)) {
1896                 if ( CurrentAccess == PRIVATE || CurrentAccess == PUBLIC )
1897                     ProcessFn($2) ;
1898            }
1899           }
1900         | member_conflict_declaring_item
1901         | member_declaring_list ','    declarator member_pure_opt
1902
1903         | type_specifier                bit_field_declarator
1904         | basic_type_name               bit_field_declarator
1905         | TYPEDEFname                   bit_field_declarator
1906         | global_or_scoped_typedefname  bit_field_declarator
1907         | declaration_specifier         bit_field_declarator /* constraint violation: storage class used */
1908         | member_declaring_list ','     bit_field_declarator
1909         ;
1910
1911
1912     /* The following conflict with constructors-
1913       member_conflict_declaring_item:
1914         TYPEDEFname             declarator member_pure_opt
1915         | declaration_specifier declarator member_pure_opt /* C++, not ANSI C * /
1916         ;
1917     so we inline expand declarator to get the following productions...
1918     */
1919 member_conflict_declaring_item:
1920         TYPEDEFname             identifier_declarator            member_pure_opt
1921         { if ( (CurrentAggType==ACCUMULATOR || CurrentAggType==MONOTONIC) 
1922                 && !FilledAccMsg ) 
1923           {     CurrentAcc->msgtype = (char *)malloc((strlen($1)+1)*sizeof(char));
1924                 strcpy(CurrentAcc->msgtype,$1) ;        
1925
1926                 CurrentAcc->msg = (char *)malloc((strlen($2)+1)*sizeof(char)) ;
1927                 strcpy(CurrentAcc->msg,$2) ;    
1928                 FilledAccMsg = TRUE ;
1929           }
1930           else if ( CurrentAggType == MESSAGE && FoundVarSize ) {
1931                 char *varname = Mystrstr(OutBuf,$2) ;
1932                 *varname = '*' ;
1933                 *(varname+1) = '\0' ;
1934                 strcat(OutBuf,$2) ;
1935                 
1936                 if ( SearchHandleTable(ChareHandleTable,ChareHandleTableSize,$2) != -1 ) 
1937                         InsertVarSize("ChareIDType",$2) ;
1938                 else
1939                         InsertVarSize($1,$2) ;
1940                 FoundVarSize = FALSE ;
1941           } 
1942           strcpy(CurrentDeclType,$1) ;
1943         }
1944
1945         | TYPEDEFname           parameter_typedef_declarator     member_pure_opt
1946           {     strcpy(CurrentDeclType,$1) ;    }
1947         | TYPEDEFname           simple_paren_typedef_declarator  member_pure_opt
1948           {     strcpy(CurrentDeclType,$1) ;    }
1949
1950         | declaration_specifier identifier_declarator            member_pure_opt
1951           {     strcpy(CurrentDeclType,$1) ;    
1952                 if ( CurrentStorage == TYPEDEF ) {
1953                         InsertSymTable($2) ;
1954                         CurrentStorage = -1 ;
1955                 }
1956                 else if ( FoundParms ) {
1957                         if (CurrentAggType==CHARE || CurrentAggType==BRANCHED){
1958                                 if ( CurrentAccess == ENTRY ) {
1959                                         ProcessEP($2,FALSE);
1960                                 }
1961                                 else if ( CurrentAccess == PRIVATE || 
1962                                           CurrentAccess == PUBLIC )
1963                                         ProcessFn($2) ;
1964                         }       
1965                         FoundParms = FALSE ;
1966                 }
1967           }
1968         | declaration_specifier parameter_typedef_declarator     member_pure_opt
1969           {     strcpy(CurrentDeclType,$1) ;    }
1970         | declaration_specifier simple_paren_typedef_declarator  member_pure_opt
1971           {     strcpy(CurrentDeclType,$1) ;    }
1972
1973         | member_conflict_paren_declaring_item
1974         ;
1975
1976
1977     /* The following still conflicts with constructors-
1978       member_conflict_paren_declaring_item:
1979         TYPEDEFname             paren_typedef_declarator     member_pure_opt
1980         | declaration_specifier paren_typedef_declarator     member_pure_opt
1981         ;
1982     so paren_typedef_declarator is expanded inline to get...*/
1983
1984 member_conflict_paren_declaring_item:
1985         TYPEDEFname   asterisk_or_ampersand
1986                 '(' simple_paren_typedef_declarator ')' member_pure_opt
1987         | TYPEDEFname unary_modifier
1988                 '(' simple_paren_typedef_declarator ')' member_pure_opt
1989         | TYPEDEFname asterisk_or_ampersand
1990                 '(' TYPEDEFname ')'                     member_pure_opt
1991         | TYPEDEFname unary_modifier
1992                 '(' TYPEDEFname ')'                     member_pure_opt
1993         | TYPEDEFname asterisk_or_ampersand
1994                  paren_typedef_declarator               member_pure_opt
1995         | TYPEDEFname unary_modifier
1996                  paren_typedef_declarator               member_pure_opt
1997
1998         | declaration_specifier asterisk_or_ampersand
1999                 '(' simple_paren_typedef_declarator ')' member_pure_opt
2000         | declaration_specifier unary_modifier
2001                 '(' simple_paren_typedef_declarator ')' member_pure_opt
2002         | declaration_specifier asterisk_or_ampersand
2003                 '(' TYPEDEFname ')'                     member_pure_opt
2004         | declaration_specifier unary_modifier
2005                 '(' TYPEDEFname ')'                     member_pure_opt
2006         | declaration_specifier asterisk_or_ampersand
2007                 paren_typedef_declarator                member_pure_opt
2008         | declaration_specifier unary_modifier
2009                 paren_typedef_declarator                member_pure_opt
2010
2011         | member_conflict_paren_postfix_declaring_item
2012         ;
2013
2014
2015     /* but we still have the following conflicts with constructors-
2016    member_conflict_paren_postfix_declaring_item:
2017       TYPEDEFname             postfix_paren_typedef_declarator member_pure_opt
2018       | declaration_specifier postfix_paren_typedef_declarator member_pure_opt
2019       ;
2020     so we expand paren_postfix_typedef inline and get...*/
2021
2022 member_conflict_paren_postfix_declaring_item:
2023         TYPEDEFname     '(' paren_typedef_declarator ')'
2024                                                            member_pure_opt
2025         | TYPEDEFname   '(' simple_paren_typedef_declarator
2026                         postfixing_abstract_declarator ')' member_pure_opt
2027         | TYPEDEFname   '(' TYPEDEFname
2028                         postfixing_abstract_declarator ')' member_pure_opt
2029         | TYPEDEFname   '(' paren_typedef_declarator ')'
2030                         postfixing_abstract_declarator     member_pure_opt
2031
2032         | declaration_specifier '(' paren_typedef_declarator ')'
2033                                                            member_pure_opt
2034         | declaration_specifier '(' simple_paren_typedef_declarator
2035                         postfixing_abstract_declarator ')' member_pure_opt
2036         | declaration_specifier '(' TYPEDEFname
2037                         postfixing_abstract_declarator ')' member_pure_opt
2038         | declaration_specifier '(' paren_typedef_declarator ')'
2039                         postfixing_abstract_declarator     member_pure_opt
2040         ;
2041     /* ...and we are done.  Now all  the  conflicts  appear  on  ';', 
2042     which can be semantically evaluated/disambiguated */
2043
2044
2045 member_pure_opt:
2046         /* nothing */
2047         | '=' OCTALconstant /* C++, not ANSI C */ /* Pure function*/
2048         ;
2049
2050
2051     /*  Note  that  bit  field  names, where redefining TYPEDEFnames, 
2052     cannot be parenthesized in C++ (due to  ambiguities),  and  hence 
2053     this  part of the grammar is simpler than ANSI C. :-) The problem 
2054     occurs because:
2055
2056          TYPEDEFname ( TYPEDEFname) : .....
2057
2058     doesn't look like a bit field, rather it looks like a constructor 
2059     definition! */
2060
2061 bit_field_declarator:
2062         bit_field_identifier_declarator
2063         | TYPEDEFname {} ':' constant_expression
2064         ;
2065
2066
2067     /* The actions taken in the "{}" above and below are intended  to 
2068     allow  the  symbol  table  to  be  updated when the declarator is 
2069     complete.  It is critical for code like:
2070
2071             foo : sizeof(foo + 1);
2072     */
2073
2074 bit_field_identifier_declarator:
2075                                    ':' constant_expression
2076         | identifier_declarator {} ':' constant_expression
2077         ;
2078
2079 enum_name_elaboration:
2080         global_opt_scope_opt_enum_key '{' enumerator_list '}'
2081         | enum_name                   '{' enumerator_list '}'
2082         ;
2083
2084
2085     /* As with structures, the distinction between "elaborating"  and 
2086     "non-elaborating"  enum  types  is  maintained.  In actuality, it 
2087     probably does not cause much in the way of conflicts, since a ':' 
2088     is not allowed.  For symmetry, we maintain the distinction.   The 
2089     {}  actions are intended to allow the symbol table to be updated.  
2090     These updates are significant to code such as:
2091
2092         enum A { first=sizeof(A)};
2093     */
2094
2095 enum_name:
2096         global_opt_scope_opt_enum_key tag_name  { InsertSymTable($2) ; }
2097         ;
2098
2099 global_opt_scope_opt_enum_key:
2100         ENUM
2101         | global_or_scope ENUM
2102         ;
2103
2104 enumerator_list:
2105         enumerator_list_no_trailing_comma
2106         | enumerator_list_no_trailing_comma ',' /* C++, not ANSI C */
2107         ;
2108
2109
2110     /* Note that we do not need to rush to add an enumerator  to  the 
2111     symbol  table  until  *AFTER* the enumerator_value_opt is parsed. 
2112     The enumerated value is only in scope  AFTER  its  definition  is 
2113     complete.   Hence the following is legal: "enum {a, b=a+10};" but 
2114     the following is (assuming no external matching of names) is  not 
2115     legal:  "enum {c, d=sizeof(d)};" ("d" not defined when sizeof was 
2116     applied.) This is  notably  contrasted  with  declarators,  which 
2117     enter scope as soon as the declarator is complete. */
2118
2119 enumerator_list_no_trailing_comma:
2120         enumerator_name enumerator_value_opt
2121         | enumerator_list_no_trailing_comma ',' enumerator_name enumerator_value_opt
2122         ;
2123
2124 enumerator_name:
2125         IDENTIFIER
2126         | TYPEDEFname
2127         ;
2128
2129 enumerator_value_opt:
2130         /* Nothing */
2131         | '=' constant_expression
2132         ;
2133
2134
2135     /*  We special case the lone type_name which has no storage class 
2136     (even though it should be an example of  a  parameter_type_list). 
2137     This helped to disambiguate type-names in parenthetical casts.*/
2138
2139 parameter_type_list:
2140         '(' ')'                             type_qualifier_list_opt
2141         | '(' type_name ')'                 type_qualifier_list_opt
2142           {     EpMsg=$2; 
2143           }
2144         | '(' type_name initializer ')'     type_qualifier_list_opt /* C++, not ANSI C */
2145         | '(' named_parameter_type_list ')' type_qualifier_list_opt 
2146                         
2147         ;
2148
2149
2150     /* The following are used in old style function definitions, when 
2151     a complex return type includes the "function returning" modifier. 
2152     Note  the  subtle  distinction  from  parameter_type_list.  These 
2153     parameters are NOT the parameters for the function being defined, 
2154     but are simply part of the type definition.  An example would be:
2155
2156         int(*f(   a  ))(float) long a; {...}
2157
2158     which is equivalent to the full new style definition:
2159
2160         int(*f(long a))(float) {...}
2161
2162     The   type   list    `(float)'    is    an    example    of    an 
2163     old_parameter_type_list.   The  bizarre point here is that an old 
2164     function definition declarator can be followed by  a  type  list, 
2165     which  can  start  with a qualifier `const'.  This conflicts with 
2166     the new syntactic construct for const member  functions!?!  As  a 
2167     result,  an  old  style function definition cannot be used in all 
2168     cases for a member function.  */
2169
2170 old_parameter_type_list:
2171         '(' ')'
2172         | '(' type_name ')'
2173         | '(' type_name initializer ')'  /* C++, not ANSI C */
2174         | '(' named_parameter_type_list ')'
2175         ;
2176
2177 named_parameter_type_list:  /* WARNING: excludes lone type_name*/
2178         parameter_list
2179         | parameter_list comma_opt_ellipsis
2180         | type_name comma_opt_ellipsis
2181         | type_name initializer comma_opt_ellipsis  /* C++, not ANSI C */
2182         | ELLIPSIS /* C++, not ANSI C */
2183         ;
2184
2185 comma_opt_ellipsis:
2186         ELLIPSIS       /* C++, not ANSI C */
2187         | ',' ELLIPSIS
2188         ;
2189
2190 parameter_list:
2191         non_casting_parameter_declaration
2192         | non_casting_parameter_declaration initializer /* C++, not ANSI C */
2193         | type_name             ',' parameter_declaration
2194         | type_name initializer ',' parameter_declaration  /* C++, not ANSI C */
2195         | parameter_list        ',' parameter_declaration
2196         ;
2197
2198
2199     /* There is some very subtle disambiguation going  on  here.   Do 
2200     not be tempted to make further use of the following production in 
2201     parameter_list,  or else the conflict count will grow noticeably. 
2202     Specifically, the next set  of  rules  has  already  been  inline 
2203     expanded for the first parameter in a parameter_list to support a 
2204     deferred disambiguation. The subtle disambiguation has to do with 
2205     contexts where parameter type lists look like old-style-casts. */
2206
2207 parameter_declaration:
2208         type_name
2209         | type_name                         initializer  /* C++, not ANSI C */
2210         | non_casting_parameter_declaration
2211         | non_casting_parameter_declaration initializer /* C++, not ANSI C */
2212         ;
2213
2214
2215     /* There is an LR ambiguity between old-style parenthesized casts 
2216     and parameter-type-lists.  This tends to happen in contexts where 
2217     either  an  expression or a parameter-type-list is possible.  For 
2218     example, assume that T is an  externally  declared  type  in  the 
2219     code:
2220
2221            int (T ((int
2222
2223     it might continue:
2224
2225            int (T ((int)0));
2226
2227     which would make it:
2228
2229            (int) (T) (int)0 ;
2230
2231     which  is  an  expression,  consisting  of  a  series  of  casts.  
2232     Alternatively, it could be:
2233
2234            int (T ((int a)));
2235
2236     which would make it the redeclaration of T, equivalent to:
2237
2238            int T (dummy_name (int a));
2239
2240     if we see a type that either has a named variable (in  the  above 
2241     case "a"), or a storage class like:
2242
2243            int (T ((int register
2244
2245     then  we  know  it  can't  be  a cast, and it is "forced" to be a 
2246     parameter_list.
2247
2248     It is not yet clear that the ANSI C++ committee would  decide  to 
2249     place this disambiguation into the syntax, rather than leaving it 
2250     as  a  constraint check (i.e., a valid parser would have to parse 
2251     everything as though it were  a  parameter  list  (in  these  odd 
2252     contexts),  and  then  give an error if is to a following context 
2253     (like "0" above) that invalidated this syntax evaluation. */
2254
2255     /* One big thing implemented here is that a TYPEDEFname CANNOT be 
2256     redeclared when we don't have declaration_specifiers! Notice that 
2257     when we do use a TYPEDEFname based declarator, only the "special" 
2258     (non-ambiguous  in  this  context)  typedef_declarator  is  used. 
2259     Everything else that is "missing" shows up as a type_name. */
2260
2261 non_casting_parameter_declaration: /*have names or storage classes */
2262         declaration_specifier
2263         | declaration_specifier abstract_declarator
2264         | declaration_specifier identifier_declarator
2265         | declaration_specifier parameter_typedef_declarator
2266
2267         | declaration_qualifier_list
2268         | declaration_qualifier_list abstract_declarator
2269         | declaration_qualifier_list identifier_declarator
2270
2271         | type_specifier identifier_declarator
2272         | type_specifier parameter_typedef_declarator
2273
2274         | basic_type_name identifier_declarator
2275         | basic_type_name parameter_typedef_declarator
2276
2277         | TYPEDEFname     identifier_declarator         
2278           {     EpMsg=$1; 
2279                 strcpy(CurrentMsgParm,$1) ;
2280           }
2281         | TYPEDEFname     parameter_typedef_declarator 
2282           {     EpMsg=$1; 
2283                 strcpy(CurrentMsgParm,$1) ;
2284           }
2285
2286         | global_or_scoped_typedefname  identifier_declarator
2287         | global_or_scoped_typedefname  parameter_typedef_declarator
2288
2289         | type_qualifier_list identifier_declarator
2290         ;
2291
2292 type_name:
2293         type_specifier
2294         | basic_type_name               
2295         | TYPEDEFname                   { $$ = $1 ; }
2296         | global_or_scoped_typedefname
2297         | type_qualifier_list
2298
2299         | type_specifier               abstract_declarator
2300         | basic_type_name              abstract_declarator
2301         | TYPEDEFname                  abstract_declarator
2302         | global_or_scoped_typedefname abstract_declarator
2303         | type_qualifier_list          abstract_declarator
2304         ;
2305
2306 initializer_opt:
2307         /* nothing */
2308         | initializer
2309         ;
2310
2311 initializer:
2312         '=' initializer_group
2313         ;
2314
2315 initializer_group:
2316         '{' initializer_list '}'
2317         | '{' initializer_list ',' '}'
2318         | assignment_expression
2319         ;
2320
2321 initializer_list:
2322         initializer_group
2323         | initializer_list ',' initializer_group
2324         ;
2325
2326
2327 /*************************** STATEMENTS *******************************/
2328
2329 statement:
2330         labeled_statement
2331         | compound_statement
2332         | expression_statement
2333         | selection_statement
2334         | iteration_statement
2335         | jump_statement
2336         | declaration /* C++, not ANSI C */
2337         ;
2338
2339 labeled_statement:
2340         label                      ':' statement
2341         | CASE constant_expression ':' statement
2342         | DEFAULT                  ':' statement
2343         ;
2344
2345
2346     /*  I sneak declarations into statement_list to support C++.  The 
2347     grammar is a little clumsy this  way,  but  the  violation  of  C 
2348     syntax is heavily localized */
2349
2350 compound_statement:
2351         '{' 
2352         {       if ( FoundAccFnDef ) {
2353                         strcat(OutBuf,prevtoken) ;
2354                         strcpy(prevtoken,"") ;
2355                         FLUSHBUF() ;
2356                         /* No locking needed anymore 
2357                         fprintf(outfile,"\n_CK_9LockAccDataArea(GetBocDataPtr(_CK_MyId)) ;\n") ;
2358                         */
2359                         fprintf(outfile,"\n#line %d \"%s\"\n",CurrentLine,CurrentFileName) ;
2360                         AccFnScope = CurrentScope ;
2361                         FoundAccFnDef = FALSE ;
2362                 }
2363         } 
2364         statement_list_opt 
2365         {       if ( AccFnScope == CurrentScope+1 ) {
2366                 /* +1 because the '}' has already been lexed at this point */
2367                         FLUSHBUF() ;
2368                         /* No locking needed anymore 
2369                         fprintf(outfile,"\n_CK_9UnlockAccDataArea(GetBocDataPtr(_CK_MyId)) ;\n") ;
2370                         */
2371                         fprintf(outfile,"\n#line %d \"%s\"\n",CurrentLine,CurrentFileName) ;
2372                         AccFnScope = -1 ;
2373                 }
2374         } 
2375         '}'     { FLUSHBUF() ; }
2376
2377 /*      | '{' statement_list_opt error  { FLUSHBUF() ; 
2378                                           SyntaxError("compound statement") ; }
2379           '}'
2380 this rule caused conflicts with the one above, so I removed it : SANJEEV */
2381         ;
2382
2383 declaration_list:
2384         declaration                     { FLUSHBUF() ; }
2385         | declaration_list declaration  { FLUSHBUF() ; }
2386         ;
2387
2388 statement_list_opt:
2389         /* nothing */
2390         | statement_list_opt statement  { FLUSHBUF() ; }
2391         ;
2392
2393 expression_statement:
2394         comma_expression_opt ';'
2395         ;
2396
2397 selection_statement:
2398           IF if_cond statement
2399         | IF if_cond statement ELSE statement
2400         | SWITCH if_cond statement
2401         ;
2402
2403 if_cond:
2404           '(' comma_expression ')'  { FLUSHBUF(); }
2405         | '(' error ')' { FLUSHBUF(); 
2406                           SyntaxError("if/switch condition") ;}
2407         ;
2408
2409 iteration_statement:
2410         WHILE '(' comma_expression_opt ')' {FLUSHBUF();} statement
2411         | WHILE '(' error ')'   { FLUSHBUF() ; 
2412                                   SyntaxError("while loop condition");}
2413           statement  
2414
2415         | DO statement WHILE '(' comma_expression ')' ';'
2416         | DO statement WHILE '(' error ')'      { FLUSHBUF() ; 
2417                                     SyntaxError("do loop condition"); }
2418           ';'   
2419
2420         | FOR '(' comma_expression_opt ';' comma_expression_opt ';'
2421                 comma_expression_opt ')' {FLUSHBUF();} statement
2422
2423         | FOR '(' declaration        comma_expression_opt ';'
2424                 comma_expression_opt ')' statement  /* C++, not ANSI C */
2425         | FOR '(' error ')'     { FLUSHBUF() ; 
2426                                   SyntaxError("for loop header") ; }
2427           statement     
2428         ;
2429
2430 jump_statement:
2431         GOTO label                     ';'
2432         | CONTINUE                     ';'
2433         | BREAK                        ';'
2434         | RETURN comma_expression_opt  ';'
2435         ;
2436
2437
2438     /*  The  following  actions should update the symbol table in the 
2439     "label" name space */
2440
2441 label:
2442         IDENTIFIER
2443         | TYPEDEFname
2444         ;
2445
2446
2447 /***************************** EXTERNAL DEFINITIONS *****************************/
2448
2449 translation_unit:
2450         /* nothing */
2451         | translation_unit external_definition  { FLUSHBUF() ; 
2452                                                   strcpy(CurrentAggName,"") ;
2453                                                 }
2454
2455 external_definition:
2456         function_declaration                         /* C++, not ANSI C*/
2457         | function_definition
2458         | declaration
2459         | linkage_specifier function_declaration     /* C++, not ANSI C*/
2460         | linkage_specifier function_definition      /* C++, not ANSI C*/
2461         | linkage_specifier declaration              /* C++, not ANSI C*/
2462         | linkage_specifier '{'         
2463           {     
2464                 if ( FoundLBrace ) 
2465                         FoundLBrace = 0 ;
2466           }
2467           translation_unit 
2468           {
2469                 if ( FoundRBrace ) 
2470                         FoundRBrace = 0 ;
2471           }
2472           '}' /* C++, not ANSI C*/
2473         ;
2474
2475 linkage_specifier:
2476         EXTERN STRINGliteral
2477         ;
2478
2479
2480     /* Note that declaration_specifiers are left out of the following 
2481     function declarations.  Such omission is illegal in ANSI C. It is 
2482     sometimes necessary in C++, in instances  where  no  return  type 
2483     should be specified (e_g., a conversion operator).*/
2484
2485 function_declaration:
2486         identifier_declarator ';'   /*  semantically  verify  it is a 
2487                                     function, and (if ANSI says  it's 
2488                                     the  law for C++ also...) that it 
2489                                     is something that  can't  have  a 
2490                                     return  type  (like  a conversion 
2491                                     function, or a destructor */
2492
2493         | constructor_function_declaration ';'
2494         ;
2495
2496 function_definition:
2497         new_function_definition         
2498         {       
2499                 if ( !CurrentFnIsInline )
2500                         InsertFunctionTable($1,TRUE) ; 
2501                 else
2502                         CurrentFnIsInline = FALSE ;
2503         }
2504         | old_function_definition
2505         | constructor_function_definition
2506         ;
2507
2508
2509     /* Note that in ANSI C, function definitions *ONLY* are presented 
2510     at file scope.  Hence, if there is a typedefname  active,  it  is 
2511     illegal  to  redeclare  it  (there  is no enclosing scope at file 
2512     scope).
2513
2514     In  contrast,  C++  allows   function   definitions   at   struct 
2515     elaboration scope, and allows tags that are defined at file scope 
2516     (and  hence  look like typedefnames) to be redeclared to function 
2517     calls.  Hence several of the rules are "partially C++  only".   I 
2518     could  actually  build separate rules for typedef_declarators and 
2519     identifier_declarators, and mention that  the  typedef_declarator 
2520     rules represent the C++ only features.
2521
2522     In  some  sense,  this  is  haggling, as I could/should have left 
2523     these as constraints in the ANSI C grammar, rather than as syntax 
2524     requirements.  */
2525
2526 new_function_definition:
2527                                        identifier_declarator 
2528           {     AddScope($1) ;  } 
2529           compound_statement    
2530           { RemoveScope($1) ; $$ = $1 ;
2531             if (CurrentAggType==CHARE || CurrentAggType==BRANCHED) {
2532                 if ( CurrentAccess == PRIVATE || CurrentAccess == PUBLIC )
2533                     ProcessFn($1) ;
2534             }
2535           }
2536         | declaration_specifier                   declarator 
2537           {if ( CurrentAggType==CHARE || CurrentAggType==BRANCHED ) {
2538                 if ( CurrentAccess == ENTRY )
2539                         ProcessEP($2,TRUE);
2540                 else if ( CurrentAccess == PRIVATE || CurrentAccess == PUBLIC )
2541                         ProcessFn($2) ;
2542                 InsideChareCode = 1 ;
2543            }
2544            else 
2545                 SetDefinedIfEp($2) ;
2546            AddScope($2) ;               
2547           } 
2548           compound_statement /* partially C++ only */   
2549           { RemoveScope($2) ; 
2550             $$ = $2 ;
2551             InsideChareCode = 0 ;
2552           }
2553         | declaration_specifier error   { FLUSHBUF() ; 
2554                                           SyntaxError("function header") ; }
2555           compound_statement
2556
2557         | type_specifier                          declarator 
2558           {       AddScope($2) ;  } 
2559           compound_statement /* partially C++ only */   
2560           { RemoveScope($2) ; 
2561             $$ = $2 ;
2562           }
2563
2564         | basic_type_name                         declarator 
2565           {int ind ;
2566            if ( CurrentAggType==CHARE || CurrentAggType==BRANCHED ) {
2567                 if ( CurrentAccess == ENTRY )
2568                         ProcessEP($2,TRUE);
2569                 else if ( CurrentAccess == PRIVATE || CurrentAccess == PUBLIC )
2570                         ProcessFn($2) ;
2571                 InsideChareCode = 1 ;
2572            }
2573            else if ( CurrentAggType == MESSAGE ) {
2574                 if ( strcmp($2,"pack")==0 || strcmp($2,"unpack")==0 ) {
2575                         if ( (ind=FoundInMsgTable(CurrentAggName)) != -1 )
2576                                 MessageTable[ind].pack = TRUE ; 
2577                         else 
2578                                 CharmError("TRANSLATOR : did not find message type in message table") ;
2579                 }                       
2580                 else 
2581                         CharmError("Messages are allowed to have only pack or unpack functions") ;
2582            }
2583            else if ( CurrentAggType == ACCUMULATOR ) {
2584                 if ( strcmp($2,"Accumulate")==0 && strcmp($1,"void")==0 ) 
2585                         FoundAccFnDef = TRUE ;
2586            }
2587            else 
2588                 SetDefinedIfEp($2) ;
2589            FLUSHBUF() ;
2590            AddScope($2) ;               
2591           } 
2592           compound_statement /* partially C++ only */   
2593           { RemoveScope($2) ; 
2594             $$ = $2 ;
2595             InsideChareCode = 0 ;
2596           }
2597
2598         | basic_type_name error { FLUSHBUF() ; 
2599                                   SyntaxError("function header") ; }
2600           compound_statement
2601
2602         | TYPEDEFname                             declarator 
2603           {AddScope($2) ;} compound_statement /* partially C++ only */  
2604           { RemoveScope($2) ; 
2605             $$ = $2 ;
2606           }
2607         | global_or_scoped_typedefname            declarator 
2608           {AddScope($2) ;} compound_statement /* partially C++ only */  
2609           { RemoveScope($2) ; 
2610             $$ = $2 ;
2611           }
2612         | declaration_qualifier_list   identifier_declarator 
2613           {AddScope($2) ;} compound_statement   
2614           { RemoveScope($2) ; 
2615             $$ = $2 ;
2616           }
2617         | type_qualifier_list          identifier_declarator 
2618           {AddScope($2) ;} compound_statement   
2619           { RemoveScope($2) ; 
2620             $$ = $2 ;
2621           }
2622         ;
2623
2624
2625     /* Note that I do not support redeclaration of TYPEDEFnames  into 
2626     function  names  as I did in new_function_definitions (see note). 
2627     Perhaps I should do it, but for now, ignore the issue. Note  that 
2628     this  is  a  non-problem  with  ANSI  C,  as  tag  names  are not 
2629     considered TYPEDEFnames. */
2630
2631 old_function_definition:
2632                                        old_function_declarator {} old_function_body
2633         | declaration_specifier        old_function_declarator {} old_function_body
2634         | type_specifier               old_function_declarator {} old_function_body
2635         | basic_type_name              old_function_declarator {} old_function_body
2636         | TYPEDEFname                  old_function_declarator {} old_function_body
2637         | global_or_scoped_typedefname old_function_declarator {} old_function_body
2638         | declaration_qualifier_list   old_function_declarator {} old_function_body
2639         | type_qualifier_list          old_function_declarator {} old_function_body
2640         ;
2641
2642 old_function_body:
2643         declaration_list compound_statement
2644         | compound_statement
2645         ;
2646
2647
2648     /*    Verify    via    constraints     that     the     following 
2649         declaration_specifier           is          really          a 
2650         typedef_declaration_specifier, consisting of:
2651
2652         ... TYPEDEFname :: TYPEDEFname
2653
2654     optionally *preceded* by a "inline" keyword.   Use  care  not  to 
2655     support "inline" as a postfix!
2656
2657     Similarly, the global_or_scoped_typedefname must be:
2658
2659         ... TYPEDEFname :: TYPEDEFname
2660
2661     with matching names at the end of the list.
2662
2663     We  use the more general form to prevent a syntax conflict with a 
2664     typical    function    definition    (which    won't    have    a 
2665     constructor_init_list) */
2666
2667 constructor_function_definition:
2668         global_or_scoped_typedefname parameter_type_list
2669         constructor_init_list_opt 
2670         {       int ind ;       
2671
2672                 SetDefinedIfEp($1) ;
2673                 CheckConstructorEP($1,TRUE) ; 
2674
2675                 if ( (ind=FoundInAccTable(AccTable,TotalAccs,$1)) != -1 ) {
2676                 /* This is an Accumulator constructor */
2677                         AccTable[ind]->initmsgtype = (char *)malloc((strlen(CurrentMsgParm)+1)*sizeof(char)) ;
2678                         strcpy(AccTable[ind]->initmsgtype,CurrentMsgParm) ;
2679                         AccTable[ind]->defined = 1 ;
2680                 }
2681                 else if ( (ind=FoundInAccTable(MonoTable,TotalMonos,$1)) != -1 ) {
2682                 /* This is a Monotonic constructor */
2683                         MonoTable[ind]->initmsgtype = (char *)malloc((strlen(CurrentMsgParm)+1)*sizeof(char)) ;
2684                         strcpy(MonoTable[ind]->initmsgtype,CurrentMsgParm) ;
2685                         MonoTable[ind]->defined = 1 ;
2686                 }
2687
2688                 AddScope($1) ;          
2689         }
2690         compound_statement
2691         {       RemoveScope($1) ;
2692                 InsideChareCode = 0 ;
2693         }
2694
2695         | declaration_specifier      parameter_type_list
2696                      constructor_init_list_opt compound_statement
2697         ;
2698
2699
2700     /*  Same  comments  as  seen  for constructor_function_definition 
2701     apply here */
2702
2703 constructor_function_declaration:
2704         global_or_scoped_typedefname parameter_type_list  /* wasteful redeclaration; used for friend decls.  */
2705
2706         | declaration_specifier      parameter_type_list  /* request to inline, no definition */
2707         ;
2708
2709
2710     /* The following use of declaration_specifiers are made to  allow 
2711     for  a TYPEDEFname preceded by an INLINE modifier. This fact must 
2712     be verified semantically.  It should also be  verified  that  the 
2713     TYPEDEFname  is  ACTUALLY  the  class name being elaborated. Note 
2714     that we could break out typedef_declaration_specifier from within 
2715     declaration_specifier, and we  might  narrow  down  the  conflict 
2716     region a bit. A second alternative (to what is done) for cleaning 
2717     up  this  stuff  is  to  let the tokenizer specially identify the 
2718     current class being elaborated as a special token, and not just a 
2719     typedefname. Unfortunately, things would get very  confusing  for 
2720     the  lexer,  as  we may pop into enclosed tag elaboration scopes; 
2721     into function definitions; or into both recursively! */
2722
2723     /* I should make the following  rules  easier  to  annotate  with 
2724     scope  entry  and exit actions.  Note how hard it is to establish 
2725     the scope when you don't even know what the decl_spec is!! It can 
2726     be done with $-1 hacking, but I should not encourage users to  do 
2727     this directly. */
2728
2729 constructor_function_in_class:
2730         declaration_specifier   constructor_parameter_list_and_body
2731           {     foundargs = FALSE ; }
2732         | TYPEDEFname           constructor_parameter_list_and_body
2733           {     int ind ;       
2734
2735                 if ( (ind=FoundInAccTable(AccTable,TotalAccs,$1)) != -1 ) {
2736                 /* This is an Accumulator constructor */
2737                         AccTable[ind]->initmsgtype = (char *)malloc((strlen(CurrentMsgParm)+1)*sizeof(char)) ;
2738                         strcpy(AccTable[ind]->initmsgtype,CurrentMsgParm) ;
2739                         AccTable[ind]->defined = FoundConstructorBody ;
2740                 }
2741                 else if ( (ind=FoundInAccTable(MonoTable,TotalMonos,$1)) != -1 ) {
2742                 /* This is a Monotonic constructor */
2743                         MonoTable[ind]->initmsgtype = (char *)malloc((strlen(CurrentMsgParm)+1)*sizeof(char)) ;
2744                         strcpy(MonoTable[ind]->initmsgtype,CurrentMsgParm) ;
2745                         MonoTable[ind]->defined = FoundConstructorBody ;
2746                 }
2747
2748                 foundargs = FALSE ;
2749           }
2750         ;
2751
2752
2753     /* The following conflicts with member declarations-
2754     constructor_parameter_list_and_body:
2755           parameter_type_list ';'
2756           | parameter_type_list constructor_init_list_opt compound_statement
2757           ;
2758     so parameter_type_list was expanded inline to get */
2759
2760     /* C++, not ANSI C */
2761 constructor_parameter_list_and_body:
2762           '('                           ')' type_qualifier_list_opt ';'
2763            { CheckConstructorEP($0,FALSE) ; 
2764              FoundConstructorBody = FALSE ; }
2765         | '(' type_name initializer     ')' type_qualifier_list_opt ';' 
2766            { CheckConstructorEP($0,FALSE) ; 
2767              FoundConstructorBody = FALSE ; }
2768         | '(' named_parameter_type_list ')' type_qualifier_list_opt ';'
2769            { foundargs = TRUE ; 
2770              CheckConstructorEP($0,FALSE) ; 
2771              FoundConstructorBody = FALSE ; }
2772
2773         | '('                           ')' type_qualifier_list_opt
2774                 constructor_init_list_opt 
2775            {    CheckConstructorEP($0,TRUE) ; 
2776            }
2777            compound_statement
2778            {    FoundConstructorBody = TRUE ; 
2779            }
2780         | '(' type_name initializer     ')' type_qualifier_list_opt
2781                 constructor_init_list_opt 
2782            {    CheckConstructorEP($0,TRUE) ; 
2783            }
2784            compound_statement
2785            {    FoundConstructorBody = TRUE ; 
2786            }
2787         | '(' named_parameter_type_list ')' type_qualifier_list_opt
2788                 constructor_init_list_opt 
2789            {    foundargs = TRUE ; CheckConstructorEP($0,TRUE) ; 
2790            }
2791            compound_statement
2792            {    FoundConstructorBody = TRUE ; 
2793            }
2794
2795         | constructor_conflicting_parameter_list_and_body
2796           {     EpMsg = CurrentTypedef ; 
2797                 CheckConstructorEP($0,FALSE) ;  }
2798         ;
2799
2800
2801     /* The following conflicted with member declaration-
2802     constructor_conflicting_parameter_list_and_body:
2803         '('   type_name ')'                 type_qualifier_list_opt ';'
2804         | '(' type_name ')'                 type_qualifier_list_opt
2805                 constructor_init_list_opt compound_statement
2806         ;
2807     so type_name was inline expanded to get the following... */
2808
2809
2810     /*  Note  that by inline expanding type_qualifier_opt in a few of 
2811     the following rules I can transform 3  RR  conflicts  into  3  SR 
2812     conflicts.  Since  all the conflicts have a look ahead of ';', it 
2813     doesn't  really  matter  (also,  there  are  no   bad   LALR-only 
2814     components in the conflicts) */
2815
2816 constructor_conflicting_parameter_list_and_body:
2817         '(' type_specifier                 ')' type_qualifier_list_opt
2818                 ';'
2819         | '(' basic_type_name              ')' type_qualifier_list_opt
2820                 ';'
2821
2822         | '(' TYPEDEFname                  ')' type_qualifier_list_opt
2823                 ';'
2824
2825         | '(' global_or_scoped_typedefname ')' type_qualifier_list_opt
2826                 ';'
2827
2828         | '(' type_qualifier_list          ')' type_qualifier_list_opt
2829                 ';'
2830
2831
2832         | '(' type_specifier               abstract_declarator ')' type_qualifier_list_opt
2833                 ';'
2834         | '(' basic_type_name              abstract_declarator ')' type_qualifier_list_opt
2835                 ';'
2836
2837         /* missing entry posted below */
2838
2839         | '(' global_or_scoped_typedefname abstract_declarator ')' type_qualifier_list_opt
2840                 ';'
2841         | '(' type_qualifier_list          abstract_declarator ')' type_qualifier_list_opt
2842                 ';'
2843
2844
2845         | '(' type_specifier               ')' type_qualifier_list_opt
2846                 constructor_init_list_opt compound_statement
2847
2848         | '(' basic_type_name              ')' type_qualifier_list_opt
2849                 constructor_init_list_opt compound_statement
2850
2851         | '(' TYPEDEFname                  ')' type_qualifier_list_opt
2852                 constructor_init_list_opt compound_statement
2853
2854         | '(' global_or_scoped_typedefname ')' type_qualifier_list_opt
2855                 constructor_init_list_opt compound_statement
2856
2857         | '(' type_qualifier_list           ')' type_qualifier_list_opt
2858                 constructor_init_list_opt compound_statement
2859
2860
2861         | '(' type_specifier  abstract_declarator ')' type_qualifier_list_opt
2862                 constructor_init_list_opt compound_statement
2863
2864         | '(' basic_type_name abstract_declarator ')' type_qualifier_list_opt
2865                 constructor_init_list_opt compound_statement
2866
2867         /* missing entry posted below */
2868
2869         | '(' global_or_scoped_typedefname abstract_declarator ')' type_qualifier_list_opt
2870                 constructor_init_list_opt compound_statement
2871
2872         | '(' type_qualifier_list          abstract_declarator ')' type_qualifier_list_opt
2873                 constructor_init_list_opt compound_statement
2874
2875         | constructor_conflicting_typedef_declarator
2876         ;
2877
2878
2879     /* The following have ambiguities with member declarations-
2880     constructor_conflicting_typedef_declarator:
2881       '(' TYPEDEFname abstract_declarator ')' type_qualifier_list_opt
2882                 ';'
2883       |  '(' TYPEDEFname abstract_declarator ')' type_qualifier_list_opt
2884                 constructor_init_list_opt compound_statement
2885       ;
2886     which can be deferred by expanding abstract_declarator, and in two
2887     cases parameter_qualifier_list, resulting in ...*/
2888
2889 constructor_conflicting_typedef_declarator:
2890         '(' TYPEDEFname unary_abstract_declarator          ')' type_qualifier_list_opt
2891                 ';'
2892
2893         | '(' TYPEDEFname unary_abstract_declarator       ')' type_qualifier_list_opt
2894                 constructor_init_list_opt compound_statement
2895
2896         | '(' TYPEDEFname postfix_abstract_declarator     ')' type_qualifier_list_opt
2897                 ';'
2898
2899         | '(' TYPEDEFname postfix_abstract_declarator     ')' type_qualifier_list_opt
2900                 constructor_init_list_opt compound_statement
2901
2902
2903         | '(' TYPEDEFname postfixing_abstract_declarator  ')' type_qualifier_list_opt
2904                 ';'
2905
2906         | '(' TYPEDEFname postfixing_abstract_declarator  ')' type_qualifier_list_opt
2907                 constructor_init_list_opt compound_statement
2908         ;
2909
2910
2911 constructor_init_list_opt:
2912         /* nothing */
2913         | constructor_init_list
2914         ;
2915
2916 constructor_init_list:
2917         ':' constructor_init
2918         | constructor_init_list ',' constructor_init
2919         ;
2920
2921 constructor_init:
2922         IDENTIFIER   '(' argument_expression_list ')'
2923         | IDENTIFIER '('                          ')'
2924
2925         | TYPEDEFname '(' argument_expression_list ')'
2926         | TYPEDEFname '('                          ')'
2927         | global_or_scoped_typedefname '(' argument_expression_list ')'
2928         | global_or_scoped_typedefname '('                          ')'
2929
2930         | '(' argument_expression_list ')' /* Single inheritance ONLY*/
2931         | '(' ')' /* Is this legal? It might be default! */
2932         ;
2933
2934 declarator:
2935         identifier_declarator   { $$ = $1; }
2936         | typedef_declarator    { $$ = $1; }
2937         ;
2938
2939 typedef_declarator:
2940         paren_typedef_declarator          /* would be ambiguous as parameter*/
2941         | simple_paren_typedef_declarator /* also ambiguous */
2942         | parameter_typedef_declarator {$$=$1;} /* not ambiguous as parameter*/
2943         ;
2944
2945 parameter_typedef_declarator:
2946         TYPEDEFname                                     { $$ = $1; }
2947         | TYPEDEFname postfixing_abstract_declarator    { $$ = $1; }
2948         | clean_typedef_declarator
2949         ;
2950
2951
2952     /*  The  following  have  at  least  one  '*'or '&'.  There is no 
2953     (redundant) '(' between the '*'/'&'  and  the  TYPEDEFname.  This 
2954     definition  is  critical  in  that  a redundant paren that it too 
2955     close to the TYPEDEFname (i.e.,  nothing  between  them  at  all) 
2956     would  make  the TYPEDEFname into a parameter list, rather than a 
2957     declarator.*/
2958
2959 clean_typedef_declarator:
2960         clean_postfix_typedef_declarator
2961         | asterisk_or_ampersand parameter_typedef_declarator
2962         | unary_modifier        parameter_typedef_declarator
2963         ;
2964
2965 clean_postfix_typedef_declarator:
2966         '('   clean_typedef_declarator ')'
2967         | '(' clean_typedef_declarator ')' postfixing_abstract_declarator
2968         ;
2969
2970
2971     /* The following have a redundant '(' placed immediately  to  the 
2972     left  of the TYPEDEFname.  This opens up the possibility that the 
2973     TYPEDEFname is really the start of a parameter list, and *not*  a 
2974     declarator*/
2975
2976 paren_typedef_declarator:
2977         postfix_paren_typedef_declarator
2978         | asterisk_or_ampersand '(' simple_paren_typedef_declarator ')'
2979         | unary_modifier        '(' simple_paren_typedef_declarator ')'
2980         | asterisk_or_ampersand '(' TYPEDEFname ')' /* redundant paren */
2981         | unary_modifier        '(' TYPEDEFname ')' /* redundant paren */
2982         | asterisk_or_ampersand paren_typedef_declarator
2983         | unary_modifier        paren_typedef_declarator
2984         ;
2985
2986 postfix_paren_typedef_declarator:
2987         '(' paren_typedef_declarator ')'
2988         | '(' simple_paren_typedef_declarator postfixing_abstract_declarator ')'
2989         | '(' TYPEDEFname postfixing_abstract_declarator ')'              /* redundant paren */
2990         | '(' paren_typedef_declarator ')' postfixing_abstract_declarator
2991         ;
2992
2993
2994     /*  The following excludes lone TYPEDEFname to help in a conflict 
2995     resolution.  We have special cased lone  TYPEDEFname  along  side 
2996     all uses of simple_paren_typedef_declarator */
2997
2998 simple_paren_typedef_declarator:
2999         '(' TYPEDEFname ')'
3000         | '(' simple_paren_typedef_declarator ')'
3001         ;
3002
3003 identifier_declarator:
3004         unary_identifier_declarator     { $$ = $1; }
3005         | paren_identifier_declarator   { $$ = $1; FoundParms = FALSE ;}
3006         ;
3007
3008
3009     /*  The  following  allows  "function return array of" as well as 
3010     "array of function returning".  It COULD be cleaned  up  the  way 
3011     abstract  declarators  have been.  This change might make it hard 
3012     to recover from user's syntax errors, whereas now they appear  as 
3013     simple constraint errors. */
3014
3015 unary_identifier_declarator:
3016         postfix_identifier_declarator   { $$ = $1; }
3017         | asterisk_or_ampersand identifier_declarator   
3018           { if ( FoundHandle > 0 ) {
3019                 if ( CurrentCharmType == ACCUMULATOR )
3020                         InsertHandleTable(AccHandleTable,&AccHandleTableSize,$2) ;
3021                 else if ( CurrentCharmType == MONOTONIC )
3022                         InsertHandleTable(MonoHandleTable,&MonoHandleTableSize,$2) ;
3023                 else if ( CurrentCharmType == WRITEONCE )
3024                         InsertHandleTable(WrOnHandleTable,&WrOnHandleTableSize,$2) ;
3025                 else if ( FoundHandle == GROUP )
3026                         InsertHandleTable(BOCHandleTable,&BOCHandleTableSize,$2) ;
3027                 else if (CurrentCharmType==CHARE || CurrentCharmType==BRANCHED)
3028                         InsertHandleTable(ChareHandleTable,&ChareHandleTableSize,$2);
3029                 else 
3030                         fprintf(stderr,"ERROR : %s, line %d : %s is not a proper type for a handle.\n",CurrentFileName,CurrentLine,CurrentAsterisk) ;
3031                         
3032                 FoundHandle = -1 ;
3033             }
3034             $$ = $2 ;
3035           }
3036            
3037         | unary_modifier        identifier_declarator
3038         ;
3039
3040 postfix_identifier_declarator:
3041         paren_identifier_declarator           postfixing_abstract_declarator 
3042          { $$ = $1; }
3043         | '(' unary_identifier_declarator ')'
3044         | '(' unary_identifier_declarator ')' postfixing_abstract_declarator
3045           { $$ = $2 ; }
3046         ;
3047
3048 old_function_declarator:
3049         postfix_old_function_declarator
3050         | asterisk_or_ampersand old_function_declarator
3051         | unary_modifier      old_function_declarator
3052         ;
3053
3054
3055     /*  ANSI  C  section  3.7.1  states  "An identifier declared as a 
3056     typedef name shall not be redeclared as a parameter".  Hence  the 
3057     following is based only on IDENTIFIERs.
3058
3059     Instead  of identifier_lists, an argument_expression_list is used 
3060     in  old  style  function   definitions.    The   ambiguity   with 
3061     constructors   required   the  use  of  argument  lists,  with  a 
3062     constraint verification of the list (e_g.: check to see that  the 
3063     "expressions" consisted of lone identifiers).
3064
3065     An interesting ambiguity appeared:
3066         const constant=5;
3067         int foo(constant) ...
3068
3069     Is  this an old function definition or constructor?  The decision 
3070     is made later by THIS grammar based on trailing context :-). This 
3071     ambiguity is probably what caused many parsers to give up on  old 
3072     style function definitions. */
3073
3074 postfix_old_function_declarator:
3075         paren_identifier_declarator '(' argument_expression_list ')'
3076         | '(' old_function_declarator ')'
3077         | '(' old_function_declarator ')' old_postfixing_abstract_declarator
3078         ;
3079
3080 old_postfixing_abstract_declarator:
3081         array_abstract_declarator /* array modifiers */
3082         | old_parameter_type_list  /* function returning modifiers */
3083         ;
3084
3085 abstract_declarator:
3086         unary_abstract_declarator
3087         | postfix_abstract_declarator
3088         | postfixing_abstract_declarator
3089         ;
3090
3091 postfixing_abstract_declarator:
3092         array_abstract_declarator
3093         | parameter_type_list   { FoundParms = TRUE ; }
3094         ;
3095
3096 array_abstract_declarator:
3097         '[' ']'
3098         | '[' constant_expression ']'
3099         | array_abstract_declarator '[' constant_expression ']'
3100         ;
3101
3102 unary_abstract_declarator:
3103         asterisk_or_ampersand
3104         | unary_modifier
3105         | asterisk_or_ampersand abstract_declarator
3106         | unary_modifier        abstract_declarator
3107         ;
3108
3109 postfix_abstract_declarator:
3110         '(' unary_abstract_declarator ')'
3111         | '(' postfix_abstract_declarator ')'
3112         | '(' postfixing_abstract_declarator ')'
3113         | '(' unary_abstract_declarator ')' postfixing_abstract_declarator
3114         ;
3115
3116 asterisk_or_ampersand:
3117         '*'        { strcpy(CurrentAsterisk,"*") ; }
3118         | '&'      { strcpy(CurrentAsterisk,"&") ; }
3119         | HANDLE   {    /* CheckCharmName() ;   Done in t.l now */
3120                         FoundHandle = HANDLE ;
3121                         strcpy(CurrentAsterisk, CurrentTypedef) ;
3122                    }    
3123         | GROUP   {     /* CheckCharmName() ;   Done in t.l now */
3124                         FoundHandle = GROUP ;
3125                         strcpy(CurrentAsterisk, CurrentTypedef) ;
3126                    }    
3127         ;
3128
3129 unary_modifier:
3130         scope '*' type_qualifier_list_opt       { if ( AddedScope > 0 ) {
3131                                                         AddedScope = 0 ;
3132                                                         PopStack() ;
3133                                                   }
3134                                                 }
3135         | asterisk_or_ampersand type_qualifier_list
3136         ;
3137
3138
3139
3140 /************************* NESTED SCOPE SUPPORT ******************************/
3141
3142
3143     /*  The  actions taken in the rules that follow involve notifying 
3144     the lexer that it should use the scope specified to determine  if 
3145     the  next  IDENTIFIER  token is really a TYPEDEFnam