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