644ecc5196dce307a181e688905d42c00e4498a2
[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            symbol *sym, *dsym;
666
667            // check for duplicate structure members
668            for (sym=$4; sym; sym=sym->next) {
669              for (dsym=sym->next; dsym; dsym=dsym->next) {
670                if (strcmp(sym->name, dsym->name)==0) {
671                  werror(E_DUPLICATE_MEMBER, 
672                         $1==STRUCT ? "struct" : "union", sym->name);
673                }
674              }
675            }
676
677            /* Create a structdef   */      
678            sdef = $2 ;
679            sdef->fields   = reverseSyms($4) ;   /* link the fields */
680            sdef->size  = compStructSize($1,sdef);   /* update size of  */
681
682            /* Create the specifier */
683            $$ = newLink (SPECIFIER) ;
684            SPEC_NOUN($$) = V_STRUCT;
685            SPEC_STRUCT($$)= sdef ;
686         }
687    | struct_or_union stag
688          {
689             $$ = newLink(SPECIFIER) ;
690             SPEC_NOUN($$) = V_STRUCT;
691             SPEC_STRUCT($$) = $2 ;
692          }
693    ;
694
695 struct_or_union
696    : STRUCT          { $$ = STRUCT ; }
697    | UNION           { $$ = UNION  ; }
698    ;
699
700 opt_stag
701 : stag
702 |  {  /* synthesize a name add to structtable */
703      $$ = newStruct(genSymName(NestLevel)) ;
704      $$->level = NestLevel ;
705      addSym (StructTab, $$, $$->tag,$$->level,currBlockno, 0);
706 };
707
708 stag
709 :  identifier  {  /* add name to structure table */
710      $$ = findSymWithBlock (StructTab,$1,currBlockno);
711      if (! $$ ) {
712        $$ = newStruct($1->name) ;
713        $$->level = NestLevel ;
714        addSym (StructTab, $$, $$->tag,$$->level,currBlockno,0);
715      }
716 };
717
718
719 struct_declaration_list
720    : struct_declaration
721    | struct_declaration_list struct_declaration
722        {
723            symbol *sym=$2;
724
725            /* go to the end of the chain */
726            while (sym->next) sym=sym->next;
727            sym->next = $1 ;
728          
729            $$ = $2;
730        }
731    ;
732
733 struct_declaration
734    : type_specifier_list struct_declarator_list ';'
735        {
736            /* add this type to all the symbols */
737            symbol *sym ;
738            for ( sym = $2 ; sym != NULL ; sym = sym->next ) {
739                
740                /* make the symbol one level up */
741                sym->level-- ;
742
743                pointerTypes(sym->type,copyLinkChain($1));
744                if (!sym->type) {
745                    sym->type = copyLinkChain($1);
746                    sym->etype = getSpec(sym->type);
747                }
748                else
749                  addDecl (sym,0,copyLinkChain($1));
750                /* make sure the type is complete and sane */
751                checkTypeSanity(sym->etype, sym->name);
752            }
753            $$ = $2;
754        }
755    ;
756
757 struct_declarator_list
758    : struct_declarator
759    | struct_declarator_list ',' struct_declarator
760        {
761            $3->next  = $1 ;
762            $$ = $3 ;
763        }
764    ;
765
766 struct_declarator
767    : declarator 
768    | ':' constant_expr  {  
769                            $$ = newSymbol (genSymName(NestLevel),NestLevel) ; 
770                            $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE));
771                         }                        
772    | declarator ':' constant_expr 
773                         { 
774                           $1->bitVar = (int) floatFromVal(constExprValue($3,TRUE));                     
775                         }
776    ;
777
778 enum_specifier
779    : ENUM            '{' enumerator_list '}' {
780            symbol *sym, *dsym;
781            char _error=0;
782
783            // check for duplicate enums
784            for (sym=$3; sym; sym=sym->next) {
785              for (dsym=sym->next; dsym; dsym=dsym->next) {
786                if (strcmp(sym->name, dsym->name)==0) {
787                  werror(E_DUPLICATE_MEMBER, "enum", sym->name);
788                  _error++;
789                }
790              }
791            }
792            if (_error==0) {
793              $$ = copyLinkChain(cenum->type);
794            } else {
795              $$ = newIntLink();
796              SPEC_NOUN($$)=0;
797            }
798          }
799
800    | ENUM identifier '{' enumerator_list '}' {
801      symbol *csym ;
802      
803      $2->type = copyLinkChain(cenum->type);
804      $2->etype = getSpec($2->type);
805      /* add this to the enumerator table */
806      if (!(csym=findSym(enumTab,$2,$2->name)) && 
807          (csym && csym->level == $2->level))
808        werror(E_DUPLICATE_TYPEDEF,csym->name);
809      
810      addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
811      //addSymChain ($4);
812      //allocVariables (reverseSyms($4));
813      $$ = copyLinkChain(cenum->type);
814      SPEC_SCLS(getSpec($$)) = 0 ;
815    }
816    | ENUM identifier                         {
817      symbol *csym ;
818      
819      /* check the enumerator table */
820      if ((csym = findSym(enumTab,$2,$2->name)))
821        $$ = copyLinkChain(csym->type);
822      else  {
823        $$ = newLink(SPECIFIER) ;
824        SPEC_NOUN($$) = V_INT   ;
825      }
826      
827      SPEC_SCLS(getSpec($$)) = 0 ;
828    }
829    ;
830
831 enumerator_list
832    : enumerator
833    | enumerator_list ',' {
834                          }
835    | enumerator_list ',' enumerator {
836                                        $3->next = $1 ;
837                                        $$ = $3  ;
838                                     }
839    ;
840
841 enumerator
842    : identifier opt_assign_expr  
843      {
844        /* make the symbol one level up */
845        $1->level-- ;
846        $1->type = copyLinkChain($2->type); 
847        $1->etype= getSpec($1->type);
848        SPEC_ENUM($1->etype) = 1;
849        $$ = $1 ;
850        // do this now, so we can use it for the next enums in the list
851        addSymChain($1);
852      }
853    ;
854
855 opt_assign_expr
856    :  '='   constant_expr  {
857                               value *val ;
858                                                         
859                               val = constExprValue($2,TRUE);                         
860                               $$ = cenum = val ;
861                            }                           
862    |                       {                              
863                               if (cenum)  {
864                                  SNPRINTF(lbuff, sizeof(lbuff), 
865                                           "%d",(int) floatFromVal(cenum)+1);
866                                  $$ = cenum = constVal(lbuff);
867                               }
868                               else {
869                                  SNPRINTF(lbuff, sizeof(lbuff), 
870                                           "%d",0);
871                                  $$ = cenum = constVal(lbuff);
872                               }   
873                            }
874    ;
875
876 declarator
877    : declarator2_function_attributes    { $$ = $1; }
878    | pointer declarator2_function_attributes
879          {
880              addDecl ($2,0,reverseLink($1));
881              $$ = $2 ;
882          }
883    ;
884
885 declarator2_function_attributes
886    : declarator2                  { $$ = $1 ; } 
887    | declarator2 function_attribute  { 
888        // copy the functionAttributes (not the args and hasVargs !!)
889        sym_link *funcType=$1->etype;
890        struct value *args=FUNC_ARGS(funcType);
891        unsigned hasVargs=FUNC_HASVARARGS(funcType);
892
893        memcpy (&funcType->funcAttrs, &$2->funcAttrs, 
894                sizeof($2->funcAttrs));
895
896        FUNC_ARGS(funcType)=args;
897        FUNC_HASVARARGS(funcType)=hasVargs;
898
899        // just to be sure
900        memset (&$2->funcAttrs, 0,
901                sizeof($2->funcAttrs));
902        
903        addDecl ($1,0,$2); 
904    }     
905    ;
906
907 declarator2
908    : identifier
909    | '(' declarator ')'     { $$ = $2; }
910    | declarator2 '[' ']'
911          {
912             sym_link   *p;
913
914             p = newLink (DECLARATOR);
915             DCL_TYPE(p) = ARRAY ;
916             DCL_ELEM(p) = 0     ;
917             addDecl($1,0,p);
918          }
919    | declarator2 '[' constant_expr ']'
920          {
921             sym_link   *p ;
922                         value *tval;
923                         
924             p = (tval = constExprValue($3,TRUE))->etype;
925             /* if it is not a constant then Error  */
926             if ( SPEC_SCLS(p) != S_LITERAL)
927                werror(E_CONST_EXPECTED) ;
928             else {
929                p = newLink (DECLARATOR);
930                DCL_TYPE(p) = ARRAY ;
931                DCL_ELEM(p) = (int) floatFromVal(tval) ;
932                addDecl($1,0,p);
933             }                           
934          }
935    | declarator2 '('  ')'       {  addDecl ($1,FUNCTION,NULL) ;   }
936    | declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')'
937          {
938            
939              addDecl ($1,FUNCTION,NULL) ;
940            
941              FUNC_HASVARARGS($1->type) = IS_VARG($4);
942              FUNC_ARGS($1->type) = reverseVal($4);
943              
944              /* nest level was incremented to take care of the parms  */
945              NestLevel-- ;
946              currBlockno--;
947
948              // if this was a pointer (to a function)
949              if (IS_PTR($1->type)) {
950                // move the args and hasVargs to the function
951                FUNC_ARGS($1->etype)=FUNC_ARGS($1->type);
952                FUNC_HASVARARGS($1->etype)=FUNC_HASVARARGS($1->type);
953                memset (&$1->type->funcAttrs, 0,
954                        sizeof($1->type->funcAttrs));
955                // remove the symbol args (if any)
956                cleanUpLevel(SymbolTab,NestLevel+1);
957              }
958              
959              $$ = $1;
960          }
961    | declarator2 '(' parameter_identifier_list ')'
962          {         
963            werror(E_OLD_STYLE,$1->name) ;         
964            
965            /* assume it returns an int */
966            $1->type = $1->etype = newIntLink();
967            $$ = $1 ;
968          }
969    ;
970
971 pointer
972    : unqualified_pointer { $$ = $1 ;}
973    | unqualified_pointer type_specifier_list   
974          {
975              $$ = $1  ;         
976              DCL_TSPEC($1) = $2;
977          }
978    | unqualified_pointer pointer         
979          {
980              $$ = $1 ;          
981              $$->next = $2 ;
982              DCL_TYPE($2)=port->unqualified_pointer;
983          }
984    | unqualified_pointer type_specifier_list pointer
985          {
986              $$ = $1 ;               
987              if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
988                  DCL_PTR_CONST($1) = SPEC_CONST($2);
989                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
990                  switch (SPEC_SCLS($2)) {
991                  case S_XDATA:
992                      DCL_TYPE($3) = FPOINTER;
993                      break;
994                  case S_IDATA:
995                      DCL_TYPE($3) = IPOINTER ;
996                      break;
997                  case S_PDATA:
998                      DCL_TYPE($3) = PPOINTER ;
999                      break;
1000                  case S_DATA:
1001                      DCL_TYPE($3) = POINTER ;
1002                      break;
1003                  case S_CODE:
1004                      DCL_PTR_CONST($3) = 1;
1005                      DCL_TYPE($3) = CPOINTER ;
1006                      break;
1007                  case S_EEPROM:
1008                      DCL_TYPE($3) = EEPPOINTER;
1009                      break;
1010                  default:
1011                    // this could be just "constant" 
1012                    // werror(W_PTR_TYPE_INVALID);
1013                      ;
1014                  }
1015              }
1016              else 
1017                  werror (W_PTR_TYPE_INVALID);
1018              $$->next = $3 ;
1019          }
1020    ;
1021
1022 unqualified_pointer
1023    :  '*'   
1024       {
1025         $$ = newLink(DECLARATOR);
1026         DCL_TYPE($$)=UPOINTER;
1027       }
1028    ;
1029
1030 type_specifier_list
1031    : type_specifier
1032    //| type_specifier_list type_specifier         {  $$ = mergeSpec ($1,$2, "type_specifier_list"); }
1033    | type_specifier_list type_specifier {
1034      /* if the decl $2 is not a specifier */
1035      /* find the spec and replace it      */
1036      if ( !IS_SPEC($2)) {
1037        sym_link *lnk = $2 ;
1038        while (lnk && !IS_SPEC(lnk->next))
1039          lnk = lnk->next;
1040        lnk->next = mergeSpec($1,lnk->next, "type_specifier_list type_specifier skipped");
1041        $$ = $2 ;
1042      }
1043      else
1044        $$ = mergeSpec($1,$2, "type_specifier_list type_specifier");
1045    }
1046    ;
1047
1048 parameter_identifier_list
1049    : identifier_list
1050    | identifier_list ',' ELIPSIS
1051    ;
1052
1053 identifier_list
1054    : identifier
1055    | identifier_list ',' identifier         
1056          {            
1057            $3->next = $1;
1058            $$ = $3 ;
1059          }
1060    ;
1061
1062 parameter_type_list
1063         : parameter_list
1064         | parameter_list ',' VAR_ARGS { $1->vArgs = 1;}
1065         ;
1066
1067 parameter_list
1068    : parameter_declaration 
1069    | parameter_list ',' parameter_declaration
1070          {
1071             $3->next = $1 ;
1072             $$ = $3 ;       
1073          }
1074    ;
1075
1076 parameter_declaration
1077    : type_specifier_list declarator 
1078                {        
1079                   symbol *loop ;
1080                   pointerTypes($2->type,$1);
1081                   addDecl ($2,0,$1);              
1082                   for (loop=$2;loop;loop->_isparm=1,loop=loop->next);
1083                   addSymChain ($2);
1084                   $$ = symbolVal($2);
1085                }
1086    | type_name { 
1087                   $$ = newValue() ; 
1088                   $$->type = $1;
1089                   $$->etype = getSpec($$->type);
1090                }
1091    ;
1092
1093 type_name
1094    : type_specifier_list  { $$ = $1 ;}
1095    | type_specifier_list abstract_declarator 
1096                {
1097                  /* go to the end of the list */
1098                  sym_link *p;
1099                  pointerTypes($2,$1);
1100                  for ( p = $2 ; p && p->next ; p=p->next);
1101                  if (!p) {
1102                    werror(E_SYNTAX_ERROR, yytext);
1103                  } else {
1104                    p->next = $1 ;
1105                  }
1106                  $$ = $2 ;
1107                }   
1108    ;
1109
1110 abstract_declarator
1111    : pointer { $$ = reverseLink($1); }
1112    | abstract_declarator2
1113    | pointer abstract_declarator2   { $1 = reverseLink($1); $1->next = $2 ; $$ = $1;} 
1114    ;
1115
1116 abstract_declarator2
1117    : '(' abstract_declarator ')'    { $$ = $2 ; }
1118    | '[' ']'                        {             
1119                                        $$ = newLink (DECLARATOR);
1120                                        DCL_TYPE($$) = ARRAY ;
1121                                        DCL_ELEM($$) = 0     ;
1122                                     }
1123    | '[' constant_expr ']'          { 
1124                                        value *val ;
1125                                        $$ = newLink (DECLARATOR);
1126                                        DCL_TYPE($$) = ARRAY ;
1127                                        DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($2,TRUE));
1128                                     }
1129    | abstract_declarator2 '[' ']'   {
1130                                        $$ = newLink (DECLARATOR);
1131                                        DCL_TYPE($$) = ARRAY ;
1132                                        DCL_ELEM($$) = 0     ;
1133                                        $$->next = $1 ;
1134                                     }
1135    | abstract_declarator2 '[' constant_expr ']'
1136                                     {
1137                                        value *val ;
1138                                        $$ = newLink (DECLARATOR);
1139                                        DCL_TYPE($$) = ARRAY ;
1140                                        DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($3,TRUE));
1141                                        $$->next = $1 ;
1142                                     }
1143    | '(' ')'                        { $$ = NULL;}
1144    | '(' parameter_type_list ')'    { $$ = NULL;}   
1145    | abstract_declarator2 '(' ')' {
1146      // $1 must be a pointer to a function
1147      sym_link *p=newLink(DECLARATOR);
1148      DCL_TYPE(p) = FUNCTION;
1149      if (!$1) {
1150        // ((void (code *) ()) 0) ()
1151        $1=newLink(DECLARATOR);
1152        DCL_TYPE($1)=CPOINTER;
1153        $$ = $1;
1154      }
1155      $1->next=p;
1156    }
1157    | abstract_declarator2 '(' parameter_type_list ')' {
1158      if (!IS_VOID($3->etype)) {
1159        // this is nonsense, so let's just burp something
1160        werror(E_TOO_FEW_PARMS);
1161      } else {
1162        // $1 must be a pointer to a function
1163        sym_link *p=newLink(DECLARATOR);
1164        DCL_TYPE(p) = FUNCTION;
1165        if (!$1) {
1166          // ((void (code *) (void)) 0) ()
1167          $1=newLink(DECLARATOR);
1168          DCL_TYPE($1)=CPOINTER;
1169          $$ = $1;
1170        }
1171        $1->next=p;
1172      }
1173    }
1174    ;
1175
1176 initializer
1177    : assignment_expr                { $$ = newiList(INIT_NODE,$1); }
1178    | '{'  initializer_list '}'      { $$ = newiList(INIT_DEEP,revinit($2)); }
1179    | '{'  initializer_list ',' '}'  { $$ = newiList(INIT_DEEP,revinit($2)); }
1180    ;
1181
1182 initializer_list
1183    : initializer
1184    | initializer_list ',' initializer  {  $3->next = $1; $$ = $3; }
1185    ;
1186
1187 statement
1188    : labeled_statement
1189    | compound_statement
1190    | expression_statement
1191    | selection_statement
1192    | iteration_statement
1193    | jump_statement
1194    | INLINEASM  ';'      {
1195                             ast *ex = newNode(INLINEASM,NULL,NULL);
1196                             ex->values.inlineasm = strdup($1);
1197                             $$ = ex;
1198                          } 
1199    ;
1200
1201 labeled_statement
1202 //   : identifier ':' statement          {  $$ = createLabel($1,$3);  }   
1203    : identifier ':'                    {  $$ = createLabel($1,NULL);  }   
1204    | CASE constant_expr ':' statement  {  $$ = createCase(STACK_PEEK(swStk),$2,$4); }
1205    | DEFAULT ':' statement             {  $$ = createDefault(STACK_PEEK(swStk),$3); }
1206    ;
1207
1208 start_block : '{' { STACK_PUSH(blockNum,currBlockno); currBlockno = ++blockNo ;  }
1209             ;
1210
1211 end_block   : '}'     { currBlockno = STACK_POP(blockNum); }           
1212             ;
1213
1214 compound_statement
1215    : start_block end_block                    { $$ = createBlock(NULL,NULL); }
1216    | start_block statement_list end_block     { $$ = createBlock(NULL,$2) ;  }
1217    | start_block 
1218           declaration_list                    { addSymChain($2); }
1219      end_block                                { $$ = createBlock($2,NULL) ;  }
1220    | start_block 
1221           declaration_list                    {  addSymChain ($2); }
1222           statement_list   
1223      end_block                                {$$ = createBlock($2,$4)   ;  }
1224    | error ';'                                { $$ = NULL ; }
1225    ;
1226
1227 declaration_list
1228    : declaration        
1229      {
1230        /* if this is typedef declare it immediately */
1231        if ( $1 && IS_TYPEDEF($1->etype)) {
1232          allocVariables ($1);
1233          $$ = NULL ;
1234        }
1235        else
1236          $$ = $1 ;
1237      }
1238
1239    | declaration_list declaration
1240      {
1241        symbol   *sym;
1242        
1243        /* if this is a typedef */
1244        if ($2 && IS_TYPEDEF($2->etype)) {
1245          allocVariables ($2);
1246          $$ = $1 ;
1247        }
1248        else {
1249                                 /* get to the end of the previous decl */
1250          if ( $1 ) {
1251            $$ = sym = $1 ;
1252            while (sym->next)
1253              sym = sym->next ;
1254            sym->next = $2;
1255          } 
1256          else
1257            $$ = $2 ;
1258        }
1259      }
1260    ;
1261
1262 statement_list
1263    : statement
1264    | statement_list statement          {  $$ = newNode(NULLOP,$1,$2) ;}
1265    ;
1266
1267 expression_statement
1268    : ';'                { $$ = NULL;}
1269    | expr ';' 
1270    ;
1271
1272 else_statement
1273    :  ELSE  statement   { $$ = $2  ; }
1274    |                    { $$ = NULL;}
1275    ;
1276
1277   
1278 selection_statement
1279    : IF '(' expr ')'  statement else_statement { noLineno++ ; $$ = createIf ($3, $5, $6 ); noLineno--;}
1280    | SWITCH '(' expr ')'   { 
1281                               ast *ex ;                              
1282                               static   int swLabel = 0 ;
1283
1284                               /* create a node for expression  */
1285                               ex = newNode(SWITCH,$3,NULL);
1286                               STACK_PUSH(swStk,ex);   /* save it in the stack */
1287                               ex->values.switchVals.swNum = swLabel ;
1288                                  
1289                               /* now create the label */
1290                               SNPRINTF(lbuff, sizeof(lbuff), 
1291                                        "_swBrk_%d",swLabel++);
1292                               $<sym>$  =  newSymbol(lbuff,NestLevel);
1293                               /* put label in the break stack  */
1294                               STACK_PUSH(breakStack,$<sym>$);   
1295                            }
1296      statement             {  
1297                               /* get back the switch form the stack  */
1298                               $$ = STACK_POP(swStk)  ;
1299                               $$->right = newNode (NULLOP,$6,createLabel($<sym>5,NULL));
1300                               STACK_POP(breakStack);   
1301                            }
1302         ;
1303
1304 while : WHILE  {  /* create and push the continue , break & body labels */
1305                   static int Lblnum = 0 ;
1306                   /* continue */
1307                   SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum);
1308                   STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1309                   /* break */
1310                   SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum);
1311                   STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1312                   /* body */
1313                   SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++);
1314                   $$ = newSymbol(lbuff,NestLevel);
1315                }
1316    ;
1317
1318 do : DO {  /* create and push the continue , break & body Labels */
1319            static int Lblnum = 0 ;
1320
1321            /* continue */
1322            SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum);
1323            STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1324            /* break */
1325            SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum);
1326            STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1327            /* do body */
1328            SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++);
1329            $$ = newSymbol (lbuff,NestLevel);       
1330         }
1331    ;
1332
1333 for : FOR { /* create & push continue, break & body labels */
1334             static int Lblnum = 0 ;
1335          
1336             /* continue */
1337             SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum);
1338             STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1339             /* break    */
1340             SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum);
1341             STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1342             /* body */
1343             SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum);
1344             $$ = newSymbol(lbuff,NestLevel);
1345             /* condition */
1346             SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++);
1347             STACK_PUSH(forStack,newSymbol(lbuff,NestLevel));
1348           }
1349    ;
1350
1351 iteration_statement  
1352    : while '(' expr ')'  statement 
1353                          { 
1354                            noLineno++ ;
1355                            $$ = createWhile ( $1, STACK_POP(continueStack),
1356                                               STACK_POP(breakStack), $3, $5 ); 
1357                            $$->lineno = $1->lineDef ;
1358                            noLineno-- ;
1359                          }
1360    | do statement   WHILE '(' expr ')' ';' 
1361                         { 
1362                           noLineno++ ; 
1363                           $$ = createDo ( $1 , STACK_POP(continueStack), 
1364                                           STACK_POP(breakStack), $5, $2);
1365                           $$->lineno = $1->lineDef ;
1366                           noLineno-- ;
1367                         }                                                 
1368    | for '(' expr_opt   ';' expr_opt ';' expr_opt ')'  statement   
1369                         {
1370                           noLineno++ ;  
1371                           
1372                           /* if break or continue statement present
1373                              then create a general case loop */
1374                           if (STACK_PEEK(continueStack)->isref ||
1375                               STACK_PEEK(breakStack)->isref) {
1376                               $$ = createFor ($1, STACK_POP(continueStack),
1377                                               STACK_POP(breakStack) ,
1378                                               STACK_POP(forStack)   ,
1379                                               $3 , $5 , $7, $9 );
1380                           } else {
1381                               $$ = newNode(FOR,$9,NULL);
1382                               AST_FOR($$,trueLabel) = $1;
1383                               AST_FOR($$,continueLabel) =  STACK_POP(continueStack);
1384                               AST_FOR($$,falseLabel) = STACK_POP(breakStack);
1385                               AST_FOR($$,condLabel)  = STACK_POP(forStack)  ;
1386                               AST_FOR($$,initExpr)   = $3;
1387                               AST_FOR($$,condExpr)   = $5;
1388                               AST_FOR($$,loopExpr)   = $7;
1389                           }
1390                           
1391                           noLineno-- ;
1392                         }
1393 ;
1394
1395 expr_opt
1396         :                       { $$ = NULL ; }
1397         |       expr
1398         ;
1399
1400 jump_statement          
1401    : GOTO identifier ';'   { 
1402                               $2->islbl = 1;
1403                               $$ = newAst_VALUE(symbolVal($2)); 
1404                               $$ = newNode(GOTO,$$,NULL);
1405                            }
1406    | CONTINUE ';'          {  
1407        /* make sure continue is in context */
1408        if (STACK_PEEK(continueStack) == NULL) {
1409            werror(E_BREAK_CONTEXT);
1410            $$ = NULL;
1411        }
1412        else {
1413            $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack)));      
1414            $$ = newNode(GOTO,$$,NULL);
1415            /* mark the continue label as referenced */
1416            STACK_PEEK(continueStack)->isref = 1;
1417        }
1418    }
1419    | BREAK ';'             { 
1420        if (STACK_PEEK(breakStack) == NULL) {
1421            werror(E_BREAK_CONTEXT);
1422            $$ = NULL;
1423        } else {
1424            $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack)));
1425            $$ = newNode(GOTO,$$,NULL);
1426            STACK_PEEK(breakStack)->isref = 1;
1427        }
1428    }
1429    | RETURN ';'            { $$ = newNode(RETURN,NULL,NULL)    ; }
1430    | RETURN expr ';'       { $$ = newNode(RETURN,NULL,$2) ; } 
1431    ;
1432
1433 identifier
1434    : IDENTIFIER   { $$ = newSymbol ($1,NestLevel) ; }
1435    ;
1436 %%
1437