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