Rune - Generation work
[rune.git] / librune / parse3.c
1 /*
2  * PARSE3.C     - The expression parser
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 Exp *pushOper(Parse *p, Exp **op, Exp **val,
11                         int t, string_t id, int flags);
12 static Exp *pushValue(Parse *p, Exp **op, Exp **val, int t, string_t id);
13 static void pushValueExp(Exp **op, Exp **val, Exp *exp);
14 static int popExp(Exp **op, Exp **val);
15
16 int
17 ParseExp(Parse *p, int t, Exp **pexp)
18 {
19         Exp *opStack = NULL;
20         Exp *valStack = NULL;
21         Exp *tmp;
22         int save;
23         int mode = 1;           /* start in unary mode */
24         int done = 0;
25         int t2;
26
27         while ((t & TOKF_ERROR) == 0 && !done) {
28                 if (mode == 1) {
29                         /*
30                          * UNARY
31                          */
32                         switch(t) {
33                         case TOK_ASS:           /* syntax error */
34                         case TOK_ANDAND:        /* syntax error */
35                         case TOK_OROR:          /* syntax error */
36                         case TOK_DOT:           /* syntax error */
37                         case TOK_STRIND:        /* syntax error */
38                                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
39                                 break;
40                         case TOK_OPER:          /* unary operator */
41                                 /*
42                                  * We have to deal with pointer indirection.
43                                  * Regenerate the token using only the first
44                                  * character if it is a '*'
45                                  */
46                                 switch(p->p_Token.t_Ptr[0]) {
47                                 case '*':
48                                         t = LexRedactToken(&p->p_Token, 1);
49                                         t = TOK_PTRIND;
50                                         break;
51                                 case '&':
52                                         t = LexRedactToken(&p->p_Token, 1);
53                                         t = TOK_ADDR;
54                                         break;
55                                 default:
56                                         break;
57                                 }
58                                 pushOper(p, &opStack, &valStack, t, 
59                                          StrTableToken(&p->p_Token), EXF_UNARY);
60                                 t = LexToken(&p->p_Token);
61                                 break;
62                         case TOK_OBRACKET:      /* syntax error */
63                         case TOK_CBRACKET:      /* syntax error */
64                                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
65                                 break;
66                         case TOK_OPAREN:        /* ( [id:]exp[, [id:]exp]* ) */
67                                 /*
68                                  * Parenthesized expression: Either a compound
69                                  * expression (which might degenerate back
70                                  * into a normal expression in the resolver),
71                                  * or a cast.
72                                  *
73                                  * (typeof(...)) is supported as a cast.
74                                  */
75                                 t2 = LexPeekToken(&p->p_Token);
76                                 if (t2 == TOK_TYPEOF) {
77                                         Exp *save2;
78
79                                         t = LexSkipToken(&p->p_Token,
80                                                          TOK_OPAREN);
81                                         assert(t == TOK_TYPEOF);
82                                         t = ParseExp(p, t, &save2);
83                                         t = LexSkipToken(&p->p_Token,
84                                                          TOK_CPAREN);
85
86                                         /*
87                                          * This is nasty, but easy to parse
88                                          * so... allow selection on a cast
89                                          * as if it were a type.
90                                          */
91                                         if (t == TOK_DOT) {
92                                                 tmp = pushValue(p, &opStack,
93                                                                 &valStack,
94                                                                 TOK_TYPE,
95                                                                 NULL);
96                                                 mode = 2;
97                                         } else {
98                                                 tmp = pushOper(p, &opStack,
99                                                                &valStack,
100                                                                TOK_CAST,
101                                                                NULL,
102                                                                EXF_UNARY);
103                                         }
104
105                                         tmp->ex_Type = save2->ex_Type;
106                                         tmp->ex_Flags |= save2->ex_Flags & 
107                                                          (EXF_PARSE_TYPE |
108                                                           EXF_REQ_TYPE);
109                                         if (save2->ex_Flags & EXF_PARSE_TYPE)
110                                                 FreeExp(save2);
111                                         else
112                                                 tmp->ex_Rhs = save2;
113                                 } else if ((t2 & (TOKF_SCOPE_QUAL |
114                                                  TOKF_STOR_QUAL)) ||
115                                            t2 == TOK_CLASSID) {
116                                         Type *type;
117                                         Scope scope;
118                                         int sqflags;
119                                         int rqflags;
120                                         string_t id = NULL;
121
122                                         t = LexSkipToken(&p->p_Token,
123                                                          TOK_OPAREN);
124                                         /* ignore scope */
125                                         t = ParseScopeQual(p, t, &scope);
126                                         t = ParseStorageQual(p, t, &sqflags);
127                                         if (scope.s_Flags & SCOPE_LVALUE)       
128                                                 rqflags = SF_LVALUE;
129                                         else
130                                                 rqflags = 0;
131                                         t = ParseType(p, t, &type, sqflags);
132                                         t = ParseDeclType(p, t, &type,
133                                                           NULL,
134                                                           scope.s_Flags &
135                                                            SCOPE_CLANG,
136                                                           rqflags, &id, 0);
137                                         t = LexSkipToken(&p->p_Token,
138                                                          TOK_CPAREN);
139                                         /*
140                                          * This is nasty, but easy to parse
141                                          * so... allow selection on a cast
142                                          * as if it were a type.
143                                          */
144                                         if (t == TOK_DOT) {
145                                                 tmp = pushValue(p, &opStack,
146                                                                 &valStack,
147                                                                 TOK_TYPE,
148                                                                 NULL);
149                                                 mode = 2;
150                                         } else {
151                                                 tmp = pushOper(p, &opStack,
152                                                                &valStack,
153                                                                TOK_CAST,
154                                                                NULL,
155                                                                EXF_UNARY);
156                                         }
157                                         tmp->ex_Type = type;
158                                         tmp->ex_Flags |= EXF_PARSE_TYPE;
159                                 } else {
160                                         t = ParseParenthesizedExp(p, t,
161                                                                   &tmp, 1);
162                                         pushValueExp(&opStack, &valStack, tmp);
163                                         mode = 2;
164                                 }
165                                 break;
166                         case TOK_DSTRING:       /* value */
167                         case TOK_SSTRING:       /* value */
168                         case TOK_BSTRING:       /* value */
169                         case TOK_INTEGER:       /* value */
170                         case TOK_FLOAT: /* value */
171                                 pushValue(p, &opStack, &valStack,
172                                           t, StrTableToken(&p->p_Token));
173                                 t = LexToken(&p->p_Token);
174                                 mode = 2;
175                                 break;
176                         case TOK_SIZEOF:
177                         case TOK_ARYSIZE:
178                         case TOK_TYPEOF:
179                                 /*
180                                  * We can distinguish between expressions and
181                                  * types by identifying a scope or storage
182                                  * qualifier or a type-flagged identifier.
183                                  */
184                                 save = t;
185                                 t = LexToken(&p->p_Token);
186                                 if (t == TOK_OPAREN)
187                                         t2 = LexPeekToken(&p->p_Token);
188                                 else
189                                         t2 = 0;
190
191                                 if (t == TOK_OPAREN &&
192                                     ((t2 & (TOKF_SCOPE_QUAL |
193                                             TOKF_STOR_QUAL)) ||
194                                      t2 == TOK_CLASSID)
195                                 ) {
196                                         Scope scope;
197                                         int sqflags;
198                                         int rqflags;
199                                         string_t id = NULL;
200                                         Type *type;
201
202                                         t = LexSkipToken(&p->p_Token,
203                                                          TOK_OPAREN);
204                                         /* ignore scope */
205                                         t = ParseScopeQual(p, t, &scope);
206                                         t = ParseStorageQual(p, t, &sqflags);
207                                         if (scope.s_Flags & SCOPE_LVALUE)       
208                                                 rqflags = SF_LVALUE;
209                                         else
210                                                 rqflags = 0;
211                                         tmp = WrapExp(&p->p_Token, NULL, save);
212                                         t = ParseType(p, t, &type, sqflags);
213                                         t = ParseDeclType(p, t, &type, NULL,
214                                                           scope.s_Flags &
215                                                            SCOPE_CLANG,
216                                                           rqflags, &id, 0);
217                                         tmp->ex_Type = type;
218                                         tmp->ex_Flags |= EXF_PARSE_TYPE |
219                                                          EXF_RET_TYPE;
220                                 } else {
221                                         t = LexSkipToken(&p->p_Token,
222                                                          TOK_OPAREN);
223                                         t = ParseExp(p, t, &tmp);
224                                         if (tmp->ex_Lhs)
225                                                 tmp->ex_Flags |= EXF_UNARY;
226                                         tmp = WrapExp(&p->p_Token, tmp, save);
227                                 }
228 #if 0
229                                 /*
230                                  * XXX removed because this can cause dynamic
231                                  * type resolution at run-time to occur.
232                                  */
233                                 if (t == TOK_COMMA) {
234                                         /*
235                                          * remove storage qualifiers
236                                          */
237                                         t = LexToken(&p->p_Token);
238                                         t = ParseStorageQual(p, t,
239                                                         &tmp->ex_AuxFlags[0]);
240                                 }
241                                 if (t == TOK_COMMA) {
242                                         /*
243                                          * add storage qualifiers
244                                          */
245                                         t = LexToken(&p->p_Token);
246                                         t = ParseStorageQual(p, t,
247                                                         &tmp->ex_AuxFlags[1]);
248                                 }
249 #endif
250                                 if (tmp->ex_Lhs)
251                                         tmp->ex_Flags |= EXF_UNARY;
252                                 pushValueExp(&opStack, &valStack, tmp);
253                                 t = LexSkipToken(&p->p_Token, TOK_CPAREN);
254                                 mode = 2;
255                                 break;
256                         case TOK_ID:            /* value: semantic id */
257                         case TOK_CLASSID:       /* value: semantic id */
258                                 pushValue(p, &opStack, &valStack,
259                                           t, StrTableToken(&p->p_Token));
260                                 t = LexToken(&p->p_Token);
261                                 mode = 2;
262                                 break;
263                         case TOK_SELF:
264                                 /*
265                                  * Identifies the procedure's argument space.
266                                  */
267                                 pushValue(p, &opStack, &valStack, t, NULL);
268                                 t = LexToken(&p->p_Token);
269                                 mode = 2;
270                                 break;
271                         case TOK_DOLLAR:
272                                 /*
273                                  * Identifies the procedure's return storage.
274                                  */
275                                 pushValue(p, &opStack, &valStack, t, NULL);
276                                 t = LexToken(&p->p_Token);
277                                 mode = 2;
278                                 break;
279                         case TOK_CPAREN:        /* syntax error */
280                         case TOK_CBRACE:        /* syntax error */
281                         case TOK_COMMA: /* syntax error */
282                         case TOK_SEMI:  /* syntax error */
283                         case TOK_COLON: /* syntax error */
284                         default:
285                                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
286                                 break;
287                         }
288                 } else {
289                         /*
290                          * BINARY
291                          */
292                         switch(t) {
293                         case TOK_ASS:
294                         case TOK_ANDAND:        /* binary operator */
295                         case TOK_OROR:  /* binary operator */
296                         case TOK_DOT:   /* binary operator */
297                         case TOK_STRIND:        /* binary operator */
298                         case TOK_OPER:  /* binary operator */
299                                 pushOper(p, &opStack, &valStack, t, 
300                                          StrTableToken(&p->p_Token),
301                                          EXF_BINARY);
302                                 t = LexToken(&p->p_Token);
303                                 mode = 1;
304                                 break;
305                         case TOK_OBRACKET:      /* '[' array operator */
306                                 t = LexToken(&p->p_Token);
307                                 tmp = NULL;
308                                 t = ParseExp(p, t, &tmp);
309                                 t = LexSkipToken(&p->p_Token, TOK_CBRACKET);
310                                 pushOper(p, &opStack, &valStack,
311                                          TOK_OBRACKET, NULL, EXF_BINARY);
312                                 pushValueExp(&opStack, &valStack, tmp);
313                                 break;
314                         case TOK_CBRACKET:      /* ']' terminator */
315                                 done = 1;
316                                 break;
317                         case TOK_OPAREN:
318                                 /*
319                                  * Procedure call.  In order to avoid
320                                  * fubar((x, y)) confusion we do not allow
321                                  * ParseParenthesizedExp() to generate a
322                                  * compound exp encapsulation for comma
323                                  * delimited case.  Instead we do it ourselves.
324                                  */
325                                 t = ParseParenthesizedExp(p, t, &tmp, 0);
326                                 tmp = ExpToCompoundExp(tmp, TOK_COMPOUND);
327                                 pushOper(p, &opStack, &valStack,
328                                          TOK_CALL, NULL, EXF_BINARY);
329                                 pushValueExp(&opStack, &valStack, tmp);
330                                 break;
331                         case TOK_ID:            /* syntax error */
332                         case TOK_CLASSID:       /* syntax error */
333                                 t = LexError(&p->p_Token,
334                                              TOK_ERR_EXP_SYNTAX_MAYTYPE);
335                                 break;
336                         case TOK_DSTRING:       /* syntax error */
337                         case TOK_SSTRING:       /* syntax error */
338                         case TOK_BSTRING:       /* syntax error */
339                         case TOK_INTEGER:       /* syntax error */
340                         case TOK_FLOAT: /* syntax error */
341                         case TOK_SIZEOF:        /* syntax error */
342                         case TOK_ARYSIZE:       /* syntax error */
343                         case TOK_TYPEOF:        /* syntax error */
344                         case TOK_SELF:  /* syntax error */
345                                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
346                                 break;
347                         case TOK_CPAREN:        /* terminator */
348                         case TOK_CBRACE:        /* terminator */
349                         case TOK_COMMA: /* terminator */
350                         case TOK_SEMI:  /* terminator */
351                         case TOK_COLON: /* terminator */
352                                 done = 1;
353                                 break;
354                         default:
355                                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
356                                 break;
357                         }
358                 }
359         }
360         while (opStack) {
361                 if (popExp(&opStack, &valStack) < 0) {
362                         t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
363                 }
364         }
365         if (valStack == NULL) {
366                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
367         } else if (valStack->ex_Next != NULL) {
368                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
369                 FreeExp(valStack->ex_Next);
370                 valStack->ex_Next = NULL;
371         }
372         *pexp = valStack;
373         return(t);
374 }
375
376 /*
377  * ParseParenthesizedExp() - parse a parenthesized expression.
378  *
379  *      This will parse a parenthesized, possibly compound expression.  docomp
380  *      determines whether the returned expression should be collapsed into
381  *      TOK_COMPOUND when there is more then one element, or whether this
382  *      should be left up to the caller.  Note that if you *REQUIRE* the
383  *      result to be compound, you should pass docomp as 0 and call
384  *      ExpToCompoundExp() unconditionally on the returned expression
385  *      to avoid confusion.
386  *
387  *      An empty expression returns a TOK_VOIDEXP exp node.
388  *
389  *      Note: A single expressive element is considered to be compound if it
390  *      is named.
391  */
392 int
393 ParseParenthesizedExp(Parse *p, int t, Exp **pexp, int docomp)
394 {
395         Exp *tmp = NULL;
396
397         t = LexSkipToken(&p->p_Token, TOK_OPAREN);
398         if (t != TOK_CPAREN) {
399                 Exp **pnext = &tmp;
400                 for (;;) {
401                         string_t argId = NULL;
402                         if (t == TOK_ID || t == TOK_CLASSID/* XXX */) {
403                                 /* lookahead */
404                                 token_t t2 = p->p_Token;
405
406                                 if (LexToken(&t2) == TOK_COLON) {
407                                         argId = StrTableToken(&p->p_Token);
408                                         /* get the colon */
409                                         LexToken(&p->p_Token);
410                                         t = LexSkipToken(&p->p_Token,
411                                                          TOK_COLON);
412                                 }
413                         }
414                         t = ParseExp(p, t, pnext);
415                         if (*pnext) {
416                                 (*pnext)->ex_ArgId = argId;
417                                 pnext = &(*pnext)->ex_Next;
418                         }
419                         if (t != TOK_COMMA)
420                                 break;
421                         t = LexToken(&p->p_Token);
422                 }
423         }
424         t = LexSkipToken(&p->p_Token, TOK_CPAREN);
425         if (tmp) {
426                 if (docomp && (tmp->ex_ArgId || tmp->ex_Next))
427                         tmp = ExpToCompoundExp(tmp, TOK_COMPOUND);
428         } else {
429                 tmp = AllocExp(&p->p_Token);
430                 tmp->ex_Token = TOK_VOIDEXP;
431         }
432         *pexp = tmp;
433         return(t);
434 }
435
436 int
437 ParseNotExp(Parse *p, int t, Exp **pexp)
438 {
439         t = ParseExp(p, t, pexp);
440         if ((t & TOKF_ERROR) == 0)
441                 *pexp = ExpToNotExp(*pexp);
442         return(t);
443 }
444
445 static Exp *
446 pushOper(Parse *p, Exp **op, Exp **val, int t, string_t id, int flags)
447 {
448         Exp *exp;
449         int prec;
450         int rtl = 0;    /* right-to-left */
451
452         if (flags & EXF_BINARY) {
453                 prec = EXPREC_USER;
454
455                 switch(t) {
456                 case TOK_OPER:
457                         /*
458                          * If the operator contains '+' or '-' its precedence
459                          * is EXPREC_PLUS.  If the operator contains '<', '=',
460                          * or '>' its precedence is EXPREC_COMPARE
461                          * (overriding '+' or '-').  Otherwise the operator
462                          * is EXPREC_USER
463                          */
464                         if (strpbrk(id, "+-") != NULL)
465                                 prec = EXPREC_PLUS;
466                         if (strpbrk(id, "<=>") != NULL)
467                                 prec = EXPREC_COMPARE;
468                         break;
469                 case TOK_DOT:
470                 case TOK_STRIND:
471                         prec = EXPREC_DOT;
472                         break;
473                 case TOK_OBRACKET:
474                         prec = EXPREC_CLOSURE;
475                         break;
476                 case TOK_CALL:
477                         prec = EXPREC_CALL;
478                         break;
479                 case TOK_ANDAND:
480                         prec = EXPREC_ANDAND;
481                         break;
482                 case TOK_ASS:
483                         prec = EXPREC_ASS;
484                         rtl = 1;
485                         break;
486                 case TOK_OROR:
487                         prec = EXPREC_OROR;
488                         break;
489                 default:
490                         dassert_parse(p, TOK_ERR_UNKNOWN, 0);
491                 }
492         } else {
493                 prec = EXPREC_UNARY;
494                 rtl = 1;
495         }
496
497         /*
498          * Construct the expression
499          */
500         exp = AllocExp(&p->p_Token);
501         exp->ex_Prec = prec;
502         exp->ex_Id = id;
503         exp->ex_Token = t;
504         exp->ex_Flags |= flags;
505
506         /*
507          * Pop-off any operators with a >= precedence.  Handle
508          * special right-to-left ordering for assignments and unary
509          * operators simply by delaying the pop.
510          */
511         while (*op) {
512                 if ((*op)->ex_Prec > prec) {
513                         popExp(op, val);
514                         continue;
515                 }
516                 if (rtl == 0 && (*op)->ex_Prec == prec) {
517                         popExp(op, val);
518                         continue;
519                 }
520                 break;
521         }
522         exp->ex_Next = *op;
523         *op = exp;
524         return(exp);
525 }
526
527 static Exp *
528 pushValue(Parse *p, Exp **op __unused, Exp **val, int t, string_t id)
529 {
530         Exp *exp = AllocExp(&p->p_Token);
531
532         exp->ex_Token = t;
533         exp->ex_Id = id;
534         exp->ex_Next = *val;
535         *val = exp;
536         return(exp);
537 }
538
539 static void
540 pushValueExp(Exp **op __unused, Exp **val, Exp *exp)
541 {
542         exp->ex_Next = *val;
543         *val = exp;
544 }
545
546 static int
547 popExp(Exp **op, Exp **val)
548 {
549         Exp *exp;
550         int r = 0;
551
552         if ((exp = *op) != NULL) {
553                 if (exp->ex_Flags & EXF_BINARY) {
554                         Exp *rhs = *val;
555                         Exp *lhs = (rhs) ? rhs->ex_Next : NULL;
556
557                         /*
558                          * The expression parser will generate an error if
559                          * this situation occurs so we can just return.
560                          */
561                         if (lhs && rhs) {
562                                 *val = lhs->ex_Next;
563                                 lhs->ex_Next = NULL;
564                                 rhs->ex_Next = NULL;
565                                 exp->ex_Lhs = lhs;
566                                 exp->ex_Rhs = rhs;
567
568                                 /*
569                                  * Special handling. 
570                                  */
571                                 switch(exp->ex_Token) {
572                                 case TOK_DOT:
573                                         /*
574                                          * Lhs may be a type, class, module,
575                                          * or variable id.
576                                          *
577                                          * Rhs must be an identifier which we
578                                          * convert to TOK_STRUCT_ID.
579                                          */
580                                         dassert_exp(rhs, rhs->ex_Token ==
581                                                          TOK_ID ||
582                                                          rhs->ex_Token ==
583                                                          TOK_CLASSID);
584                                         rhs->ex_Token = TOK_STRUCT_ID;
585                                         break;
586                                 case TOK_STRIND:
587                                         /*
588                                          * Lhs must an lvalue or rvalue (not
589                                          * checked), Rhs must must be an
590                                          * identifier which we convert to
591                                          * TOK_STRUCT_ID.
592                                          */
593                                         dassert_exp(rhs, rhs->ex_Token ==
594                                                          TOK_ID ||
595                                                          rhs->ex_Token ==
596                                                          TOK_CLASSID);
597                                         rhs->ex_Token = TOK_STRUCT_ID;
598                                         break;
599                                 case TOK_CALL:
600                                         /*
601                                          * The rhs of a procedure call is a
602                                          * compound expression, denoted by
603                                          * TOK_COMPOUND.  The compound
604                                          * expression is necessary to govern
605                                          * the context the arguments will
606                                          * eventually be stored in, so we do
607                                          * not collapse this even if its
608                                          * a void call.
609                                          */
610                                         dassert_exp(rhs, rhs->ex_Token ==
611                                                          TOK_COMPOUND);
612 #if 0
613                                         exp->ex_Rhs = rhs->ex_Lhs;
614                                         rhs->ex_Lhs = NULL;
615                                         FreeExp(rhs);
616                                         rhs = NULL;
617 #endif
618                                         break;
619                                 case TOK_ANDAND:
620                                 case TOK_OROR:
621                                 default:
622                                         break;
623                                 }
624                         } else {
625                                 r = -1;
626                         }
627                 } else {
628                         Exp *lhs = *val;
629
630                         if (lhs) {
631                                 exp->ex_Lhs = lhs;
632                                 *val = lhs->ex_Next;
633                                 lhs->ex_Next = NULL;
634                         } else {
635                                 r = -1;
636                         }
637                 }
638                 *op = exp->ex_Next;
639                 exp->ex_Next = *val;
640                 *val = exp;
641         }
642         return(r);
643 }