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