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