Rune - Change regsave burden for syscalls
[rune.git] / librune / parse1.c
1 /*
2  * PARSE1.C
3  *
4  * (c)Copyright 1993-2014, Matthew Dillon, All Rights Reserved.  See the  
5  *    COPYRIGHT file at the base of the distribution.
6  */
7
8 #include "defs.h"
9
10 static int ParseImportStmt(Parse *p, int t, Scope *scope);
11 static int ParseClassStmt(Parse *p, int t, Scope *scope);
12 static int ParseSubClassStmt(Parse *p, int t, Scope *scope);
13 static int ParseProjectStmt(Parse *p, int t, Scope *scope);
14 static int ParseBlockStmt(Parse *p, int t, Stmt **pst);
15 static int ParseProcStmt(Parse *p, int t, Declaration *d, Stmt **pst);
16 static int ParseForStmt(Parse *p, int t, Stmt **pst);
17 static int ParseWhileStmt(Parse *p, int t, Stmt **pst);
18 static int ParseUntilStmt(Parse *p, int t, Stmt **pst);
19 static int ParseDoStmt(Parse *p, int t, Stmt **pst);
20 static int ParseBreakContStmt(Parse *p, int t, Stmt **pst);
21 static int ParseSwitchStmt(Parse *p, int t, Stmt **pst);
22 static int ParseIfElseStmt(Parse *p, int t, Stmt **pst);
23 static int ParseReturnStmt(Parse *p, int t, Stmt **pst);
24 static int ParseResultStmt(Parse *p, int t, Stmt **pst);
25 static int ParseNopStmt(Parse *p, int t, Stmt **pst);
26 static int ParseExpStmt(Parse *p, int t, Stmt **pst);
27 static int ParseThreadSchedStmt(Parse *p, int t, Stmt **pst);
28
29 static int distinguishBlockLabel(Parse *p, int t);
30 static int distinguishDeclaration(Parse *p, int t);
31
32 /*
33  * Merge default scope for semantic layer with per-declaration scope.
34  */
35 static __inline
36 void
37 mergeScope(Scope *src, Scope *dst)
38 {
39         dst->s_Flags |= src->s_Flags;
40         if (dst->s_AlignOverride == 0)
41                 dst->s_AlignOverride = src->s_AlignOverride;
42 }
43
44 /*
45  * ParseModule() - parse the body of an imported entity.
46  *
47  *      This function is called from the top level utility to bring in
48  *      initial source module, and is called by ParseImport() to import
49  *      a new module.  We create a placeholder statement to represent
50  *      the entire module.  Also note that the semantic group will be
51  *      associated with the new Parse zone, but is still linked to the
52  *      parent.
53  *
54  *      Note that all declarations made at the import level are automatically
55  *      given GLOBAL scope.
56  */
57 int
58 ParseModule(Parse *p, Stmt *stpar, int t)
59 {
60         Stmt *st;
61         Declaration *d;
62         Scope save_scope = { 0, 0 };
63
64         dassert_stmt(stpar, stpar->st_Op == ST_Import);
65
66         st = PushStmt(p, NULL, ST_Module,
67                       STF_SEMANTIC | STF_SEMTOP | STF_FORWARD);
68         dassert(stpar->st_Op == ST_Import);
69
70         /*
71          * Glue to the parent that imported us.  Note that ed_SemGroup will be
72          * NULL for shared-library (.so) imports, since this code is never
73          * reached in that case.
74          */
75         stpar->st_ImportStmt.es_SemGroup = st->st_MyGroup;
76         if ((d = stpar->st_ImportStmt.es_Decl) != NULL)
77                 d->d_ImportDecl.ed_SemGroup = st->st_MyGroup;
78
79
80         if (st->st_LexRef.lr_Lex == NULL)
81                 LexInitRef(&st->st_LexRef, &p->p_Token);
82
83         while ((t & TOKF_ERREOF) == 0) {
84                 Scope scope;
85
86                 t = ParseScopeQual(p, t, &scope);
87
88                 switch(t) {
89                 case TOK_COLON:
90                         save_scope = scope;
91                         t = LexToken(&p->p_Token);
92                         break;
93                 case TOK_IMPORT:
94                         scope.s_Flags |= SCOPE_GLOBAL;
95                         mergeScope(&save_scope, &scope);
96                         t = ParseImportStmt(p, t, &scope);
97                         break;
98                 case TOK_INTERFACE:
99                         scope.s_Flags |= SCOPE_GLOBAL;
100                         scope.s_Flags |= SCOPE_INTERFACE;
101                         /* fall through */
102                 case TOK_CLASS:
103                         scope.s_Flags |= SCOPE_GLOBAL;
104                         mergeScope(&save_scope, &scope);
105                         t = ParseClassStmt(p, t, &scope);
106                         break;
107                 case TOK_SUBINTERFACE:
108                         scope.s_Flags |= SCOPE_GLOBAL;
109                         scope.s_Flags |= SCOPE_INTERFACE;
110                         /* fall through */
111                 case TOK_SUBCLASS:
112                         scope.s_Flags |= SCOPE_GLOBAL;
113                         mergeScope(&save_scope, &scope);
114                         t = ParseSubClassStmt(p, t, &scope);
115                         break;
116                 case TOK_PROJECT:
117                         mergeScope(&save_scope, &scope);
118                         t = ParseProjectStmt(p, t, &scope);
119                         break;
120                 case TOK_TYPEDEF:
121                         scope.s_Flags |= SCOPE_GLOBAL;
122                         mergeScope(&save_scope, &scope);
123                         t = ParseTypedefStmt(p, t, &scope);
124                         break;
125                 case TOK_ALIAS:
126                 default:
127                         /*
128                          * NOTE: dop is overridden by TOK_ALIAS and other
129                          *       scope flags such as SCOPE_GLOBAL.
130                          *
131                          * NOTE: We do not set SCOPE_GLOBAL here, because
132                          *       the declaration might be contextually in
133                          *       a class (e.g. Fd.setfd).  It will be handled
134                          *       deeper.
135                          */
136                         mergeScope(&save_scope, &scope);
137                         t = ParseDeclarationStmt(p, t, 2, NULL,
138                                                  DOP_GROUP_STORAGE, &scope);
139                         break;
140                 }
141         }
142         if ((t & TOKF_ERROR) == 0)
143                 p->p_Format = PFMT_PARSED;
144         PopStmt(p, st);
145
146         return(t);
147 }
148
149 int
150 ParseStmt(Parse *p, int t, Stmt **pst)
151 {
152         switch(t) {
153         case TOK_OBRACE:
154                 t = ParseBlockStmt(p, t, pst);
155                 break;
156         case TOK_FOR:
157                 t = ParseForStmt(p, t, pst);
158                 break;
159         case TOK_WHILE:
160                 t = ParseWhileStmt(p, t, pst);
161                 break;
162         case TOK_UNTIL:
163                 t = ParseUntilStmt(p, t, pst);
164                 break;
165         case TOK_DO:
166                 t = ParseDoStmt(p, t, pst);
167                 break;
168         case TOK_BREAK:
169         case TOK_CONTINUE:
170                 t = ParseBreakContStmt(p, t, pst);
171                 break;
172         case TOK_SWITCH:
173                 t = ParseSwitchStmt(p, t, pst);
174                 break;
175         case TOK_THREAD_SCHEDULE:
176                 t = ParseThreadSchedStmt(p, t, pst);
177                 break;
178         case TOK_IF:
179                 t = ParseIfElseStmt(p, t, pst);
180                 break;
181         case TOK_ELSE:
182                 t = LexError(&p->p_Token, TOK_ERR_ELSE_WITHOUT_IF);
183                 if (pst)
184                         *pst = NULL;
185                 break;
186         case TOK_RETURN:
187                 t = ParseReturnStmt(p, t, pst);
188                 break;
189         case TOK_RESULT:
190                 t = ParseResultStmt(p, t, pst);
191                 break;
192         case TOK_CASE:
193                 t = LexError(&p->p_Token, TOK_ERR_CASE_WITHOUT_SWITCH);
194                 if (pst)
195                         *pst = NULL;
196                 break;
197         case TOK_SEMI:
198                 t = ParseNopStmt(p, t, pst);
199                 break;
200         case TOK_DEFAULT:
201                 t = LexError(&p->p_Token, TOK_ERR_DEFAULT_WITHOUT_SWITCH);
202                 if (pst)
203                         *pst = NULL;
204                 break;
205         default:
206                 /*
207                  * Parse a declaration or an expression.  Declarations are 
208                  * distinguished from expressions by beginning with a scope
209                  * qualifier, "alias", or a class identifier.
210                  */
211                 if (t == TOK_ID && distinguishBlockLabel(p, t)) {
212                         t = ParseBlockStmt(p, t, pst);
213                 } else if ((t & (TOKF_STOR_QUAL|TOKF_SCOPE_QUAL)) ||
214                            t == TOK_ALIAS ||
215                            distinguishDeclaration(p, t)
216                 ) {
217                         Scope scope;
218
219                         /*
220                          * NOTE: TOK_ALIAS will override the passed-in dop
221                          *       to DOP_ALIAS.
222                          */
223                         t = ParseScopeQual(p, t, &scope);
224                         t = ParseDeclarationStmt(p, t, 1, pst,
225                                                  DOP_STACK_STORAGE, &scope);
226                 } else {
227                         t = ParseExpStmt(p, t, pst);
228                 }
229         }
230         return(t);
231 }
232
233 /*
234  * Return non-zero if the identifier is part of a block label
235  */
236 static int
237 distinguishBlockLabel(Parse *p, int t __unused)
238 {
239         token_t tok = p->p_Token;
240
241         if (LexToken(&tok) == TOK_OBRACE)
242                 return 1;
243         else
244                 return 0;
245 }
246
247 /*
248  * Return non-zero to parse as a declaration
249  */
250 static int
251 distinguishDeclaration(Parse *p, int t)
252 {
253         token_t tok = p->p_Token;
254
255         /*
256          * Possible compound declaration.
257          */
258         if (t == TOK_OPAREN) {
259                 int count = 1;
260                 while (count && ((t = LexToken(&tok)) & TOKF_ERROR) == 0) {
261                         /* check comma to detect compound type */
262                         if (t == TOK_COMMA && count == 1)
263                                 return(1);
264                         if (t == TOK_OPAREN)
265                                 ++count;
266                         if (t == TOK_CPAREN)
267                                 --count;
268                 }
269                 if (count == 0)
270                         t = LexToken(&tok);
271         } else if ((t & TOKF_ID) == 0) {
272                 return(0);
273         } else {
274                 int nt;
275
276                 while ((nt = LexToken(&tok)) == TOK_DOT) {
277                         nt = LexToken(&tok);
278                         if ((nt & TOKF_ID) == 0)
279                                 return(0);
280                         t = nt;
281                 }
282         }
283
284         /*
285          * seq id
286          */
287         if (t == TOK_CLASSID)
288                 return(1);
289 #if 0
290         /*
291          * 'seq *' or 'seq @'
292          */
293         if (t == TOK_AT)
294                 return(1);
295         if (t == TOK_OPER && tok.t_Ptr[0] == '*')
296                 return(1);
297 #endif
298         return(0);
299 }
300
301 /*
302  * import "path" [ as id ];
303  *
304  */
305 static int
306 ParseImportStmt(Parse *p, int t, Scope *scope)
307 {
308         Stmt *st;
309         int limport;
310
311         /*
312          * NOTE: Lexer recognizes that the previous token was TOK_IMPORT
313          *       and will parse angle-brackets as if they were quotes.
314          */
315         t = LexSkipToken(&p->p_Token, TOK_IMPORT);
316         limport = 0;
317
318         if (t == TOK_ID) {
319                 if (StrCmpToken(String_SelfContained, &p->p_Token) == 0) {
320                         st = p->p_CurStmt;
321                         while (st->st_Op != ST_Module)
322                                 st = st->st_Parent;
323                         if ((st->st_Flags & STF_SELFCONTAINED) == 0) {
324                                 st->st_Flags |= STF_SELFCONTAINED;
325                                 st->st_MyGroup->sg_Flags |= SGF_SELFCONTAINED;
326                                 st = st->st_Parent;
327                                 dassert(st->st_Op == ST_Import);
328                                 SetSharedImport(&p->p_St,
329                                                 st->st_ImportStmt.es_SemGroup);
330                         }
331                         t = LexToken(&p->p_Token);
332                         t = LexSkipToken(&p->p_Token, TOK_SEMI);
333                 } else {
334                         t = LexError(&p->p_Token, TOK_ERR_SYNTAX);
335                 }
336                 return(t);
337         }
338 #if 0
339         st = PushStmt(p, NULL, ST_Import, STF_SEMANTIC|STF_SEMTOP|STF_FORWARD);
340 #endif
341         st = PushStmt(p, NULL, ST_Import, 0);
342
343         if (t == TOK_DSTRING)
344                 limport = 1;
345
346         if (t == TOK_DSTRING || t == TOK_ANGLESTR) {
347                 token_t tmp;
348                 string_t path;
349                 const char *ptr;
350
351                 LexStripQuotes(&p->p_Token, &tmp);
352                 path = StrTableToken(&tmp);
353                 if ((ptr = strrchr(path, '/')) != NULL) {
354                         ++ptr;
355                         safe_asprintf(
356                                 &st->st_ImportStmt.es_Path, 
357                                 "%*.*s",
358                                 ptr - path,
359                                 ptr - path,
360                                 path
361                         );
362                         st->st_ImportStmt.es_File = safe_strdup(ptr);
363                         dassert_parse(p, TOK_ERR_EMPTY_PATH, *ptr != 0);
364                 } else {
365                         st->st_ImportStmt.es_Path = safe_strdup("");
366                         st->st_ImportStmt.es_File = safe_strdup(path);
367                 }
368                 RelStrTable(&path);
369                 t = LexToken(&p->p_Token);
370
371                 if (limport) {
372                         st->st_ImportStmt.es_AsId = String_Self;
373                 } else if (t == TOK_AS) {
374                         t = LexToken(&p->p_Token);
375                         if (t & TOKF_ID) {
376                                 st->st_ImportStmt.es_AsId =
377                                         StrTableToken(&p->p_Token);
378                                 t = LexToken(&p->p_Token);
379                         } else {
380                                 t = LexError(&p->p_Token, TOK_ERR_EXPECTED_ID);
381                         }
382                 } else {
383                         int len;
384                         const char *str;
385
386                         str = StripPathId(st->st_ImportStmt.es_File, &len);
387                         st->st_ImportStmt.es_AsId = StrTableAlloc(str, len, 0);
388                 }
389         } else {
390                 t = LexError(&p->p_Token, TOK_ERR_EXPECTED_STRING);
391         }
392
393         /*
394          * Parse the imported entity (XXX unless shared and already parsed)
395          *
396          * NOTE! ParseOpen() is responsible for allocating st_MyGroup
397          */
398         if ((t & TOKF_ERROR) == 0) {
399                 int t2;
400
401                 t2 = ParseOpen(st,
402                                &st->st_ImportStmt.es_Parser,
403                                &st->st_ImportStmt.es_DLL);
404                 if (t2 & TOKF_ERROR) {
405                         t = LexError(&p->p_Token, t2);
406                 } else if (t2 == 0 && (st->st_Flags & STF_SHARED)) {
407                         /*
408                          * Assign d_Stmt so a DLL import can find the DLL
409                          * (which is stored in the ImportStmt).  Note that
410                          * ed_SemGroup may be NULL if the import represents
411                          * a DLL.
412                          *
413                          * XXX st_MyGroup was overriden, free original? 
414                          */
415                         st->st_ImportStmt.es_Decl = AllocImportDecl(st, scope);
416                         st->st_ImportStmt.es_Decl->d_ImportDecl.ed_SemGroup =
417                                 st->st_ImportStmt.es_SemGroup;
418                         st->st_ImportStmt.es_Decl->d_Stmt = st;
419                 } else {
420                         st->st_ImportStmt.es_Decl = AllocImportDecl(st, scope);
421                         st->st_ImportStmt.es_Decl->d_Stmt = st;
422                         t2 = ParseModule(st->st_ImportStmt.es_Parser, st, t2);
423                         if (t2 & TOKF_ERROR) {
424                                 LexPrintError(
425                                         &st->st_ImportStmt.es_Parser->p_Token);
426                                 t = LexError(&p->p_Token,
427                                              TOK_ERR_IMPORT_FAILED);
428                         }
429                 }
430                 ParseDone(st->st_ImportStmt.es_Parser);
431         }
432
433         /*
434          * Cleanup
435          */
436         t = LexSkipToken(&p->p_Token, TOK_SEMI);
437         PopStmt(p, st);
438         return(t);
439 }
440
441 /*
442  * ParseClassStmt() - parse a class or interface.
443  *
444  * class id { ... }
445  * interface id { ... }
446  */
447 static int
448 ParseClassStmt(Parse *p, int t, Scope *scope)
449 {
450         Stmt *st = PushStmt(p, NULL, ST_Class,
451                             STF_SEMANTIC | STF_SEMTOP | STF_FORWARD);
452
453         /*
454          * Get the dotted id path.  Extract the last identifier into id
455          * (it will not be counted by count or appear in the returned array).
456          */
457         t = LexSkipToken(&p->p_Token, t);       /* class or interface */
458         if (t != TOK_CLASSID) {
459                 /*if ((t & TOKF_ID) == 0)*/
460                 t = LexError(&p->p_Token, TOK_ERR_EXPECTED_CLASSID);
461         } else {
462                 string_t id;
463                 Scope save_scope = { 0, 0 };
464
465                 id = StrTableToken(&p->p_Token);        /* retrieve the id */
466                 t = LexToken(&p->p_Token);
467
468                 st->st_ClassStmt.es_Decl = AllocClassDecl(st, id, NULL, scope);
469                 st->st_ClassStmt.es_Super = NULL;
470
471                 t = LexSkipToken(&p->p_Token, TOK_OBRACE);
472                 while ((t & TOKF_ERROR) == 0 && t != TOK_CBRACE) {
473                         Scope scope2;
474
475                         t = ParseScopeQual(p, t, &scope2);
476                         switch(t) {
477                         case TOK_COLON:
478                                 save_scope = scope2;
479                                 t = LexToken(&p->p_Token);
480                                 break;
481                         case TOK_TYPEDEF:
482                                 mergeScope(&save_scope, &scope2);
483                                 t = ParseTypedefStmt(p, t, &scope2);
484                                 break;
485                         case TOK_ALIAS:
486                         default:
487                                 /*
488                                  * NOTE: dop is overridden by TOK_ALIAS and
489                                  *       other scope flags such as
490                                  *       SCOPE_GLOBAL.
491                                  */
492                                 mergeScope(&save_scope, &scope2);
493                                 t = ParseDeclarationStmt(p, t, 1, NULL,
494                                                          DOP_GROUP_STORAGE,
495                                                          &scope2);
496                                 break;
497                         }
498                 }
499                 t = LexSkipToken(&p->p_Token, TOK_CBRACE);
500
501                 if (scope->s_Flags & SCOPE_INTERNAL)
502                         t = InternalClassAttach(p, t, st->st_ClassStmt.es_Decl);
503         }
504         PopStmt(p, st);
505
506         return(t);
507 }
508
509 /*
510  * ParseSubClassStmt() - parse a subclass or subinterface 
511  *
512  * subclass id from id[.id]* { ... }
513  * subinterface id from id[.id]* { ... }
514  */
515 static int
516 ParseSubClassStmt(Parse *p, int t, Scope *scope)
517 {
518         Stmt *st = PushStmt(p, NULL, ST_Class,
519                             STF_SEMANTIC | STF_SEMTOP | STF_FORWARD);
520         string_t id = NULL;
521         string_t *ary;
522         int count;
523         int lt;
524
525         t = LexSkipToken(&p->p_Token, t); /* subclass or subinterface */
526
527         /*
528          * The subclass identifier.  Name of the new subclass
529          */
530         if (t & TOKF_ID) {
531                 id = StrTableToken(&p->p_Token); /* retrieve the id */
532                 t = LexToken(&p->p_Token);
533         } else {
534                 t = LexError(&p->p_Token, TOK_ERR_EXPECTED_ID);
535         }
536
537         /*
538          * Get the dotted id path.  Extract the last identifier into id
539          * (it will not be counted by count or appear in the returned array).
540          *
541          * XXX free ary on error
542          */
543         if ((t & TOKF_ERROR) == 0)
544                 t = LexSkipToken(&p->p_Token, TOK_FROM);
545         if ((t & TOKF_ERROR) == 0) {
546                 t = ParseDotIdAry(p, t, &ary, &count, &lt);
547                 if (lt != TOK_CLASSID)
548                         t = LexError(&p->p_Token, TOK_ERR_EXPECTED_CLASSID);
549         } else {
550                 ary = NULL;
551                 count = 0;
552         }
553
554         /*
555          * Figure out the superclass, if any.
556          */
557         if ((t & TOKF_ERROR) == 0) {
558                 SemGroup *isg;
559                 Type *super;
560                 Scope save_scope = { 0, 0 };
561
562                 isg = p->p_Import->st_ImportStmt.es_SemGroup;
563                 super = AllocUnresolvedType(isg, p->p_CurSemGroup, ary, 1);
564
565                 st->st_ClassStmt.es_Decl = AllocClassDecl(st, id, super, scope);
566                 st->st_ClassStmt.es_Super = super; 
567
568                 t = LexSkipToken(&p->p_Token, TOK_OBRACE);
569                 while ((t & TOKF_ERROR) == 0 && t != TOK_CBRACE) {
570                         Scope scope2;
571
572                         t = ParseScopeQual(p, t, &scope2);
573                         switch(t) {
574                         case TOK_COLON:
575                                 save_scope = scope2;
576                                 t = LexToken(&p->p_Token);
577                                 break;
578                         case TOK_TYPEDEF:
579                                 mergeScope(&save_scope, &scope2);
580                                 t = ParseTypedefStmt(p, t, &scope2);
581                                 break;
582                         case TOK_ALIAS:
583                         default:
584                                 /*
585                                  * NOTE: dop is overridden by TOK_ALIAS and
586                                  *       other scope flags such as
587                                  *       SCOPE_GLOBAL.
588                                  */
589                                 mergeScope(&save_scope, &scope2);
590                                 t = ParseDeclarationStmt(p, t, 1, NULL,
591                                                          DOP_GROUP_STORAGE,
592                                                          &scope2);
593                                 break;
594                         }
595                 }
596                 t = LexSkipToken(&p->p_Token, TOK_CBRACE);
597
598                 if (scope->s_Flags & SCOPE_INTERNAL)
599                         t = InternalClassAttach(p, t, st->st_ClassStmt.es_Decl);
600         }
601         PopStmt(p, st);
602         return(t);
603 }
604
605 /*
606  * ParseProjectStmt() - Set project name for shared persistent variables
607  */
608 int
609 ParseProjectStmt(Parse *p, int t, Scope *scope __unused)
610 {
611         SemGroup *sg;
612
613         sg = p->p_CurSemGroup;
614
615         t = LexSkipToken(&p->p_Token, TOK_PROJECT);
616         if (t == TOK_DSTRING) {
617                 token_t tmp;
618
619                 RelStrTable(&sg->sg_Project);
620                 LexStripQuotes(&p->p_Token, &tmp);
621                 sg->sg_Project = StrTableToken(&tmp);
622                 t = LexToken(&p->p_Token);
623         } else {
624                 t = LexError(&p->p_Token, TOK_ERR_EXPECTED_STRING);
625         }
626         t = LexSkipToken(&p->p_Token, TOK_SEMI);
627         return t;
628 }
629
630 /*
631  * ParseTypedefStmt() - parse a typedef
632  *
633  *      Note that we have to give the typedef global scope so use of the
634  *      typedef can occur out of the current context.  XXX
635  */
636 int
637 ParseTypedefStmt(Parse *p, int t, Scope *scope)
638 {
639         Stmt *st = PushStmt(p, NULL, ST_Typedef, 0);
640         Declaration *d;
641         Scope tscope = *scope;
642
643         t = LexSkipToken(&p->p_Token, TOK_TYPEDEF);
644
645         tscope.s_Flags |= SCOPE_GLOBAL;
646
647         t = ParseDeclaration(p, t, &d, 2, DOP_TYPEDEF, &tscope);
648         if ((t & TOKF_ERROR) == 0) {
649                 Type *type = d->d_StorDecl.ed_Type;
650                 Exp *exp = d->d_StorDecl.ed_AssExp;
651
652                 d->d_Op = DOP_TYPEDEF;
653                 d->d_TypedefDecl.ed_Type = TypeToQualType(type,
654                                                           NULL,
655                                                           type->ty_SQFlags,
656                                                           exp);
657                 if (tscope.s_Flags & SCOPE_INTERNAL)
658                         InternalTypeAttach(p, t, d);
659                 st->st_TypedefStmt.es_Decl = d; /* short cut */
660         }
661         t = LexSkipToken(&p->p_Token, TOK_SEMI);
662         PopStmt(p, st);
663         return(t);
664 }
665
666 static int
667 ParseBlockStmt(Parse *p, int t, Stmt **pst)
668 {
669         Stmt *st = PushStmt(p, pst, ST_Block, STF_SEMANTIC);
670
671         if (t == TOK_ID) {
672                 st->st_BlockStmt.es_BlockId = StrTableToken(&p->p_Token);
673                 t = LexSkipToken(&p->p_Token, TOK_ID);
674         }
675         t = LexSkipToken(&p->p_Token, TOK_OBRACE);
676         while ((t & TOKF_ERROR) == 0 && t != TOK_CBRACE) {
677                 t = ParseStmt(p, t, NULL);
678         }
679         t = LexSkipToken(&p->p_Token, TOK_CBRACE);
680         PopStmt(p, st);
681         return(t);
682 }
683
684 /*
685  * ParseProcStmt() - process a procedure body
686  *
687  *      Due to dotted id handling, the current SemGroup may not be
688  *      the SemGroup the declaration was placed in.  We have to temporarily
689  *      switch to the other semgroup in order to process the procedure
690  *      body.
691  *
692  *      If this is a nested procedure we have to mark it as such.
693  *      Note that STF_SEMTOP is used for storage management and is
694  *      still set for a nested procedure (it's local storage is 
695  *      independant of its parent).
696  */
697 static int
698 ParseProcStmt(Parse *p, int t, Declaration *d, Stmt **pst)
699 {
700         Stmt *st;
701         SemGroup *save;
702         SemGroup *scan;
703         int flags = STF_SEMANTIC|STF_SEMTOP;
704
705         save = p->p_CurSemGroup;
706         p->p_CurSemGroup = d->d_MyGroup;
707
708         for (scan = d->d_MyGroup; scan; scan = scan->sg_Parent) {
709                 if ((st = scan->sg_Stmt) != NULL && (st->st_Flags & STF_SEMTOP)) {
710                         if (st->st_Op == ST_Proc)
711                                 flags |= STF_NESTED;
712                         break;
713                 }
714         }
715
716         st = PushStmt(p, pst, ST_Proc, flags);
717         st->st_DeclStmt.es_Decl = d;
718         st->st_DeclStmt.es_DeclCount = 1;
719         st->st_DeclStmt.es_Scope = d->d_Scope;
720         AdjustProcArgsNestingLevel(d, st->st_MyGroup);
721
722         t = LexSkipToken(&p->p_Token, TOK_OBRACE);
723         while ((t & TOKF_ERROR) == 0 && t != TOK_CBRACE) {
724                 t = ParseStmt(p, t, NULL);
725         }
726         t = LexSkipToken(&p->p_Token, TOK_CBRACE);
727         PopStmt(p, st);
728         p->p_CurSemGroup = save;
729
730         return(t);
731 }
732
733 static int
734 ParseForStmt(Parse *p, int t, Stmt **pst)
735 {
736         Stmt *st = PushStmt(p, pst, ST_Loop, STF_SEMANTIC);
737
738         t = LexSkipToken(&p->p_Token, TOK_FOR);
739         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
740
741         /* note: semicolon implied by statement parser */
742         t = ParseStmt(p, t, &st->st_LoopStmt.es_Init);
743         if (t != TOK_SEMI)
744                 t = ParseExp(p, t, &st->st_LoopStmt.es_BCond);
745         t = LexSkipToken(&p->p_Token, TOK_SEMI);
746         if (t != TOK_CPAREN)
747                 t = ParseExp(p, t, &st->st_LoopStmt.es_AExp);
748         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
749         t = ParseStmt(p, t, &st->st_LoopStmt.es_Body);
750         PopStmt(p, st);
751         return(t);
752 }
753
754 static int
755 ParseWhileStmt(Parse *p, int t, Stmt **pst)
756 {
757         Stmt *st = PushStmt(p, pst, ST_Loop, STF_SEMANTIC);
758
759         t = LexSkipToken(&p->p_Token, TOK_WHILE);
760         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
761         t = ParseExp(p, t, &st->st_LoopStmt.es_BCond);
762         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
763         t = ParseStmt(p, t, &st->st_LoopStmt.es_Body);
764         PopStmt(p, st);
765         return(t);
766 }
767
768 static int
769 ParseUntilStmt(Parse *p, int t, Stmt **pst)
770 {
771         Stmt *st = PushStmt(p, pst, ST_Loop, STF_SEMANTIC);
772
773         t = LexSkipToken(&p->p_Token, TOK_WHILE);
774         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
775         t = ParseNotExp(p, t, &st->st_LoopStmt.es_BCond);
776         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
777         t = ParseStmt(p, t, &st->st_LoopStmt.es_Body);
778         PopStmt(p, st);
779         return(t);
780 }
781
782 static int
783 ParseDoStmt(Parse *p, int t, Stmt **pst)
784 {
785         Stmt *st = PushStmt(p, pst, ST_Loop, STF_SEMANTIC);
786
787         t = LexSkipToken(&p->p_Token, TOK_DO);
788         t = ParseStmt(p, t, &st->st_LoopStmt.es_Body);
789
790         switch(t) {
791         case TOK_WHILE:
792                 t = LexToken(&p->p_Token);
793                 t = LexSkipToken(&p->p_Token, TOK_OPAREN);
794                 t = ParseExp(p, t, &st->st_LoopStmt.es_ACond);
795                 t = LexSkipToken(&p->p_Token, TOK_CPAREN);
796                 t = LexSkipToken(&p->p_Token, TOK_SEMI);
797                 break;
798         case TOK_UNTIL:
799                 t = LexToken(&p->p_Token);
800                 t = LexSkipToken(&p->p_Token, TOK_OPAREN);
801                 t = ParseNotExp(p, t, &st->st_LoopStmt.es_ACond);
802                 t = LexSkipToken(&p->p_Token, TOK_CPAREN);
803                 t = LexSkipToken(&p->p_Token, TOK_SEMI);
804                 break;
805         default:
806                 t = LexError(&p->p_Token, TOK_ERR_DO_WITHOUT_WHILE);
807                 break;
808         }
809         PopStmt(p, st);
810         return(t);
811 }
812
813 /*
814  * break [ for | while | do | switch | if | block | <empty> ] ;
815  * continue [ for | while | do | switch | if | block | <empty> ] ;
816  */
817 static int
818 ParseBreakContStmt(Parse *p, int t, Stmt **pst)
819 {
820         Stmt *st = PushStmt(p, pst, ST_BreakCont, 0);
821         Stmt *scan;
822         string_t id;
823
824         switch(t) {
825         case TOK_CONTINUE:
826                 st->st_BreakStmt.es_IsCont = 1;
827                 /* fall through */
828         case TOK_BREAK:
829                 t = LexToken(&p->p_Token);
830                 switch(t) {
831                 case TOK_CASE:
832                         st->st_BreakStmt.es_StmtType = ST_Case;
833                         t = LexToken(&p->p_Token);
834                         break;
835                 case TOK_LOOP:
836                         st->st_BreakStmt.es_StmtType = ST_Loop;
837                         t = LexToken(&p->p_Token);
838                         break;
839                 case TOK_SWITCH:
840                         st->st_BreakStmt.es_StmtType = ST_Switch;
841                         t = LexToken(&p->p_Token);
842                         break;
843                 case TOK_IF:
844                         st->st_BreakStmt.es_StmtType = ST_IfElse;
845                         t = LexToken(&p->p_Token);
846                         break;
847                 case TOK_ELSE:
848                         st->st_BreakStmt.es_StmtType = ST_Else;
849                         t = LexToken(&p->p_Token);
850                         break;
851                 case TOK_BLOCK:
852                         st->st_BreakStmt.es_StmtType = ST_Block;
853                         st->st_BreakStmt.es_BlockId = NULL;
854                         t = LexToken(&p->p_Token);
855                         break;
856                 case TOK_ID:
857                         id = StrTableToken(&p->p_Token);
858                         if (id == String_Procedure) {
859                                 st->st_BreakStmt.es_StmtType = ST_Proc;
860                         } else {
861                                 st->st_BreakStmt.es_StmtType = ST_Block;
862                                 st->st_BreakStmt.es_BlockId = id;
863                         }
864                         t = LexToken(&p->p_Token);
865                         break;
866                 case TOK_SEMI:
867                         /* fall through to semicolon handler */
868                         break;
869                 default:
870                         /*
871                          * fall through.  If this isn't a ';' we will
872                          * fail below.
873                          */
874                         break;
875                 }
876
877                 /*
878                  * Calculate the correct break/continue count.
879                  */
880                 for (scan = st->st_Parent; 
881                      scan->st_Op != ST_Proc;
882                      scan = scan->st_Parent)
883                 {
884                         /*
885                          * Adjust for layer
886                          */
887                         if (st->st_BreakStmt.es_IsCont) {
888                                 --st->st_BreakStmt.es_Count;
889                         } else {
890                                 ++st->st_BreakStmt.es_Count;
891                         }
892
893                         /*
894                          * A standard break breaks out of the nearest loop
895                          * or case.  A standard continue continues the
896                          * nearest loop.
897                          */
898                         if (st->st_BreakStmt.es_StmtType == 0) {
899                                 if (st->st_BreakStmt.es_IsCont) {
900                                         if (scan->st_Op == ST_Loop)
901                                                 break;
902                                 } else {
903                                         if (scan->st_Op == ST_Switch ||
904                                             scan->st_Op == ST_Loop)
905                                                 break;
906                                 }
907                         }
908
909                         /*
910                          * if/else has two continue points.  The outer point
911                          * is for 'if', the inner point is for else.  Both
912                          * break points are the same.
913                          */
914                         if (scan->st_Op == ST_IfElse) {
915                                 /*
916                                  * break/continue outer
917                                  */
918                                 if (st->st_BreakStmt.es_StmtType == ST_IfElse) {
919                                         if (st->st_BreakStmt.es_IsCont)
920                                                 --st->st_BreakStmt.es_Count;
921                                         else
922                                                 ++st->st_BreakStmt.es_Count;
923                                         break;
924                                 }
925
926                                 /*
927                                  * break/continue inner
928                                  */
929                                 if (st->st_BreakStmt.es_StmtType == ST_Else)
930                                         break;
931
932                                 /*
933                                  * skip both and continue.
934                                  */
935                                 if (st->st_BreakStmt.es_IsCont) {
936                                         --st->st_BreakStmt.es_Count;
937                                 } else {
938                                         ++st->st_BreakStmt.es_Count;
939                                 }
940                         }
941
942                         /*
943                          * Stop if we locate the keyword.  If we are breaking
944                          * on ST_Block it might be a named block.
945                          */
946                         if (st->st_BreakStmt.es_StmtType == scan->st_Op) {
947                                 if (scan->st_Op != ST_Block)
948                                         break;
949                                 if (st->st_BreakStmt.es_BlockId == NULL)
950                                         break;
951                                 if (scan->st_BlockStmt.es_BlockId ==
952                                     st->st_BreakStmt.es_BlockId) {
953                                         break;
954                                 }
955                         }
956                 }
957
958                 /*
959                  * If we hit the main procedure body top the break/continue
960                  * point might not have been found, but we must still check
961                  * for BlockId.
962                  */
963                 dassert_stmt(st, scan != NULL);
964                 if (scan->st_Op == ST_Proc) {
965                         if (st->st_BreakStmt.es_StmtType == ST_Proc) {
966                                 if (st->st_BreakStmt.es_IsCont) {
967                                         --st->st_BreakStmt.es_Count;
968                                 } else {
969                                         ++st->st_BreakStmt.es_Count;
970                                 }
971                         } else {
972                                 t = LexError(&p->p_Token,
973                                              TOK_ERR_BREAK_CONT_NOT_FOUND);
974                         }
975                 }
976
977                 if (t == TOK_SEMI)
978                         t = LexToken(&p->p_Token);
979                 else
980                         t = LexError(&p->p_Token, TOK_ERR_BAD_BREAK_KEYWORD);
981                 break;
982         default:
983                 t = LexError(&p->p_Token, TOK_ERR_SYNTAX);
984                 break;
985         }
986         PopStmt(p, st);
987         return(t);
988 }
989
990 /*
991  * switch (exp) { cases/default ... }
992  */
993 static int
994 ParseSwitchStmt(Parse *p, int t, Stmt **pst)
995 {
996         Stmt *st = PushStmt(p, pst, ST_Switch, 0);
997
998         t = LexSkipToken(&p->p_Token, TOK_SWITCH);
999         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
1000         t = ParseExp(p, t, &st->st_SwStmt.es_Exp);
1001         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
1002         t = LexSkipToken(&p->p_Token, TOK_OBRACE);
1003         while (t == TOK_CASE || t == TOK_DEFAULT) {
1004                 Stmt *cst = PushStmt(p, NULL, ST_Case, STF_SEMANTIC);
1005                 if (t == TOK_CASE) {
1006                         t = LexToken(&p->p_Token);
1007                         t = ParseExp(p, t, &cst->st_CaseStmt.es_Exp);
1008                 } else {
1009                         if (st->st_SwStmt.es_Default == NULL)  {
1010                                 st->st_SwStmt.es_Default = cst;
1011                                 t = LexToken(&p->p_Token);
1012                         } else {
1013                                 t = LexError(&p->p_Token,
1014                                              TOK_ERR_MULTIPLE_DEFAULTS);
1015                         }
1016                 }
1017                 t = LexSkipToken(&p->p_Token, TOK_COLON);
1018                 while (t != TOK_CASE &&
1019                        t != TOK_DEFAULT &&
1020                        t != TOK_CBRACE &&
1021                        (t & TOKF_ERROR) == 0)
1022                 {
1023                         t = ParseStmt(p, t, NULL);
1024                 }
1025                 PopStmt(p, cst);
1026         }
1027         t = LexSkipToken(&p->p_Token, TOK_CBRACE);
1028         PopStmt(p, st);
1029         return(t);
1030 }
1031
1032 static int
1033 ParseThreadSchedStmt(Parse *p, int t, Stmt **pst)
1034 {
1035         Stmt *st = PushStmt(p, pst, ST_ThreadSched, 0);
1036         t = LexToken(&p->p_Token);
1037         st->st_ThreadSchedStmt.es_Mode = 0;
1038         while (t & TOKF_ID) {
1039                 if (StrCmpToken(String_Preempt, &p->p_Token) == 0) {
1040                         st->st_ThreadSchedStmt.es_Mode = SPECIAL_AUX_PREEMPT;
1041                 } else if (StrCmpToken(String_NoPreempt, &p->p_Token) == 0) {
1042                         st->st_ThreadSchedStmt.es_Mode = SPECIAL_AUX_NOPREEMPT;
1043                 } else if (StrCmpToken(String_Immediate, &p->p_Token) == 0) {
1044                         st->st_ThreadSchedStmt.es_Mode = SPECIAL_AUX_IMMEDIATE;
1045                 } else {
1046                         t = LexError(&p->p_Token, TOK_ERR_SYNTAX);
1047                 }
1048                 if ((t & TOKF_ERROR) == 0)
1049                         t = LexToken(&p->p_Token);
1050         }
1051         t = LexSkipToken(&p->p_Token, TOK_SEMI);
1052         PopStmt(p, st);
1053         return(t);
1054 }
1055
1056 /*
1057  * if (exp) stmt [ else stmt ]
1058  */
1059 static int
1060 ParseIfElseStmt(Parse *p, int t, Stmt **pst)
1061 {
1062         Stmt *st = PushStmt(p, pst, ST_IfElse, 0);
1063
1064         t = LexSkipToken(&p->p_Token, TOK_IF);
1065         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
1066         t = ParseExp(p, t, &st->st_IfStmt.es_Exp);
1067         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
1068         t = ParseStmt(p, t, &st->st_IfStmt.es_TrueStmt);
1069         if (t == TOK_ELSE) {
1070                 t = LexToken(&p->p_Token);
1071                 t = ParseStmt(p, t, &st->st_IfStmt.es_FalseStmt);
1072         }
1073         PopStmt(p, st);
1074         return(t);
1075 }
1076
1077 /*
1078  * return ([id:]exp[, [id:]exp]*);
1079  */
1080 static int
1081 ParseReturnStmt(Parse *p, int t, Stmt **pst)
1082 {
1083         Stmt *st = PushStmt(p, pst, ST_Return, 0);
1084         Stmt *scan;
1085
1086         t = LexSkipToken(&p->p_Token, TOK_RETURN);
1087
1088         if (t == TOK_OPAREN)
1089                 t = ParseParenthesizedExp(p, t, &st->st_RetStmt.es_Exp, 1);
1090         else if (t != TOK_SEMI)
1091                 t = ParseExp(p, t, &st->st_RetStmt.es_Exp);
1092         t = LexSkipToken(&p->p_Token, TOK_SEMI);
1093
1094         /*
1095          * Calculate the break-count required to return from the
1096          * procedure.  There are no special cases for 'break' count
1097          * calculations.
1098          */
1099         for (
1100                 scan = st->st_Parent; 
1101                 scan->st_Op != ST_Proc;
1102                 scan = scan->st_Parent
1103         ) {
1104                 ++st->st_RetStmt.es_Count;
1105                 if (scan->st_Op == ST_IfElse)   /* if stmt counts twice */
1106                         ++st->st_RetStmt.es_Count;
1107         }
1108         ++st->st_RetStmt.es_Count;      /* break out of procedure block */
1109
1110         PopStmt(p, st);
1111         return(t);
1112 }
1113
1114 /*
1115  * result ([id:]exp[, [id:]exp]*);
1116  */
1117 static int
1118 ParseResultStmt(Parse *p, int t, Stmt **pst)
1119 {
1120         Stmt *st = PushStmt(p, pst, ST_Result, 0);
1121         Stmt *scan;
1122
1123         /*
1124          * Parse a (possibly compound) expression.  Note that the parentheses
1125          * are required.
1126          */
1127         t = LexSkipToken(&p->p_Token, TOK_RESULT);
1128
1129         if (t == TOK_OPAREN)
1130                 t = ParseParenthesizedExp(p, t, &st->st_ResStmt.es_Exp, 1);
1131         else if (t != TOK_SEMI)
1132                 t = ParseExp(p, t, &st->st_ResStmt.es_Exp);
1133         t = LexSkipToken(&p->p_Token, TOK_SEMI);
1134
1135         /*
1136          * Calculate the break-count required to return from the
1137          * procedure.  There are no special cases for 'break' count
1138          * calculations.
1139          *
1140          * Note that the compiler and interpreter ignore the break count
1141          * for result() statements.. that is, they do not actually return
1142          * from the procedure from the point of view of the procedure.  What
1143          * they do is 'set' the return value and, if the procedure is a thread,
1144          * allow the caller's thread to resume with that value while continuing
1145          * to run the new procedure in its own thread.
1146          */
1147         for (
1148                 scan = st->st_Parent; 
1149                 scan->st_Op != ST_Proc;
1150                 scan = scan->st_Parent
1151         ) {
1152                 ++st->st_ResStmt.es_Count;
1153                 if (scan->st_Op == ST_IfElse)   /* if stmt counts twice */
1154                         ++st->st_RetStmt.es_Count;
1155         }
1156         ++st->st_ResStmt.es_Count;      /* break out of procedure block */
1157
1158         PopStmt(p, st);
1159         return(t);
1160 }
1161
1162 int
1163 ParseNopStmt(Parse *p, int t, Stmt **pst)
1164 {
1165         Stmt *st = PushStmt(p, pst, ST_Nop, 0);
1166
1167         t = LexSkipToken(&p->p_Token, TOK_SEMI);
1168         PopStmt(p, st);
1169         return(t);
1170 }
1171
1172 /*
1173  * A declaration statement, such as:  int a = 4, b, c = 27;
1174  *
1175  * idRequired will either be 1 or 2.  2 is used at the top level of the
1176  * source module, 1 is used elsewhere.  Note that if 2 is used the declaration
1177  * may be silently moved out of the current SemGroup and into the SemGroup
1178  * of some other class.  Also, an idRequired of 2 implies global scope in the
1179  * case where the declaration is NOT moved.  See ParseDeclaration().
1180  */
1181 int
1182 ParseDeclarationStmt(Parse *p, int t, int idRequired,
1183                      Stmt **pst, int dop, Scope *scope)
1184 {
1185         Stmt *st = PushStmt(p, pst, ST_Decl, 0);
1186
1187         st->st_DeclStmt.es_Scope = *scope;
1188
1189         for (;;) {
1190                 Declaration *d = NULL;
1191
1192                 switch(t) {
1193                 case TOK_CLASS:
1194                 case TOK_INTERFACE:
1195                         t = LexError(&p->p_Token, TOK_ERR_NESTED_CLASS);
1196                         break;
1197                 case TOK_SUBCLASS:
1198                 case TOK_SUBINTERFACE:
1199                         t = LexError(&p->p_Token, TOK_ERR_NESTED_CLASS);
1200                         break;
1201                 default:
1202                         t = ParseDeclaration(p, t, &d, idRequired, dop, scope);
1203                         break;
1204                 }
1205                 if (st->st_DeclStmt.es_Decl == NULL)
1206                         st->st_DeclStmt.es_Decl = d;
1207
1208                 /*
1209                  * Assign d_Stmt.  Force SCOPE_GLOBAL if the declaration
1210                  * resides in its import semantic group.
1211                  */
1212                 if (d) {
1213                         d->d_Stmt = st;
1214
1215                         if (d->d_MyGroup == d->d_ImportSemGroup) {
1216                                 d->d_ScopeFlags |= SCOPE_GLOBAL;
1217                         }
1218
1219                 }
1220                 ++st->st_DeclStmt.es_DeclCount;
1221                 if (t & TOKF_ERROR)
1222                         break;
1223
1224                 /*
1225                  * Handle a process definition by attaching the { body }.
1226                  */
1227                 if (t == TOK_OBRACE) {
1228                         if (d->d_Op == DOP_PROC) {
1229                                 dassert_decl(d,
1230                                     d->d_ProcDecl.ed_Type->ty_Op == TY_PROC);
1231                                 t = ParseProcStmt(p, t, d,
1232                                                   &d->d_ProcDecl.ed_OrigBody);
1233                         } else {
1234                                 t = LexError(&p->p_Token,
1235                                              TOK_ERR_DECL_NOT_PROCEDURE);
1236                         }
1237                         break;  /* only one allowed */
1238                 }
1239                 if (d->d_Op == DOP_ALIAS) {
1240                         t = LexSkipToken(&p->p_Token, TOK_SEMI);
1241                         break;  /* only one allowed */
1242                 }
1243                 /*
1244                  * Otherwise look for a comma or a semicolon
1245                  */
1246                 if (t == TOK_SEMI) {
1247                         t = LexToken(&p->p_Token);
1248                         break;
1249                 }
1250                 if (t != TOK_COMMA) {
1251                         t = LexError(&p->p_Token, TOK_ERR_EXPECTED_COMMA);
1252                         break;
1253                 }
1254                 t = LexToken(&p->p_Token);
1255         }
1256         PopStmt(p, st);
1257         return(t);
1258 }
1259
1260 static int
1261 ParseExpStmt(Parse *p, int t, Stmt **pst)
1262 {
1263         Stmt *st = PushStmt(p, pst, ST_Exp, 0);
1264
1265         t = ParseExp(p, t, &st->st_ExpStmt.es_Exp);
1266         t = LexSkipToken(&p->p_Token, TOK_SEMI);
1267         PopStmt(p, st);
1268         return(t);
1269 }