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