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