* src/SDCCsymt.h,
[fw/sdcc] / src / SDCC.y
1 /*-----------------------------------------------------------------------
2
3   SDCC.y - parser definition file for sdcc :
4           Written By : Sandeep Dutta . sandeep.dutta@usa.net (1997)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19    
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!  
23 -------------------------------------------------------------------------*/
24 %{
25 #include <stdio.h>
26 #include <stdarg.h> 
27 #include <string.h>
28 #include "SDCCglobl.h"
29 #include "SDCCsymt.h"
30 #include "SDCChasht.h"
31 #include "SDCCval.h"
32 #include "SDCCmem.h"
33 #include "SDCCast.h"
34 #include "port.h"
35 #include "newalloc.h"
36 #include "SDCCerr.h"
37 #include "SDCCutil.h"
38
39 extern int yyerror (char *);
40 extern FILE     *yyin;
41 int NestLevel = 0 ;     /* current NestLevel       */
42 int stackPtr  = 1 ;     /* stack pointer           */
43 int xstackPtr = 0 ;     /* xstack pointer          */
44 int reentrant = 0 ; 
45 int blockNo   = 0 ;     /* sequential block number  */
46 int currBlockno=0 ;
47 int inCritical= 0 ;
48 int seqPointNo= 1 ;     /* sequence point number */
49 int ignoreTypedefType=0;
50 extern int yylex();
51 int yyparse(void);
52 extern int noLineno ;
53 char lbuff[1024];      /* local buffer */
54
55 /* break & continue stacks */
56 STACK_DCL(continueStack  ,symbol *,MAX_NEST_LEVEL)
57 STACK_DCL(breakStack  ,symbol *,MAX_NEST_LEVEL)
58 STACK_DCL(forStack  ,symbol *,MAX_NEST_LEVEL)
59 STACK_DCL(swStk   ,ast   *,MAX_NEST_LEVEL)
60 STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3)
61
62 value *cenum = NULL  ;  /* current enumeration  type chain*/
63 bool uselessDecl = TRUE;
64
65 #define YYDEBUG 1
66
67 %}
68 %expect 6
69
70 %union {
71     symbol     *sym ;      /* symbol table pointer       */
72     structdef  *sdef;      /* structure definition       */
73     char       yychar[SDCC_NAME_MAX+1];
74     sym_link   *lnk ;      /* declarator  or specifier   */
75     int        yyint;      /* integer value returned     */
76     value      *val ;      /* for integer constant       */
77     initList   *ilist;     /* initial list               */
78     const char *yyinline;  /* inlined assembler code     */
79     ast        *asts;      /* expression tree            */
80 }
81
82 %token <yychar> IDENTIFIER TYPE_NAME
83 %token <val>   CONSTANT   STRING_LITERAL
84 %token SIZEOF TYPEOF 
85 %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
86 %token AND_OP OR_OP 
87 %token <yyint> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
88 %token <yyint> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
89 %token <yyint> XOR_ASSIGN OR_ASSIGN
90 %token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR AT SBIT
91 %token REENTRANT USING  XDATA DATA IDATA PDATA VAR_ARGS CRITICAL NONBANKED BANKED
92 %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT
93 %token STRUCT UNION ENUM ELIPSIS RANGE FAR
94 %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
95 %token NAKED JAVANATIVE OVERLAY
96 %token <yyinline> INLINEASM
97 %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT
98 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
99 %token RRC RLC 
100 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
101 %token DUMMY_READ_VOLATILE ENDCRITICAL SWAP
102
103 %type <yyint>  Interrupt_storage
104 %type <sym> identifier  declarator  declarator2 declarator3 enumerator_list enumerator
105 %type <sym> struct_declarator function_declarator function_declarator2
106 %type <sym> struct_declarator_list  struct_declaration   struct_declaration_list
107 %type <sym> declaration init_declarator_list init_declarator
108 %type <sym> declaration_list identifier_list parameter_identifier_list
109 %type <sym> declarator2_function_attributes while do for critical
110 %type <lnk> pointer type_specifier_list type_specifier type_name
111 %type <lnk> storage_class_specifier struct_or_union_specifier
112 %type <lnk> declaration_specifiers sfr_reg_bit sfr_attributes type_specifier2
113 %type <lnk> function_attribute function_attributes enum_specifier
114 %type <lnk> abstract_declarator abstract_declarator2 unqualified_pointer
115 %type <val> parameter_type_list parameter_list parameter_declaration opt_assign_expr
116 %type <sdef> stag opt_stag
117 %type <asts> primary_expr
118 %type <asts> postfix_expr unary_expr cast_expr multiplicative_expr
119 %type <asts> additive_expr shift_expr relational_expr equality_expr
120 %type <asts> and_expr exclusive_or_expr inclusive_or_expr logical_or_expr
121 %type <asts> logical_and_expr conditional_expr assignment_expr constant_expr
122 %type <asts> expr argument_expr_list function_definition expr_opt
123 %type <asts> statement_list statement labeled_statement compound_statement
124 %type <asts> expression_statement selection_statement iteration_statement
125 %type <asts> jump_statement function_body else_statement string_literal
126 %type <asts> critical_statement
127 %type <ilist> initializer initializer_list
128 %type <yyint> unary_operator  assignment_operator struct_or_union
129
130 %start file
131
132 %%
133
134 file
135    : external_definition       
136    | file external_definition
137    ;
138
139 external_definition
140    : function_definition     { 
141                                blockNo=0;
142                              }
143    | declaration             { 
144                                ignoreTypedefType = 0;
145                                if ($1 && $1->type
146                                 && IS_FUNC($1->type))
147                                {
148                                    /* The only legal storage classes for 
149                                     * a function prototype (declaration)
150                                     * are extern and static. extern is the
151                                     * default. Thus, if this function isn't
152                                     * explicitly marked static, mark it
153                                     * extern.
154                                     */
155                                    if ($1->etype 
156                                     && IS_SPEC($1->etype)
157                                     && !SPEC_STAT($1->etype))
158                                    {
159                                         SPEC_EXTR($1->etype) = 1;
160                                    }
161                                }
162                                addSymChain ($1);
163                                allocVariables ($1) ;
164                                cleanUpLevel (SymbolTab,1);
165                              }
166    ;
167
168 function_definition
169    : function_declarator function_body  {   /* function type not specified */
170                                    /* assume it to be 'int'       */
171                                    addDecl($1,0,newIntLink());
172                                    $$ = createFunction($1,$2); 
173                                } 
174    | declaration_specifiers function_declarator function_body  
175                                 {   
176                                     pointerTypes($2->type,copyLinkChain($1));
177                                     addDecl($2,0,$1); 
178                                     $$ = createFunction($2,$3);   
179                                 }
180    ;
181
182 function_attribute
183    : function_attributes
184    | function_attributes function_attribute { $$ = mergeSpec($1,$2,"function_attribute"); }
185    ;
186
187 function_attributes
188    :  USING CONSTANT {
189                         $$ = newLink(SPECIFIER) ;
190                         FUNC_REGBANK($$) = (int) floatFromVal($2);
191                      }
192    |  REENTRANT      {  $$ = newLink (SPECIFIER);
193                         FUNC_ISREENT($$)=1;
194                      }
195    |  CRITICAL       {  $$ = newLink (SPECIFIER);
196                         FUNC_ISCRITICAL($$) = 1;
197                      }
198    |  NAKED          {  $$ = newLink (SPECIFIER);
199                         FUNC_ISNAKED($$)=1;
200                      }
201    |  JAVANATIVE     {  $$ = newLink (SPECIFIER);
202                         FUNC_ISJAVANATIVE($$)=1;
203                      }
204    |  OVERLAY        {  $$ = newLink (SPECIFIER);
205                         FUNC_ISOVERLAY($$)=1;
206                      }
207    |  NONBANKED      {$$ = newLink (SPECIFIER);
208                         FUNC_NONBANKED($$) = 1;
209                         if (FUNC_BANKED($$)) {
210                             werror(W_BANKED_WITH_NONBANKED);
211                         }
212                      }
213    |  BANKED         {$$ = newLink (SPECIFIER);
214                         FUNC_BANKED($$) = 1;
215                         if (FUNC_NONBANKED($$)) {
216                             werror(W_BANKED_WITH_NONBANKED);
217                         }
218                         if (SPEC_STAT($$)) {
219                             werror(W_BANKED_WITH_STATIC);
220                         }
221                      }
222    |  Interrupt_storage
223                      {
224                         $$ = newLink (SPECIFIER) ;
225                         FUNC_INTNO($$) = $1 ;
226                         FUNC_ISISR($$) = 1;
227                      }
228    ;
229
230 function_body
231    : compound_statement                   
232    | declaration_list compound_statement
233          {
234             werror(E_OLD_STYLE,($1 ? $1->name: "")) ;
235             exit(1);
236          }
237    ;
238
239 primary_expr
240    : identifier      {  $$ = newAst_VALUE(symbolVal($1));  }
241    | CONSTANT        {  $$ = newAst_VALUE($1);  }
242    | string_literal  
243    | '(' expr ')'    {  $$ = $2 ;                   }
244    ;
245          
246 string_literal
247     : STRING_LITERAL                    { $$ = newAst_VALUE($1); }
248     ;
249
250 postfix_expr
251    : primary_expr
252    | postfix_expr '[' expr ']'          { $$ = newNode  ('[', $1, $3) ; }
253    | postfix_expr '(' ')'               { $$ = newNode  (CALL,$1,NULL); 
254                                           $$->left->funcName = 1;}
255    | postfix_expr '(' argument_expr_list ')'
256           {        
257             $$ = newNode  (CALL,$1,$3) ; $$->left->funcName = 1;
258           }
259    | postfix_expr '.' identifier       
260                       {    
261                         $3 = newSymbol($3->name,NestLevel);
262                         $3->implicit = 1;
263                         $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst_VALUE(symbolVal($3)));
264 /*                      $$ = newNode('.',$1,newAst(EX_VALUE,symbolVal($3))) ;                   */
265                       }
266    | postfix_expr PTR_OP identifier    
267                       { 
268                         $3 = newSymbol($3->name,NestLevel);
269                         $3->implicit = 1;                       
270                         $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($3)));
271                       }
272    | postfix_expr INC_OP   
273                       { $$ = newNode(INC_OP,$1,NULL);}
274    | postfix_expr DEC_OP
275                       { $$ = newNode(DEC_OP,$1,NULL); }
276    ;
277
278 argument_expr_list
279    : assignment_expr 
280    | assignment_expr ',' argument_expr_list { $$ = newNode(PARAM,$1,$3); }
281    ;
282
283 unary_expr
284    : postfix_expr
285    | INC_OP unary_expr        { $$ = newNode(INC_OP,NULL,$2);  }
286    | DEC_OP unary_expr        { $$ = newNode(DEC_OP,NULL,$2);  }
287    | unary_operator cast_expr { $$ = newNode($1,$2,NULL)    ;  }
288    | SIZEOF unary_expr        { $$ = newNode(SIZEOF,NULL,$2);  }
289    | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); }
290    | TYPEOF unary_expr        { $$ = newNode(TYPEOF,NULL,$2);  }
291    ;
292               
293 unary_operator
294    : '&'    { $$ = '&' ;}
295    | '*'    { $$ = '*' ;}
296    | '+'    { $$ = '+' ;}
297    | '-'    { $$ = '-' ;}
298    | '~'    { $$ = '~' ;}
299    | '!'    { $$ = '!' ;}
300    ;
301
302 cast_expr
303    : unary_expr
304    | '(' type_name ')' cast_expr { $$ = newNode(CAST,newAst_LINK($2),$4); }
305    ;
306
307 multiplicative_expr
308    : cast_expr
309    | multiplicative_expr '*' cast_expr { $$ = newNode('*',$1,$3);}
310    | multiplicative_expr '/' cast_expr { $$ = newNode('/',$1,$3);}
311    | multiplicative_expr '%' cast_expr { $$ = newNode('%',$1,$3);}
312    ;
313
314 additive_expr
315    : multiplicative_expr
316    | additive_expr '+' multiplicative_expr { $$=newNode('+',$1,$3);}
317    | additive_expr '-' multiplicative_expr { $$=newNode('-',$1,$3);}
318    ;
319
320 shift_expr
321    : additive_expr
322    | shift_expr LEFT_OP additive_expr  { $$ = newNode(LEFT_OP,$1,$3); }
323    | shift_expr RIGHT_OP additive_expr { $$ = newNode(RIGHT_OP,$1,$3); }
324    ;
325
326 relational_expr
327    : shift_expr
328    | relational_expr '<' shift_expr    { 
329         $$ = (port->lt_nge ? 
330               newNode('!',newNode(GE_OP,$1,$3),NULL) :
331               newNode('<', $1,$3));
332    }
333    | relational_expr '>' shift_expr    { 
334            $$ = (port->gt_nle ? 
335                  newNode('!',newNode(LE_OP,$1,$3),NULL) :
336                  newNode('>',$1,$3));
337    }
338    | relational_expr LE_OP shift_expr  { 
339            $$ = (port->le_ngt ? 
340                  newNode('!', newNode('>', $1 , $3 ), NULL) :
341                  newNode(LE_OP,$1,$3));
342    }
343    | relational_expr GE_OP shift_expr  { 
344            $$ = (port->ge_nlt ? 
345                  newNode('!', newNode('<', $1 , $3 ), NULL) :
346                  newNode(GE_OP,$1,$3));
347    }
348    ;
349
350 equality_expr
351    : relational_expr
352    | equality_expr EQ_OP relational_expr  { 
353     $$ = (port->eq_nne ? 
354           newNode('!',newNode(NE_OP,$1,$3),NULL) : 
355           newNode(EQ_OP,$1,$3));
356    }
357    | equality_expr NE_OP relational_expr { 
358        $$ = (port->ne_neq ? 
359              newNode('!', newNode(EQ_OP,$1,$3), NULL) : 
360              newNode(NE_OP,$1,$3));
361    }       
362    ;
363
364 and_expr
365    : equality_expr
366    | and_expr '&' equality_expr  { $$ = newNode('&',$1,$3);}
367    ;
368
369 exclusive_or_expr
370    : and_expr
371    | exclusive_or_expr '^' and_expr { $$ = newNode('^',$1,$3);}
372    ;
373
374 inclusive_or_expr
375    : exclusive_or_expr
376    | inclusive_or_expr '|' exclusive_or_expr { $$ = newNode('|',$1,$3);}
377    ;
378
379 logical_and_expr
380    : inclusive_or_expr
381    | logical_and_expr AND_OP { seqPointNo++;} inclusive_or_expr 
382                                  { $$ = newNode(AND_OP,$1,$4);}
383    ;
384
385 logical_or_expr
386    : logical_and_expr
387    | logical_or_expr OR_OP { seqPointNo++;} logical_and_expr  
388                                  { $$ = newNode(OR_OP,$1,$4); }
389    ;
390
391 conditional_expr
392    : logical_or_expr
393    | logical_or_expr '?' { seqPointNo++;} logical_or_expr ':' conditional_expr  
394                      {
395                         $$ = newNode(':',$4,$6) ;
396                         $$ = newNode('?',$1,$$) ;
397                      }                        
398    ;
399
400 assignment_expr
401    : conditional_expr
402    | unary_expr assignment_operator assignment_expr   
403                      { 
404                                  
405                              switch ($2) {
406                              case '=':
407                                      $$ = newNode($2,$1,$3);
408                                      break;
409                              case MUL_ASSIGN:
410                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
411                                                       newNode('*',removePreIncDecOps(copyAst($1)),$3));
412                                      break;
413                              case DIV_ASSIGN:
414                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
415                                                       newNode('/',removePreIncDecOps(copyAst($1)),$3));
416                                      break;
417                              case MOD_ASSIGN:
418                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
419                                                       newNode('%',removePreIncDecOps(copyAst($1)),$3));
420                                      break;
421                              case ADD_ASSIGN:
422                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
423                                                       newNode('+',removePreIncDecOps(copyAst($1)),$3));
424                                      break;
425                              case SUB_ASSIGN:
426                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
427                                                       newNode('-',removePreIncDecOps(copyAst($1)),$3));
428                                      break;
429                              case LEFT_ASSIGN:
430                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
431                                                       newNode(LEFT_OP,removePreIncDecOps(copyAst($1)),$3));
432                                      break;
433                              case RIGHT_ASSIGN:
434                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
435                                                       newNode(RIGHT_OP,removePreIncDecOps(copyAst($1)),$3));
436                                      break;
437                              case AND_ASSIGN:
438                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
439                                                       newNode('&',removePreIncDecOps(copyAst($1)),$3));
440                                      break;
441                              case XOR_ASSIGN:
442                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
443                                                       newNode('^',removePreIncDecOps(copyAst($1)),$3));
444                                      break;
445                              case OR_ASSIGN:
446                                      /* $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3)); */
447                                      $$ = newNode('=',removePostIncDecOps(copyAst($1)),
448                                                       newNode('|',removePreIncDecOps(copyAst($1)),$3));
449                                      break;
450                              default :
451                                      $$ = NULL;
452                              }
453                                      
454                      }
455 ;
456
457 assignment_operator
458    : '='             { $$ = '=' ;}
459    | MUL_ASSIGN
460    | DIV_ASSIGN
461    | MOD_ASSIGN
462    | ADD_ASSIGN
463    | SUB_ASSIGN
464    | LEFT_ASSIGN
465    | RIGHT_ASSIGN
466    | AND_ASSIGN
467    | XOR_ASSIGN
468    | OR_ASSIGN
469    ;
470
471 expr
472    : assignment_expr
473    | expr ',' { seqPointNo++;} assignment_expr { $$ = newNode(',',$1,$4);}
474    ;
475
476 constant_expr
477    : conditional_expr 
478    ;
479
480 declaration
481    : declaration_specifiers ';'
482       {
483          if (uselessDecl)
484            werror(W_USELESS_DECL);
485          uselessDecl = TRUE;
486          $$ = NULL ;
487       }
488    | declaration_specifiers init_declarator_list ';'
489       {
490          /* add the specifier list to the id */
491          symbol *sym , *sym1;
492
493          for (sym1 = sym = reverseSyms($2);sym != NULL;sym = sym->next) {
494              sym_link *lnk = copyLinkChain($1);
495              /* do the pointer stuff */
496              pointerTypes(sym->type,lnk);
497              addDecl (sym,0,lnk) ;
498          }
499         
500          uselessDecl = TRUE;
501          $$ = sym1 ;
502       }
503    ;
504
505 declaration_specifiers
506    : storage_class_specifier                                            { $$ = $1; }
507    | storage_class_specifier declaration_specifiers { 
508      /* if the decl $2 is not a specifier */
509      /* find the spec and replace it      */
510      if ( !IS_SPEC($2)) {
511        sym_link *lnk = $2 ;
512        while (lnk && !IS_SPEC(lnk->next))
513          lnk = lnk->next;
514        lnk->next = mergeSpec($1,lnk->next, "storage_class_specifier declaration_specifiers - skipped");
515        $$ = $2 ;
516      }
517      else
518        $$ = mergeSpec($1,$2, "storage_class_specifier declaration_specifiers");
519    }
520    | type_specifier                                 { $$ = $1; }
521    | type_specifier declaration_specifiers          { 
522      /* if the decl $2 is not a specifier */
523      /* find the spec and replace it      */
524      if ( !IS_SPEC($2)) {
525        sym_link *lnk = $2 ;
526        while (lnk && !IS_SPEC(lnk->next))
527          lnk = lnk->next;
528        lnk->next = mergeSpec($1,lnk->next, "type_specifier declaration_specifiers - skipped");
529        $$ = $2 ;
530      }
531      else
532        $$ = mergeSpec($1,$2, "type_specifier declaration_specifiers");
533    }
534    ;
535
536 init_declarator_list
537    : init_declarator
538    | init_declarator_list ',' init_declarator      { $3->next = $1 ; $$ = $3;}
539    ;
540
541 init_declarator
542    : declarator                  { $1->ival = NULL ; }
543    | declarator '=' initializer  { $1->ival = $3   ; }
544    ;
545
546
547 storage_class_specifier
548    : TYPEDEF   {
549                   $$ = newLink (SPECIFIER) ;
550                   SPEC_TYPEDEF($$) = 1 ;
551                }
552    | EXTERN    {
553                   $$ = newLink(SPECIFIER);
554                   SPEC_EXTR($$) = 1 ;
555                }
556    | STATIC    {
557                   $$ = newLink (SPECIFIER);
558                   SPEC_STAT($$) = 1 ;
559                }
560    | AUTO      {
561                   $$ = newLink (SPECIFIER) ;
562                   SPEC_SCLS($$) = S_AUTO  ;
563                }
564    | REGISTER  {
565                   $$ = newLink (SPECIFIER);
566                   SPEC_SCLS($$) = S_REGISTER ;
567                }
568    ;
569
570 Interrupt_storage
571    : INTERRUPT { $$ = INTNO_UNSPEC ; }
572    | INTERRUPT CONSTANT
573         { int intno = (int) floatFromVal($2);
574           if ((intno >= 0) && (intno <= INTNO_MAX))
575             $$ = intno;
576           else
577             {
578               werror(E_INT_BAD_INTNO, intno);
579               $$ = INTNO_UNSPEC;
580             }
581         }
582    ;
583
584 type_specifier
585    : type_specifier2
586    | type_specifier2 AT constant_expr
587         {
588            /* add this to the storage class specifier  */
589            SPEC_ABSA($1) = 1;   /* set the absolute addr flag */
590            /* now get the abs addr from value */
591            SPEC_ADDR($1) = (int) floatFromVal(constExprValue($3,TRUE)) ;
592         }
593    ;
594
595 type_specifier2
596    : CHAR   {
597                $$=newLink(SPECIFIER);
598                SPEC_NOUN($$) = V_CHAR  ;
599                ignoreTypedefType = 1;
600             }
601    | SHORT  {
602                $$=newLink(SPECIFIER);
603                $$->select.s._short = 1 ;
604                ignoreTypedefType = 1;
605             }
606    | INT    {
607                $$=newLink(SPECIFIER);
608                SPEC_NOUN($$) = V_INT   ;
609                ignoreTypedefType = 1;
610             }
611    | LONG   {
612                $$=newLink(SPECIFIER);
613                SPEC_LONG($$) = 1       ;
614                ignoreTypedefType = 1;
615             }
616    | SIGNED {
617                $$=newLink(SPECIFIER);
618                $$->select.s._signed = 1;
619                ignoreTypedefType = 1;
620             }
621    | UNSIGNED  {
622                $$=newLink(SPECIFIER);
623                SPEC_USIGN($$) = 1      ;
624                ignoreTypedefType = 1;
625             }
626    | VOID   {
627                $$=newLink(SPECIFIER);
628                SPEC_NOUN($$) = V_VOID  ;
629                ignoreTypedefType = 1;
630             }
631    | CONST  {
632                $$=newLink(SPECIFIER);
633                SPEC_CONST($$) = 1;
634             }
635    | VOLATILE  {
636                $$=newLink(SPECIFIER);
637                SPEC_VOLATILE($$) = 1 ;
638             }
639    | FLOAT  {
640                $$=newLink(SPECIFIER);
641                SPEC_NOUN($$) = V_FLOAT;
642                ignoreTypedefType = 1;
643             }
644    | XDATA     {
645                   $$ = newLink (SPECIFIER);
646                   SPEC_SCLS($$) = S_XDATA  ;
647                }
648    | CODE      {
649                   $$ = newLink (SPECIFIER) ;
650                   SPEC_SCLS($$) = S_CODE ;                 
651                }
652    | EEPROM      {
653                   $$ = newLink (SPECIFIER) ;
654                   SPEC_SCLS($$) = S_EEPROM ;
655                }
656    | DATA      {
657                   $$ = newLink (SPECIFIER);
658                   SPEC_SCLS($$) = S_DATA   ;
659                }
660    | IDATA     {
661                   $$ = newLink (SPECIFIER);
662                   SPEC_SCLS($$) = S_IDATA  ;
663                }
664    | PDATA     { 
665                   $$ = newLink (SPECIFIER);
666                   SPEC_SCLS($$) = S_PDATA  ;
667                }
668    | BIT    {
669                $$=newLink(SPECIFIER);
670                SPEC_NOUN($$) = V_BIT   ;
671                SPEC_SCLS($$) = S_BIT   ;
672                SPEC_BLEN($$) = 1;
673                SPEC_BSTR($$) = 0;
674                ignoreTypedefType = 1;
675             }
676
677    | struct_or_union_specifier  {
678                                    uselessDecl = FALSE;
679                                    $$ = $1 ;
680                                    ignoreTypedefType = 1;
681                                 }
682    | enum_specifier     {                           
683                            cenum = NULL ;
684                            uselessDecl = FALSE;
685                            ignoreTypedefType = 1;
686                            $$ = $1 ;                              
687                         }
688    | TYPE_NAME    
689          {
690             symbol *sym;
691             sym_link   *p  ;
692             sym = findSym(TypedefTab,NULL,$1) ;
693             $$ = p = copyLinkChain(sym->type);
694             SPEC_TYPEDEF(getSpec(p)) = 0;
695             ignoreTypedefType = 1;
696          }
697    | sfr_reg_bit
698    ;
699
700 sfr_reg_bit
701    :  SBIT  {
702                $$ = newLink(SPECIFIER) ;
703                SPEC_NOUN($$) = V_SBIT;
704                SPEC_SCLS($$) = S_SBIT;
705                ignoreTypedefType = 1;
706             }
707    |  sfr_attributes
708    ;
709
710 sfr_attributes
711    : SFR    {
712                $$ = newLink(SPECIFIER) ;
713                FUNC_REGBANK($$) = 0;
714                SPEC_NOUN($$)    = V_CHAR;
715                SPEC_SCLS($$)    = S_SFR ;
716                SPEC_USIGN($$)   = 1 ;
717                ignoreTypedefType = 1;
718             }
719    | SFR BANKED {
720                $$ = newLink(SPECIFIER) ;
721                FUNC_REGBANK($$) = 1;
722                SPEC_NOUN($$)    = V_CHAR;
723                SPEC_SCLS($$)    = S_SFR ;
724                SPEC_USIGN($$)   = 1 ;
725                ignoreTypedefType = 1;
726             }
727    ;
728
729 struct_or_union_specifier
730    : struct_or_union opt_stag
731         {
732            if (!$2->type)
733              {
734                $2->type = $1;
735              }
736            else
737              {
738                if ($2->type != $1)
739                  werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union");
740              }
741
742         }
743            '{' struct_declaration_list '}'
744         {
745            structdef *sdef ;
746            symbol *sym, *dsym;
747
748            // check for errors in structure members
749            for (sym=$5; sym; sym=sym->next) {
750              if (IS_ABSOLUTE(sym->etype)) {
751                werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "'at'");
752                SPEC_ABSA(sym->etype) = 0;
753              }
754              if (IS_SPEC(sym->etype) && SPEC_SCLS(sym->etype)) {
755                werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "storage class");
756                printTypeChainRaw (sym->type,NULL);
757                SPEC_SCLS(sym->etype) = 0;
758              }
759              for (dsym=sym->next; dsym; dsym=dsym->next) {
760                if (strcmp(sym->name, dsym->name)==0) {
761                  werrorfl(sym->fileDef, sym->lineDef, E_DUPLICATE_MEMBER, 
762                         $1==STRUCT ? "struct" : "union", sym->name);
763                }
764              }
765            }
766
767            /* Create a structdef   */      
768            sdef = $2 ;
769            sdef->fields   = reverseSyms($5) ;   /* link the fields */
770            sdef->size  = compStructSize($1,sdef);   /* update size of  */
771
772            /* Create the specifier */
773            $$ = newLink (SPECIFIER) ;
774            SPEC_NOUN($$) = V_STRUCT;
775            SPEC_STRUCT($$)= sdef ;
776         }
777    | struct_or_union stag
778          {
779             $$ = newLink(SPECIFIER) ;
780             SPEC_NOUN($$) = V_STRUCT;
781             SPEC_STRUCT($$) = $2;
782
783            if (!$2->type)
784              {
785                $2->type = $1;
786              }
787            else
788              {
789                if ($2->type != $1)
790                  werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union");
791              }
792          }
793    ;
794
795 struct_or_union
796    : STRUCT          { $$ = STRUCT ; }
797    | UNION           { $$ = UNION  ; }
798    ;
799
800 opt_stag
801 : stag
802 |  {  /* synthesize a name add to structtable */
803      $$ = newStruct(genSymName(NestLevel)) ;
804      $$->level = NestLevel ;
805      addSym (StructTab, $$, $$->tag,$$->level,currBlockno, 0);
806 };
807
808 stag
809 :  identifier  {  /* add name to structure table */
810      $$ = findSymWithBlock (StructTab,$1,currBlockno);
811      if (! $$ ) {
812        $$ = newStruct($1->name) ;
813        $$->level = NestLevel ;
814        addSym (StructTab, $$, $$->tag,$$->level,currBlockno,0);
815      }
816 };
817
818
819 struct_declaration_list
820    : struct_declaration
821    | struct_declaration_list struct_declaration
822        {
823            symbol *sym=$2;
824
825            /* go to the end of the chain */
826            while (sym->next) sym=sym->next;
827            sym->next = $1 ;
828          
829            $$ = $2;
830        }
831    ;
832
833 struct_declaration
834    : type_specifier_list struct_declarator_list ';'
835        {
836            /* add this type to all the symbols */
837            symbol *sym ;
838            for ( sym = $2 ; sym != NULL ; sym = sym->next ) {
839                sym_link *btype = copyLinkChain($1);
840                
841                /* make the symbol one level up */
842                sym->level-- ;
843
844                pointerTypes(sym->type,btype);
845                if (!sym->type) {
846                    sym->type = btype;
847                    sym->etype = getSpec(sym->type);
848                }
849                else
850                  addDecl (sym,0,btype);
851                /* make sure the type is complete and sane */
852                checkTypeSanity(sym->etype, sym->name);
853            }
854            ignoreTypedefType = 0;
855            $$ = $2;
856        }
857    ;
858
859 struct_declarator_list
860    : struct_declarator
861    | struct_declarator_list ',' struct_declarator
862        {
863            $3->next  = $1 ;
864            $$ = $3 ;
865        }
866    ;
867
868 struct_declarator
869    : declarator 
870    | ':' constant_expr  {
871                            int bitsize;
872                            $$ = newSymbol (genSymName(NestLevel),NestLevel) ; 
873                            bitsize= (int) floatFromVal(constExprValue($2,TRUE));
874                            if (bitsize > (port->s.int_size * 8)) {
875                              bitsize = port->s.int_size * 8;
876                              werror(E_BITFLD_SIZE, bitsize);
877                            }
878                            if (!bitsize)
879                              bitsize = BITVAR_PAD;
880                            $$->bitVar = bitsize;
881                         }                        
882    | declarator ':' constant_expr 
883                         {
884                           int bitsize;
885                           bitsize= (int) floatFromVal(constExprValue($3,TRUE));
886                           if (bitsize > (port->s.int_size * 8)) {
887                             bitsize = port->s.int_size * 8;
888                             werror(E_BITFLD_SIZE, bitsize);
889                           }
890                           if (!bitsize) {
891                             $$ = newSymbol (genSymName(NestLevel),NestLevel) ; 
892                             $$->bitVar = BITVAR_PAD;
893                             werror(W_BITFLD_NAMED);
894                           }
895                           else
896                             $1->bitVar = bitsize;
897                         }
898    ;
899
900 enum_specifier
901    : ENUM            '{' enumerator_list '}' {
902            $$ = newEnumType ($3);       //copyLinkChain(cenum->type);
903            SPEC_SCLS(getSpec($$)) = 0;
904          }
905
906    | ENUM identifier '{' enumerator_list '}' {
907      symbol *csym ;
908      sym_link *enumtype;
909
910      csym=findSym(enumTab,$2,$2->name);
911      if ((csym && csym->level == $2->level))
912        werrorfl($2->fileDef, $2->lineDef, E_DUPLICATE_TYPEDEF,csym->name);
913      
914      enumtype = newEnumType ($4);       //copyLinkChain(cenum->type);
915      SPEC_SCLS(getSpec(enumtype)) = 0;
916      $2->type = enumtype;
917      
918      /* add this to the enumerator table */
919      if (!csym)
920        addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
921      $$ = copyLinkChain(enumtype);
922    }
923    | ENUM identifier                         {
924      symbol *csym ;
925      
926      /* check the enumerator table */
927      if ((csym = findSym(enumTab,$2,$2->name)))
928        $$ = copyLinkChain(csym->type);
929      else  {
930        $$ = newLink(SPECIFIER) ;
931        SPEC_NOUN($$) = V_INT   ;
932      }
933    }
934    ;
935
936 enumerator_list
937    : enumerator
938    | enumerator_list ',' {
939                          }
940    | enumerator_list ',' enumerator
941      {
942        symbol *dsym;
943        
944        for (dsym=$1; dsym; dsym=dsym->next)
945          {
946            if (strcmp($3->name, dsym->name)==0)
947              werrorfl($3->fileDef, $3->lineDef, E_DUPLICATE_MEMBER, "enum", $3->name);
948          }
949        
950        $3->next = $1 ;
951        $$ = $3  ;
952      }
953    ;
954
955 enumerator
956    : identifier opt_assign_expr  
957      {
958        /* make the symbol one level up */
959        $1->level-- ;
960        $1->type = copyLinkChain($2->type); 
961        $1->etype= getSpec($1->type);
962        SPEC_ENUM($1->etype) = 1;
963        $$ = $1 ;
964        // do this now, so we can use it for the next enums in the list
965        addSymChain($1);
966      }
967    ;
968
969 opt_assign_expr
970    :  '='   constant_expr  {
971                               value *val ;
972
973                               val = constExprValue($2,TRUE);
974                               if (!IS_INT(val->type) && !IS_CHAR(val->type))
975                                 {
976                                   werror(E_ENUM_NON_INTEGER);
977                                   SNPRINTF(lbuff, sizeof(lbuff), 
978                                           "%d",(int) floatFromVal(val));
979                                   val = constVal(lbuff);
980                                 }
981                               $$ = cenum = val ;
982                            }                           
983    |                       {                              
984                               if (cenum)  {
985                                  SNPRINTF(lbuff, sizeof(lbuff), 
986                                           "%d",(int) floatFromVal(cenum)+1);
987                                  $$ = cenum = constVal(lbuff);
988                               }
989                               else {
990                                  SNPRINTF(lbuff, sizeof(lbuff), 
991                                           "%d",0);
992                                  $$ = cenum = constVal(lbuff);
993                               }   
994                            }
995    ;
996
997 declarator
998    : declarator3                        { $$ = $1 ; } 
999    | pointer declarator3
1000          {
1001              addDecl ($2,0,reverseLink($1));
1002              $$ = $2 ;
1003          }
1004    ;
1005
1006 declarator3
1007    : declarator2_function_attributes    { $$ = $1 ; }
1008    | declarator2                        { $$ = $1 ; }
1009    ;
1010
1011 function_declarator
1012    : declarator2_function_attributes    { $$ = $1; }
1013    | pointer declarator2_function_attributes
1014          {
1015              addDecl ($2,0,reverseLink($1));
1016              $$ = $2 ;
1017          }
1018    ;
1019    
1020 declarator2_function_attributes
1021    : function_declarator2                 { $$ = $1 ; } 
1022    | function_declarator2 function_attribute  { 
1023            // copy the functionAttributes (not the args and hasVargs !!)
1024            struct value *args;
1025            unsigned hasVargs;
1026            sym_link *funcType=$1->type;
1027
1028            while (funcType && !IS_FUNC(funcType))
1029              funcType = funcType->next;
1030            
1031            if (!funcType)
1032              werror (E_FUNC_ATTR);
1033            else
1034              {
1035                args=FUNC_ARGS(funcType);
1036                hasVargs=FUNC_HASVARARGS(funcType);
1037
1038                memcpy (&funcType->funcAttrs, &$2->funcAttrs, 
1039                    sizeof($2->funcAttrs));
1040
1041                FUNC_ARGS(funcType)=args;
1042                FUNC_HASVARARGS(funcType)=hasVargs;
1043
1044                // just to be sure
1045                memset (&$2->funcAttrs, 0,
1046                    sizeof($2->funcAttrs));
1047            
1048                addDecl ($1,0,$2); 
1049              }
1050    }     
1051    ;
1052
1053 declarator2
1054    : identifier
1055    | '(' declarator ')'     { $$ = $2; }
1056    | declarator3 '[' ']'
1057          {
1058             sym_link   *p;
1059
1060             p = newLink (DECLARATOR);
1061             DCL_TYPE(p) = ARRAY ;
1062             DCL_ELEM(p) = 0     ;
1063             addDecl($1,0,p);
1064          }
1065    | declarator3 '[' constant_expr ']'
1066          {
1067             sym_link   *p ;
1068                         value *tval;
1069                         
1070             tval = constExprValue($3,TRUE);
1071             /* if it is not a constant then Error  */
1072             p = newLink (DECLARATOR);
1073             DCL_TYPE(p) = ARRAY ;
1074             if ( !tval || (SPEC_SCLS(tval->etype) != S_LITERAL)) {
1075                werror(E_CONST_EXPECTED) ;
1076                /* Assume a single item array to limit the cascade */
1077                /* of additional errors. */
1078                DCL_ELEM(p) = 1;
1079             }
1080             else {
1081                DCL_ELEM(p) = (int) floatFromVal(tval) ;
1082             }                           
1083             addDecl($1,0,p);
1084          }
1085    ;
1086
1087 function_declarator2
1088    : declarator2 '('  ')'       {  addDecl ($1,FUNCTION,NULL) ;   }
1089    | declarator2 '('            { NestLevel++ ; currBlockno++;  }
1090                      parameter_type_list ')'
1091          {
1092              sym_link *funcType;
1093            
1094              addDecl ($1,FUNCTION,NULL) ;
1095
1096              funcType = $1->type;
1097              while (funcType && !IS_FUNC(funcType))
1098                funcType = funcType->next;
1099            
1100              assert (funcType);
1101              
1102              FUNC_HASVARARGS(funcType) = IS_VARG($4);
1103              FUNC_ARGS(funcType) = reverseVal($4);
1104              
1105              /* nest level was incremented to take care of the parms  */
1106              NestLevel-- ;
1107              currBlockno--;
1108
1109              // if this was a pointer (to a function)
1110              if (!IS_FUNC($1->type))
1111                cleanUpLevel(SymbolTab,NestLevel+1);
1112              
1113              $$ = $1;
1114          }
1115    | declarator2 '(' parameter_identifier_list ')'
1116          {         
1117            werror(E_OLD_STYLE,$1->name) ;         
1118            /* assume it returns an int */
1119            $1->type = $1->etype = newIntLink();
1120            $$ = $1 ;
1121          }
1122    ;
1123    
1124 pointer
1125    : unqualified_pointer { $$ = $1 ;}
1126    | unqualified_pointer type_specifier_list   
1127          {
1128              $$ = $1  ;
1129              if (IS_SPEC($2)) {
1130                  DCL_TSPEC($1) = $2;
1131                  DCL_PTR_CONST($1) = SPEC_CONST($2);
1132                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
1133              }
1134              else
1135                  werror (W_PTR_TYPE_INVALID);
1136          }
1137    | unqualified_pointer pointer         
1138          {
1139              $$ = $1 ;          
1140              $$->next = $2 ;
1141              DCL_TYPE($2)=port->unqualified_pointer;
1142          }
1143    | unqualified_pointer type_specifier_list pointer
1144          {
1145              $$ = $1 ;               
1146              if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
1147                  DCL_PTR_CONST($1) = SPEC_CONST($2);
1148                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
1149                  switch (SPEC_SCLS($2)) {
1150                  case S_XDATA:
1151                      DCL_TYPE($3) = FPOINTER;
1152                      break;
1153                  case S_IDATA:
1154                      DCL_TYPE($3) = IPOINTER ;
1155                      break;
1156                  case S_PDATA:
1157                      DCL_TYPE($3) = PPOINTER ;
1158                      break;
1159                  case S_DATA:
1160                      DCL_TYPE($3) = POINTER ;
1161                      break;
1162                  case S_CODE:
1163                      DCL_TYPE($3) = CPOINTER ;
1164                      break;
1165                  case S_EEPROM:
1166                      DCL_TYPE($3) = EEPPOINTER;
1167                      break;
1168                  default:
1169                    // this could be just "constant" 
1170                    // werror(W_PTR_TYPE_INVALID);
1171                      ;
1172                  }
1173              }
1174              else 
1175                  werror (W_PTR_TYPE_INVALID);
1176              $$->next = $3 ;
1177          }
1178    ;
1179
1180 unqualified_pointer
1181    :  '*'   
1182       {
1183         $$ = newLink(DECLARATOR);
1184         DCL_TYPE($$)=UPOINTER;
1185       }
1186    ;
1187
1188 type_specifier_list
1189    : type_specifier
1190    //| type_specifier_list type_specifier         {  $$ = mergeSpec ($1,$2, "type_specifier_list"); }
1191    | type_specifier_list type_specifier {
1192      /* if the decl $2 is not a specifier */
1193      /* find the spec and replace it      */
1194      if ( !IS_SPEC($2)) {
1195        sym_link *lnk = $2 ;
1196        while (lnk && !IS_SPEC(lnk->next))
1197          lnk = lnk->next;
1198        lnk->next = mergeSpec($1,lnk->next, "type_specifier_list type_specifier skipped");
1199        $$ = $2 ;
1200      }
1201      else
1202        $$ = mergeSpec($1,$2, "type_specifier_list type_specifier");
1203    }
1204    ;
1205
1206 parameter_identifier_list
1207    : identifier_list
1208    | identifier_list ',' ELIPSIS
1209    ;
1210
1211 identifier_list
1212    : identifier
1213    | identifier_list ',' identifier         
1214          {            
1215            $3->next = $1;
1216            $$ = $3 ;
1217          }
1218    ;
1219
1220 parameter_type_list
1221         : parameter_list
1222         | parameter_list ',' VAR_ARGS { $1->vArgs = 1;}
1223         ;
1224
1225 parameter_list
1226    : parameter_declaration
1227    | parameter_list ',' parameter_declaration
1228          {
1229             $3->next = $1 ;
1230             $$ = $3 ;
1231          }
1232    ;
1233
1234 parameter_declaration
1235    : type_specifier_list declarator 
1236                {        
1237                   symbol *loop ;
1238                   pointerTypes($2->type,$1);
1239                   addDecl ($2,0,$1);              
1240                   for (loop=$2;loop;loop->_isparm=1,loop=loop->next);
1241                   addSymChain ($2);
1242                   $$ = symbolVal($2);
1243                   ignoreTypedefType = 0;
1244                }
1245    | type_name { 
1246                   $$ = newValue() ; 
1247                   $$->type = $1;
1248                   $$->etype = getSpec($$->type);
1249                   ignoreTypedefType = 0;
1250                }
1251    ;
1252
1253 type_name
1254    : type_specifier_list  { $$ = $1; ignoreTypedefType = 0;}
1255    | type_specifier_list abstract_declarator 
1256                {
1257                  /* go to the end of the list */
1258                  sym_link *p;
1259                  pointerTypes($2,$1);
1260                  for ( p = $2 ; p && p->next ; p=p->next);
1261                  if (!p) {
1262                    werror(E_SYNTAX_ERROR, yytext);
1263                  } else {
1264                    p->next = $1 ;
1265                  }
1266                  $$ = $2 ;
1267                  ignoreTypedefType = 0;
1268                }   
1269    ;
1270
1271 abstract_declarator
1272    : pointer { $$ = reverseLink($1); }
1273    | abstract_declarator2
1274    | pointer abstract_declarator2   { $1 = reverseLink($1); $1->next = $2 ; $$ = $1;
1275           if (IS_PTR($1) && IS_FUNC($2))
1276             DCL_TYPE($1) = CPOINTER;
1277         } 
1278    ;
1279
1280 abstract_declarator2
1281    : '(' abstract_declarator ')'    { $$ = $2 ; }
1282    | '[' ']'                        {             
1283                                        $$ = newLink (DECLARATOR);
1284                                        DCL_TYPE($$) = ARRAY ;
1285                                        DCL_ELEM($$) = 0     ;
1286                                     }
1287    | '[' constant_expr ']'          { 
1288                                        value *val ;
1289                                        $$ = newLink (DECLARATOR);
1290                                        DCL_TYPE($$) = ARRAY ;
1291                                        DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($2,TRUE));
1292                                     }
1293    | abstract_declarator2 '[' ']'   {
1294                                        $$ = newLink (DECLARATOR);
1295                                        DCL_TYPE($$) = ARRAY ;
1296                                        DCL_ELEM($$) = 0     ;
1297                                        $$->next = $1 ;
1298                                     }
1299    | abstract_declarator2 '[' constant_expr ']'
1300                                     {
1301                                        value *val ;
1302                                        $$ = newLink (DECLARATOR);
1303                                        DCL_TYPE($$) = ARRAY ;
1304                                        DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($3,TRUE));
1305                                        $$->next = $1 ;
1306                                     }
1307    | '(' ')'                        { $$ = NULL;}
1308    | '(' parameter_type_list ')'    { $$ = NULL;}   
1309    | abstract_declarator2 '(' ')' {
1310      // $1 must be a pointer to a function
1311      sym_link *p=newLink(DECLARATOR);
1312      DCL_TYPE(p) = FUNCTION;
1313      if (!$1) {
1314        // ((void (code *) ()) 0) ()
1315        $1=newLink(DECLARATOR);
1316        DCL_TYPE($1)=CPOINTER;
1317        $$ = $1;
1318      }
1319      $1->next=p;
1320    }
1321    | abstract_declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')' {
1322        sym_link *p=newLink(DECLARATOR);
1323        DCL_TYPE(p) = FUNCTION;
1324            
1325        FUNC_HASVARARGS(p) = IS_VARG($4);
1326        FUNC_ARGS(p) = reverseVal($4);
1327              
1328        /* nest level was incremented to take care of the parms  */
1329        NestLevel-- ;
1330        currBlockno--;
1331        p->next = $1;
1332        $$ = p;
1333
1334        // remove the symbol args (if any)
1335        cleanUpLevel(SymbolTab,NestLevel+1);
1336    }
1337    ;
1338
1339 initializer
1340    : assignment_expr                { $$ = newiList(INIT_NODE,$1); }
1341    | '{'  initializer_list '}'      { $$ = newiList(INIT_DEEP,revinit($2)); }
1342    | '{'  initializer_list ',' '}'  { $$ = newiList(INIT_DEEP,revinit($2)); }
1343    ;
1344
1345 initializer_list
1346    : initializer
1347    | initializer_list ',' initializer  {  $3->next = $1; $$ = $3; }
1348    ;
1349
1350 statement
1351    : labeled_statement
1352    | compound_statement
1353    | expression_statement
1354    | selection_statement
1355    | iteration_statement
1356    | jump_statement
1357    | critical_statement
1358    | INLINEASM  ';'      {
1359                             ast *ex;
1360                             seqPointNo++;
1361                             ex = newNode(INLINEASM,NULL,NULL);
1362                             ex->values.inlineasm = strdup($1);
1363                             seqPointNo++;
1364                             $$ = ex;
1365                          } 
1366    ;
1367
1368 critical
1369    : CRITICAL   {
1370                    inCritical++;
1371                    STACK_PUSH(continueStack,NULL);
1372                    STACK_PUSH(breakStack,NULL);
1373                    $$ = NULL;
1374                 }
1375    ;
1376    
1377 critical_statement
1378    : critical statement  {
1379                    STACK_POP(breakStack);
1380                    STACK_POP(continueStack);
1381                    inCritical--;
1382                    $$ = newNode(CRITICAL,$2,NULL);
1383                 }
1384    ;
1385       
1386 labeled_statement
1387 //   : identifier ':' statement          {  $$ = createLabel($1,$3);  }   
1388    : identifier ':'                    {  $$ = createLabel($1,NULL);  }   
1389    | CASE constant_expr ':' statement
1390      {
1391        if (STACK_EMPTY(swStk))
1392          $$ = createCase(NULL,$2,$4);
1393        else
1394          $$ = createCase(STACK_PEEK(swStk),$2,$4);
1395      }
1396    | DEFAULT { $<asts>$ = newNode(DEFAULT,NULL,NULL); } ':' statement
1397      {
1398        if (STACK_EMPTY(swStk))
1399          $$ = createDefault(NULL,$<asts>2,$4);
1400        else
1401          $$ = createDefault(STACK_PEEK(swStk),$<asts>2,$4);
1402      }
1403    ;
1404
1405 start_block : '{'
1406               {
1407                 STACK_PUSH(blockNum,currBlockno);
1408                 currBlockno = ++blockNo ;
1409                 ignoreTypedefType = 0;
1410               }
1411             ;
1412
1413 end_block   : '}'     { currBlockno = STACK_POP(blockNum); }           
1414             ;
1415
1416 compound_statement
1417    : start_block end_block                    { $$ = createBlock(NULL,NULL); }
1418    | start_block statement_list end_block     { $$ = createBlock(NULL,$2) ;  }
1419    | start_block 
1420           declaration_list                    { addSymChain($2); }
1421      end_block                                { $$ = createBlock($2,NULL) ;  }
1422    | start_block 
1423           declaration_list                    {  addSymChain ($2); }
1424           statement_list   
1425      end_block                                {$$ = createBlock($2,$4)   ;  }
1426    | error ';'                                { $$ = NULL ; }
1427    ;
1428
1429 declaration_list
1430    : declaration        
1431      {
1432        /* if this is typedef declare it immediately */
1433        if ( $1 && IS_TYPEDEF($1->etype)) {
1434          allocVariables ($1);
1435          $$ = NULL ;
1436        }
1437        else
1438          $$ = $1 ;
1439        ignoreTypedefType = 0;
1440      }
1441
1442    | declaration_list declaration
1443      {
1444        symbol   *sym;
1445        
1446        /* if this is a typedef */
1447        if ($2 && IS_TYPEDEF($2->etype)) {
1448          allocVariables ($2);
1449          $$ = $1 ;
1450        }
1451        else {
1452                                 /* get to the end of the previous decl */
1453          if ( $1 ) {
1454            $$ = sym = $1 ;
1455            while (sym->next)
1456              sym = sym->next ;
1457            sym->next = $2;
1458          } 
1459          else
1460            $$ = $2 ;
1461        }
1462        ignoreTypedefType = 0;
1463      }
1464    ;
1465
1466 statement_list
1467    : statement
1468    | statement_list statement          {  $$ = newNode(NULLOP,$1,$2) ;}
1469    ;
1470
1471 expression_statement
1472    : ';'                { $$ = NULL;}
1473    | expr ';'           { $$ = $1; seqPointNo++;} 
1474    ;
1475
1476 else_statement
1477    :  ELSE  statement   { $$ = $2  ; }
1478    |                    { $$ = NULL;}
1479    ;
1480
1481   
1482 selection_statement
1483    : IF '(' expr ')' { seqPointNo++;} statement else_statement
1484                            {
1485                               noLineno++ ;
1486                               $$ = createIf ($3, $6, $7 );
1487                               noLineno--;
1488                            }
1489    | SWITCH '(' expr ')'   { 
1490                               ast *ex ;                              
1491                               static   int swLabel = 0 ;
1492
1493                               seqPointNo++;
1494                               /* create a node for expression  */
1495                               ex = newNode(SWITCH,$3,NULL);
1496                               STACK_PUSH(swStk,ex);   /* save it in the stack */
1497                               ex->values.switchVals.swNum = swLabel ;
1498                                  
1499                               /* now create the label */
1500                               SNPRINTF(lbuff, sizeof(lbuff), 
1501                                        "_swBrk_%d",swLabel++);
1502                               $<sym>$  =  newSymbol(lbuff,NestLevel);
1503                               /* put label in the break stack  */
1504                               STACK_PUSH(breakStack,$<sym>$);   
1505                            }
1506      statement             {  
1507                               /* get back the switch form the stack  */
1508                               $$ = STACK_POP(swStk)  ;
1509                               $$->right = newNode (NULLOP,$6,createLabel($<sym>5,NULL));
1510                               STACK_POP(breakStack);   
1511                            }
1512         ;
1513
1514 while : WHILE  {  /* create and push the continue , break & body labels */
1515                   static int Lblnum = 0 ;
1516                   /* continue */
1517                   SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum);
1518                   STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1519                   /* break */
1520                   SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum);
1521                   STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1522                   /* body */
1523                   SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++);
1524                   $$ = newSymbol(lbuff,NestLevel);
1525                }
1526    ;
1527
1528 do : DO {  /* create and push the continue , break & body Labels */
1529            static int Lblnum = 0 ;
1530
1531            /* continue */
1532            SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum);
1533            STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1534            /* break */
1535            SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum);
1536            STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1537            /* do body */
1538            SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++);
1539            $$ = newSymbol (lbuff,NestLevel);       
1540         }
1541    ;
1542
1543 for : FOR { /* create & push continue, break & body labels */
1544             static int Lblnum = 0 ;
1545          
1546             /* continue */
1547             SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum);
1548             STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1549             /* break    */
1550             SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum);
1551             STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1552             /* body */
1553             SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum);
1554             $$ = newSymbol(lbuff,NestLevel);
1555             /* condition */
1556             SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++);
1557             STACK_PUSH(forStack,newSymbol(lbuff,NestLevel));
1558           }
1559    ;
1560
1561 iteration_statement  
1562    : while '(' expr ')' { seqPointNo++;}  statement 
1563                          { 
1564                            noLineno++ ;
1565                            $$ = createWhile ( $1, STACK_POP(continueStack),
1566                                               STACK_POP(breakStack), $3, $6 ); 
1567                            $$->lineno = $1->lineDef ;
1568                            noLineno-- ;
1569                          }
1570    | do statement   WHILE '(' expr ')' ';' 
1571                         { 
1572                           seqPointNo++; 
1573                           noLineno++ ; 
1574                           $$ = createDo ( $1 , STACK_POP(continueStack), 
1575                                           STACK_POP(breakStack), $5, $2);
1576                           $$->lineno = $1->lineDef ;
1577                           noLineno-- ;
1578                         }                                                 
1579    | for '(' expr_opt   ';' expr_opt ';' expr_opt ')'  statement   
1580                         {
1581                           noLineno++ ;  
1582                           
1583                           /* if break or continue statement present
1584                              then create a general case loop */
1585                           if (STACK_PEEK(continueStack)->isref ||
1586                               STACK_PEEK(breakStack)->isref) {
1587                               $$ = createFor ($1, STACK_POP(continueStack),
1588                                               STACK_POP(breakStack) ,
1589                                               STACK_POP(forStack)   ,
1590                                               $3 , $5 , $7, $9 );
1591                           } else {
1592                               $$ = newNode(FOR,$9,NULL);
1593                               AST_FOR($$,trueLabel) = $1;
1594                               AST_FOR($$,continueLabel) =  STACK_POP(continueStack);
1595                               AST_FOR($$,falseLabel) = STACK_POP(breakStack);
1596                               AST_FOR($$,condLabel)  = STACK_POP(forStack)  ;
1597                               AST_FOR($$,initExpr)   = $3;
1598                               AST_FOR($$,condExpr)   = $5;
1599                               AST_FOR($$,loopExpr)   = $7;
1600                           }
1601                           
1602                           noLineno-- ;
1603                         }
1604 ;
1605
1606 expr_opt
1607         :                       { $$ = NULL ; seqPointNo++; }
1608         |       expr            { $$ = $1 ; seqPointNo++; }
1609         ;
1610
1611 jump_statement          
1612    : GOTO identifier ';'   { 
1613                               $2->islbl = 1;
1614                               $$ = newAst_VALUE(symbolVal($2)); 
1615                               $$ = newNode(GOTO,$$,NULL);
1616                            }
1617    | CONTINUE ';'          {  
1618        /* make sure continue is in context */
1619        if (STACK_EMPTY(continueStack) || STACK_PEEK(continueStack) == NULL) {
1620            werror(E_BREAK_CONTEXT);
1621            $$ = NULL;
1622        }
1623        else {
1624            $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack)));      
1625            $$ = newNode(GOTO,$$,NULL);
1626            /* mark the continue label as referenced */
1627            STACK_PEEK(continueStack)->isref = 1;
1628        }
1629    }
1630    | BREAK ';'             { 
1631        if (STACK_EMPTY(breakStack) || STACK_PEEK(breakStack) == NULL) {
1632            werror(E_BREAK_CONTEXT);
1633            $$ = NULL;
1634        } else {
1635            $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack)));
1636            $$ = newNode(GOTO,$$,NULL);
1637            STACK_PEEK(breakStack)->isref = 1;
1638        }
1639    }
1640    | RETURN ';'            {
1641        seqPointNo++;
1642        if (inCritical) {
1643            werror(E_INVALID_CRITICAL);
1644            $$ = NULL;
1645        } else {
1646            $$ = newNode(RETURN,NULL,NULL);
1647        }
1648    }
1649    | RETURN expr ';'       {
1650        seqPointNo++;
1651        if (inCritical) {
1652            werror(E_INVALID_CRITICAL);
1653            $$ = NULL;
1654        } else {
1655            $$ = newNode(RETURN,NULL,$2);
1656        }
1657    }
1658    ;
1659
1660 identifier
1661    : IDENTIFIER   { $$ = newSymbol ($1,NestLevel) ; }
1662    ;
1663 %%
1664