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