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