Rune - Further Object abstraction 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, int t,
11                         const char *sym, int len, int flags);
12 static Exp *pushValue(Parse *p, Exp **op, Exp **val, int t);
13 static Exp *pushValueId(Parse *p, Exp **op, Exp **val, int t, runeid_t id);
14 static Exp *pushValueStr(Parse *p, Exp **op, Exp **val, int t, string_t str);
15 static void pushValueExp(Exp **op, Exp **val, Exp *exp);
16 static int popExp(Exp **op, Exp **val);
17
18 int
19 ParseExp(Parse *p, int t, Exp **pexp)
20 {
21     Exp    *opStack = NULL;
22     Exp    *valStack = NULL;
23     Exp    *tmp;
24     int     save;
25     int     mode = 1;           /* start in unary mode */
26     int     done = 0;
27     int     t2;
28
29     while ((t & TOKF_ERROR) == 0 && !done) {
30         if (mode == 1) {
31             /*
32              * UNARY
33              */
34             switch (t) {
35             case TOK_ASS:       /* syntax error */
36             case TOK_ANDAND:    /* syntax error */
37             case TOK_OROR:      /* syntax error */
38             case TOK_DOT:       /* syntax error */
39             case TOK_STRIND:    /* syntax error */
40                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
41                 break;
42             case TOK_OPER:      /* unary operator */
43                 /*
44                  * Operators parsed as multi-char operators may have to
45                  * be redacted to the proper unary operator.
46                  *
47                  * We have to deal with pointer indirection. Regenerate the
48                  * token using only the first character if it is a '*'
49                  */
50                 switch (p->p_Token.t_Ptr[0]) {
51                 case '*':
52                     t = LexRedactToken(&p->p_Token, 1);
53                     t = TOK_PTRIND;
54                     break;
55                 case '&':
56                     t = LexRedactToken(&p->p_Token, 1);
57                     t = TOK_ADDR;
58                     break;
59                 default:
60                     break;
61                 }
62                 pushOper(p, &opStack, &valStack, t,
63                          p->p_Token.t_Ptr, p->p_Token.t_Len, EXF_UNARY);
64                 t = LexToken(&p->p_Token);
65                 break;
66             case TOK_OBRACKET:
67                 /*
68                  * Bracketed array.  This is similar to a compound expression
69                  * except it represents elements of an array.
70                  */
71                 t = ParseBracketedExp(p, t, &tmp);
72                 pushValueExp(&opStack, &valStack, tmp);
73                 mode = 2;
74                 break;
75             case TOK_CBRACKET:  /* syntax error */
76                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
77                 break;
78             case TOK_OPAREN:    /* ( [id:]exp[, [id:]exp]* ) */
79                 /*
80                  * Parenthesized expression: Either a compound expression
81                  * (which might degenerate back into a normal expression in
82                  * the resolver), or a cast.
83                  *
84                  * (typeof(blah)) is supported as a cast. We may have to save
85                  * (blah) for the resolver, store it in ex_Rhs as a special
86                  * case.
87                  */
88                 t2 = LexPeekToken(&p->p_Token);
89                 if (t2 == TOK_TYPEOF) {
90                     Exp    *save2;
91
92                     t = LexSkipToken(&p->p_Token,
93                                      TOK_OPAREN);
94                     assert(t == TOK_TYPEOF);
95                     t = ParseExp(p, t, &save2);
96                     t = LexSkipToken(&p->p_Token,
97                                      TOK_CPAREN);
98
99                     /*
100                      * This is nasty, but easy to parse so... allow selection
101                      * on a cast as if it were a type.
102                      */
103                     if (t == TOK_DOT) {
104                         tmp = pushValue(p, &opStack, &valStack, TOK_TYPE);
105                         mode = 2;
106                     } else {
107                         tmp = pushOper(p, &opStack, &valStack, TOK_CAST,
108                                        NULL, 0, EXF_UNARY);
109                     }
110
111                     tmp->ex_Type = save2->ex_Type;
112                     tmp->ex_Flags |= save2->ex_Flags &
113                         (EXF_PARSE_TYPE |
114                          EXF_REQ_TYPE);
115                     if (save2->ex_Flags & EXF_PARSE_TYPE)
116                         FreeExp(save2);
117                     else
118                         tmp->ex_Rhs = save2;
119                 } else if ((t2 & (TOKF_SCOPE_QUAL | TOKF_STOR_QUAL)) ||
120                            t2 == TOK_CLASSID)
121                 {
122                     Type   *type;
123                     Scope   scope;
124                     int     sqflags;
125                     int     rqflags;
126                     runeid_t id = 0;
127
128                     t = LexSkipToken(&p->p_Token,
129                                      TOK_OPAREN);
130                     /* ignore scope */
131                     t = ParseScopeQual(p, t, &scope);
132                     t = ParseStorageQual(p, t, &sqflags);
133                     if (scope.s_Flags & SCOPE_LVALUE)
134                         rqflags = SF_LVALUE;
135                     else
136                         rqflags = 0;
137                     t = ParseType(p, t, &type, sqflags);
138                     t = ParseDeclType(p, t, &type,
139                                       NULL,
140                                       scope.s_Flags &
141                                       SCOPE_CLANG,
142                                       rqflags, &id, 0);
143                     t = LexSkipToken(&p->p_Token,
144                                      TOK_CPAREN);
145                     /*
146                      * This is nasty, but easy to parse so... allow selection
147                      * on a cast as if it were a type.
148                      */
149                     if (t == TOK_DOT) {
150                         tmp = pushValue(p, &opStack, &valStack, TOK_TYPE);
151                         mode = 2;
152                     } else {
153                         tmp = pushOper(p, &opStack, &valStack, TOK_CAST,
154                                        NULL, 0, EXF_UNARY);
155                     }
156                     tmp->ex_Type = type;
157                     tmp->ex_Flags |= EXF_PARSE_TYPE;
158                 } else {
159                     t = ParseParenthesizedExp(p, t, &tmp, 1);
160                     pushValueExp(&opStack, &valStack, tmp);
161                     mode = 2;
162                 }
163                 break;
164             case TOK_DSTRING:   /* value */
165             case TOK_BSTRING:   /* value */
166                 pushValueStr(p, &opStack, &valStack,
167                              t, StrTableToken(&p->p_Token));
168                 t = LexToken(&p->p_Token);
169                 mode = 2;
170                 break;
171             case TOK_SSTRING:   /* value */
172                 {
173                     uint64_t val;
174
175                     tmp = pushValue(p, &opStack, &valStack, t);
176                     val = StrTableSingleQuotedString(p->p_Token.t_Ptr,
177                                                      p->p_Token.t_Len,
178                                                      &tmp->ex_Type);
179                     if (tmp->ex_Type == &UInt8Type) {
180                         tmp->ex_Tmp.ts_UInt8 = val;
181                     } else if (tmp->ex_Type == &UInt16Type) {
182                         tmp->ex_Tmp.ts_UInt16 = val;
183                     } else if (tmp->ex_Type == &UInt32Type) {
184                         tmp->ex_Tmp.ts_UInt32 = val;
185                     } else if (tmp->ex_Type == &UInt64Type) {
186                         tmp->ex_Tmp.ts_UInt64 = val;
187                     }
188                 }
189                 tmp->ex_Flags |= EXF_PARSE_TYPE;
190                 t = LexToken(&p->p_Token);
191                 mode = 2;
192                 break;
193             case TOK_INTEGER:   /* value */
194                 /*
195                  * Save as an integer
196                  */
197                 if (p->p_Token.t_Ptr[0] == '#') {
198                     /*
199                      * #id - runeid_t hashed identifier
200                      */
201                     tmp = pushValue(p, &opStack, &valStack, t);
202                     tmp->ex_Tmp.ts_UInt64 = p->p_Token.t_Id;
203                     tmp->ex_Type = &UInt64Type;
204                 } else {
205                     /* 
206                      * C-like integer constants (though with more suffixes)
207                      */
208                     unsigned long long uval;
209                     char    buf[RUNE_MAXFLT_CHARS];
210                     char    *ptr;
211                     int     size;
212
213                     /*
214                      * We're just gonna use strtoull(), the string
215                      * must be zero-terminated.
216                      */
217                     if (p->p_Token.t_Len >= RUNE_MAXINT_CHARS) {
218                         t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
219                         break;
220                     }
221                     bcopy(p->p_Token.t_Ptr, buf, p->p_Token.t_Len);
222                     buf[p->p_Token.t_Len] = 0;
223
224                     /*
225                      * Push atom
226                      */
227                     tmp = pushValue(p, &opStack, &valStack, t);
228
229                     /*
230                      * Evaluate the integer
231                      */
232                     ptr = buf;
233                     uval = strtoull(buf, &ptr, 0);
234                     size = 4;
235
236                     while (*ptr) {
237                         switch (*ptr) {
238                         case 'u':
239                         case 'U':
240                             size |= 0x1000;             /* unsigned constant */
241                             break;
242                         case 's':
243                         case 'S':
244                             size &= ~0x1000;            /* signed constant */
245                             break;
246                         case 'b':
247                         case 'B':
248                             size = (size & ~0xFFF) | 1; /* always 8 bits */
249                             break;
250                         case 'w':
251                         case 'W':
252                             size = (size & ~0xFFF) | 2; /* always 16 bits */
253                             break;
254                         case 'i':
255                         case 'I':
256                             size = (size & ~0xFFF) | 4; /* always 32 bits */
257                             break;
258                         case 'l':
259                         case 'L':
260                             size = (size & ~0xFFF) | 8; /* always 64 bits */
261                             break;
262                         case 'p':
263                         case 'P':
264                             /*
265                              * [u]intptr_t can vary in size depending on
266                              * the architecture and model, but is always
267                              * as wide or wider than size_t.
268                              */
269                             size = (size & ~0xFFF) | sizeof(intptr_t);
270                             break;
271                         case 'x':
272                         case 'X':
273                             size = (size & ~0xFFF) | 16; /* always 128 bits */
274                             break;
275                         case 'z':
276                         case 'Z':
277                             /*
278                              * usize_t/ssize_t can vary in size depending on
279                              * the architecture and model.
280                              */
281                             size = (size & ~0xFFF) | sizeof(urunesize_t);
282                             break;
283                         default:
284                             dfatal_exp(tmp, TOK_ERR_ILLEGAL_SUFFIX, NULL);
285                             /* NOT REACHED */
286                             break;
287                         }
288                         ++ptr;
289                     }
290
291                     switch (size) {
292                     case 1:
293                         tmp->ex_Type = &Int8Type;
294                         tmp->ex_Tmp.ts_Int8 = (int8_t)uval;
295                         break;
296                     case 2:
297                         tmp->ex_Type = &Int16Type;
298                         tmp->ex_Tmp.ts_Int16 = (int16_t)uval;
299                         break;
300                     case 4:
301                         tmp->ex_Type = &Int32Type;
302                         tmp->ex_Tmp.ts_Int32 = (int32_t)uval;
303                         break;
304                     case 8:
305                         tmp->ex_Type = &Int64Type;
306                         tmp->ex_Tmp.ts_Int64 = (int64_t)uval;
307                         break;
308                     case 16:
309                         t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);/*XXX*/
310                         tmp->ex_Type = &Int128Type;
311                         //tmp->ex_Tmp.ts_Int128 = uval;
312                         break;
313                     case 0x1000 | 1:
314                         tmp->ex_Type = &UInt8Type;
315                         tmp->ex_Tmp.ts_UInt8 = (uint8_t)uval;
316                         break;
317                     case 0x1000 | 2:
318                         tmp->ex_Type = &UInt16Type;
319                         tmp->ex_Tmp.ts_UInt16 = (uint16_t)uval;
320                         break;
321                     case 0x1000 | 4:
322                         tmp->ex_Type = &UInt32Type;
323                         tmp->ex_Tmp.ts_UInt32 = (uint32_t)uval;
324                         break;
325                     case 0x1000 | 8:
326                         tmp->ex_Type = &UInt64Type;
327                         tmp->ex_Tmp.ts_UInt64 = (uint64_t)uval;
328                         break;
329                     case 0x1000 | 16:
330                         t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);/*XXX*/
331                         tmp->ex_Type = &UInt128Type;
332                         //tmp->ex_Tmp.ts_UInt128 = uval;
333                         break;
334                     default:
335                         tmp->ex_Type = &Int32Type;
336                         tmp->ex_Tmp.ts_Int32 = (int32_t)uval;
337                         break;
338                     }
339                 }
340                 tmp->ex_Flags |= EXF_PARSE_TYPE;
341                 t = LexToken(&p->p_Token);
342                 mode = 2;
343                 break;
344             case TOK_FLOAT:
345                 /*
346                  * Save as a floating point number
347                  */
348                 {
349                     long double fval;
350                     char    buf[RUNE_MAXFLT_CHARS];
351                     char    *ptr;
352
353                     /*
354                      * We're just gonna use strtold(), the string
355                      * must be zero-terminated.
356                      */
357                     if (p->p_Token.t_Len >= RUNE_MAXFLT_CHARS) {
358                         t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
359                         break;
360                     }
361                     bcopy(p->p_Token.t_Ptr, buf, p->p_Token.t_Len);
362                     buf[p->p_Token.t_Len] = 0;
363
364                     /*
365                      * Value atom
366                      */
367                     tmp = pushValue(p, &opStack, &valStack, t);
368                     tmp->ex_Type = &Float64Type;
369
370                     ptr = buf;
371                     fval = strtold(buf, &ptr);
372                     tmp->ex_Tmp.ts_Float64 = (float64_t)fval;
373
374                     while (*ptr) {
375                         switch (*ptr) {
376                         case 'f':
377                         case 'F':
378                             tmp->ex_Type = &Float32Type;
379                             tmp->ex_Tmp.ts_Float32 = (float32_t)fval;
380                             break;
381                         case 'd':
382                         case 'D':
383                             tmp->ex_Type = &Float64Type;
384                             tmp->ex_Tmp.ts_Float64 = (float64_t)fval;
385                             break;
386                         case 'x':
387                         case 'X':
388                             tmp->ex_Type = &Float128Type;
389                             tmp->ex_Tmp.ts_Float128 = fval;
390                             break;
391                         }
392                         ++ptr;
393                     }
394                 }
395                 tmp->ex_Flags |= EXF_PARSE_TYPE;
396                 t = LexToken(&p->p_Token);
397                 mode = 2;
398                 break;
399             case TOK_SIZEOF:
400             case TOK_ARYSIZE:
401             case TOK_TYPEOF:
402                 /*
403                  * We can distinguish between expressions and types by
404                  * identifying a scope or storage qualifier or a type-flagged
405                  * identifier.
406                  */
407                 save = t;
408                 t = LexToken(&p->p_Token);
409                 if (t == TOK_OPAREN)
410                     t2 = LexPeekToken(&p->p_Token);
411                 else
412                     t2 = 0;
413
414                 if (t == TOK_OPAREN &&
415                     ((t2 & (TOKF_SCOPE_QUAL | TOKF_STOR_QUAL)) ||
416                      t2 == TOK_CLASSID))
417                 {
418                     Scope   scope;
419                     int     sqflags;
420                     int     rqflags;
421                     runeid_t id = 0;
422                     Type   *type;
423
424                     t = LexSkipToken(&p->p_Token,
425                                      TOK_OPAREN);
426                     /* ignore scope */
427                     t = ParseScopeQual(p, t, &scope);
428                     t = ParseStorageQual(p, t, &sqflags);
429                     if (scope.s_Flags & SCOPE_LVALUE)
430                         rqflags = SF_LVALUE;
431                     else
432                         rqflags = 0;
433                     tmp = WrapExp(&p->p_Token, NULL, save);
434                     t = ParseType(p, t, &type, sqflags);
435                     t = ParseDeclType(p, t, &type, NULL,
436                                       scope.s_Flags &
437                                       SCOPE_CLANG,
438                                       rqflags, &id, 0);
439                     tmp->ex_Type = type;
440                     tmp->ex_Flags |= EXF_PARSE_TYPE | EXF_RET_TYPE;
441                 } else {
442                     t = LexSkipToken(&p->p_Token, TOK_OPAREN);
443                     t = ParseExp(p, t, &tmp);
444                     /*
445                      * XXX why was this here? if (tmp->ex_Lhs) tmp->ex_Flags
446                      * |= EXF_UNARY;
447                      */
448                     tmp = WrapExp(&p->p_Token, tmp, save);
449                 }
450 #if 0
451                 /*
452                  * XXX removed because this can cause dynamic type resolution
453                  * at run-time to occur.
454                  */
455                 if (t == TOK_COMMA) {
456                     /*
457                      * remove storage qualifiers
458                      */
459                     t = LexToken(&p->p_Token);
460                     t = ParseStorageQual(p, t,
461                                          &tmp->ex_AuxFlags[0]);
462                 }
463                 if (t == TOK_COMMA) {
464                     /*
465                      * add storage qualifiers
466                      */
467                     t = LexToken(&p->p_Token);
468                     t = ParseStorageQual(p, t,
469                                          &tmp->ex_AuxFlags[1]);
470                 }
471 #endif
472                 /*
473                  * XXX why was this here? if (tmp->ex_Lhs) tmp->ex_Flags |=
474                  * EXF_UNARY;
475                  */
476                 pushValueExp(&opStack, &valStack, tmp);
477                 t = LexSkipToken(&p->p_Token, TOK_CPAREN);
478                 mode = 2;
479                 break;
480             case TOK_ID:        /* value: semantic id */
481             case TOK_CLASSID:   /* value: semantic id */
482                 pushValueId(p, &opStack, &valStack, t, p->p_Token.t_Id);
483                 t = LexToken(&p->p_Token);
484                 mode = 2;
485                 break;
486             case TOK_SELF:
487                 /*
488                  * Identifies the procedure's argument space.
489                  */
490                 pushValue(p, &opStack, &valStack, t);
491                 t = LexToken(&p->p_Token);
492                 mode = 2;
493                 break;
494             case TOK_DOLLAR:
495                 /*
496                  * Identifies the procedure's return storage.
497                  */
498                 pushValue(p, &opStack, &valStack, t);
499                 t = LexToken(&p->p_Token);
500                 mode = 2;
501                 break;
502             case TOK_CPAREN:    /* syntax error */
503             case TOK_CBRACE:    /* syntax error */
504             case TOK_COMMA:     /* syntax error */
505             case TOK_SEMI:      /* syntax error */
506             case TOK_COLON:     /* syntax error */
507             default:
508                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
509                 break;
510             }
511         } else {
512             /*
513              * BINARY
514              */
515             switch (t) {
516             case TOK_ASS:
517             case TOK_ANDAND:    /* binary operator */
518             case TOK_OROR:      /* binary operator */
519             case TOK_DOT:       /* binary operator */
520             case TOK_STRIND:    /* binary operator */
521             case TOK_OPER:      /* binary operator */
522                 /*
523                  * The lexer guarantees t_Id is set for all of these
524                  * cases.
525                  */
526                 pushOper(p, &opStack, &valStack, t,
527                          p->p_Token.t_Ptr, p->p_Token.t_Len, EXF_BINARY);
528                 t = LexToken(&p->p_Token);
529                 mode = 1;
530                 break;
531             case TOK_OBRACKET:  /* '[' array operator */
532                 t = LexToken(&p->p_Token);
533                 tmp = NULL;
534                 t = ParseExp(p, t, &tmp);
535                 t = LexSkipToken(&p->p_Token, TOK_CBRACKET);
536                 pushOper(p, &opStack, &valStack, TOK_OBRACKET,
537                          NULL, 0, EXF_BINARY);
538                 pushValueExp(&opStack, &valStack, tmp);
539                 break;
540             case TOK_CBRACKET:  /* ']' terminator */
541                 done = 1;
542                 break;
543             case TOK_OPAREN:
544                 /*
545                  * Procedure call.  In order to avoid fubar((x, y)) confusion
546                  * we do not allow ParseParenthesizedExp() to generate a
547                  * compound exp encapsulation for comma delimited case.
548                  * Instead we do it ourselves.
549                  */
550                 t = ParseParenthesizedExp(p, t, &tmp, 0);
551                 tmp = ExpToCompoundExp(tmp, TOK_COMPOUND);
552                 pushOper(p, &opStack, &valStack, TOK_CALL,
553                          NULL, 0, EXF_BINARY);
554                 pushValueExp(&opStack, &valStack, tmp);
555                 break;
556             case TOK_ID:        /* syntax error */
557             case TOK_CLASSID:   /* syntax error */
558                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX_MAYTYPE);
559                 break;
560             case TOK_DSTRING:   /* syntax error */
561             case TOK_SSTRING:   /* syntax error */
562             case TOK_BSTRING:   /* syntax error */
563             case TOK_INTEGER:   /* syntax error */
564             case TOK_FLOAT:     /* syntax error */
565             case TOK_SIZEOF:    /* syntax error */
566             case TOK_ARYSIZE:   /* syntax error */
567             case TOK_TYPEOF:    /* syntax error */
568             case TOK_SELF:      /* syntax error */
569                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
570                 break;
571             case TOK_CPAREN:    /* terminator */
572             case TOK_CBRACE:    /* terminator */
573             case TOK_COMMA:     /* terminator */
574             case TOK_SEMI:      /* terminator */
575             case TOK_COLON:     /* terminator */
576                 done = 1;
577                 break;
578             default:
579                 t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
580                 break;
581             }
582         }
583     }
584     while (opStack) {
585         if (popExp(&opStack, &valStack) < 0) {
586             t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
587         }
588     }
589     if (valStack == NULL) {
590         t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
591     } else if (valStack->ex_Next != NULL) {
592         t = LexError(&p->p_Token, TOK_ERR_EXP_SYNTAX);
593         FreeExp(valStack->ex_Next);
594         valStack->ex_Next = NULL;
595     }
596     *pexp = valStack;
597     return (t);
598 }
599
600 /*
601  * ParseParenthesizedExp() - parse a parenthesized expression.
602  *
603  * This will parse a parenthesized, possibly compound expression.  docomp
604  * determines whether the returned expression should be collapsed into
605  * TOK_COMPOUND when there is more then one element, or whether this should
606  * be left up to the caller.  Note that if you *REQUIRE* the result to be
607  * compound, you should pass docomp as 0 and call ExpToCompoundExp()
608  * unconditionally on the returned expression to avoid confusion.
609  *
610  * An empty expression returns a TOK_VOIDEXP exp node.
611  *
612  * NOTE: A single expressive element is considered to be compound if it is
613  * named.
614  */
615 int
616 ParseParenthesizedExp(Parse *p, int t, Exp **pexp, int docomp)
617 {
618     Exp    *tmp = NULL;
619
620     t = LexSkipToken(&p->p_Token, TOK_OPAREN);
621     if (t != TOK_CPAREN) {
622         Exp   **pnext = &tmp;
623         for (;;) {
624             runeid_t argId = 0;
625             if (t == TOK_ID || t == TOK_CLASSID /* XXX */ ) {
626                 /* lookahead */
627                 token_t t2 = p->p_Token;
628
629                 if (LexToken(&t2) == TOK_COLON) {
630                     argId = p->p_Token.t_Id;
631                     /* get the colon */
632                     LexToken(&p->p_Token);
633                     t = LexSkipToken(&p->p_Token, TOK_COLON);
634                 }
635             }
636             t = ParseExp(p, t, pnext);
637             if (*pnext) {
638                 (*pnext)->ex_ArgId = argId;
639                 pnext = &(*pnext)->ex_Next;
640             }
641             if (t != TOK_COMMA)
642                 break;
643             t = LexToken(&p->p_Token);
644         }
645     }
646     t = LexSkipToken(&p->p_Token, TOK_CPAREN);
647
648     /*
649      * Generate a non-compound expression for unnamed single-element
650      * parenthesized objects.  Set EX2F_WASCOMP in case the resolver wants to
651      * know what we need.
652      */
653     if (tmp) {
654         if (docomp && (tmp->ex_ArgId || tmp->ex_Next))
655             tmp = ExpToCompoundExp(tmp, TOK_COMPOUND);
656         else if (docomp)
657             tmp->ex_Flags2 |= EX2F_WASCOMP;
658     } else {
659         tmp = AllocExp(&p->p_Token);
660         tmp->ex_Token = TOK_VOIDEXP;
661     }
662     *pexp = tmp;
663     return (t);
664 }
665
666 /*
667  * ParseBracketedExp() - parse a bracketed expression.
668  *
669  * This parses an expression representing array elements.  The returned
670  * expression is collapsed into TOK_BRACKETED.
671  */
672 int
673 ParseBracketedExp(Parse *p, int t, Exp **pexp)
674 {
675     Exp    *tmp = NULL;
676
677     t = LexSkipToken(&p->p_Token, TOK_OBRACKET);
678     if (t != TOK_CBRACKET) {
679         Exp   **pnext = &tmp;
680         for (;;) {
681             t = ParseExp(p, t, pnext);
682             if (*pnext) {
683                 /* XXX use (*pnext)->ex_ArgId for index? */
684                 pnext = &(*pnext)->ex_Next;
685             }
686             if (t != TOK_COMMA)
687                 break;
688             t = LexToken(&p->p_Token);
689         }
690     }
691     t = LexSkipToken(&p->p_Token, TOK_CBRACKET);
692
693     /*
694      * Generate a non-compound expression for unnamed single-element
695      * parenthesized objects.  Set EX2F_WASCOMP in case the resolver wants to
696      * know what we need.
697      */
698     if (tmp) {
699         tmp = ExpToBracketedExp(tmp, TOK_BRACKETED);
700     } else {
701         tmp = AllocExp(&p->p_Token);
702         tmp->ex_Token = TOK_BRACKETED;
703     }
704     *pexp = tmp;
705
706     return (t);
707 }
708
709 int
710 ParseNotExp(Parse *p, int t, Exp **pexp)
711 {
712     t = ParseExp(p, t, pexp);
713     if ((t & TOKF_ERROR) == 0)
714         *pexp = ExpToNotExp(*pexp);
715     return (t);
716 }
717
718 static Exp *
719 pushOper(Parse *p, Exp **op, Exp **val, int t,
720          const char *sym, int len, int flags)
721 {
722     Exp     *exp;
723     int     prec;
724     int     rtl = 0;            /* right-to-left */
725     int     i;
726
727     if (flags & EXF_BINARY) {
728         prec = EXPREC_USER;
729
730         switch (t) {
731         case TOK_OPER:
732             /*
733              * EXPREC_PLUS      - contains '+', or '-'
734              * EXPREC_SHIFT     - begins '<<' or '>>'
735              * EXPREC_COMPARE   - not SHIFT and contains '<', '=', or '>'.
736              * EXPREC_ASS       - not COMPARE and ends with '='
737              *                    (also make right-to-left)
738              */
739             for (i = 0; i < len; ++i) {
740                 if (sym[i] == '+' || sym[i] == '-') {
741                     prec = EXPREC_PLUS;
742                     break;
743                 }
744             }
745             if (sym[0] == '<' && sym[1] == '<') {
746                 prec = EXPREC_SHIFT;
747             } else if (sym[0] == '>' && sym[1] == '>') {
748                 prec = EXPREC_SHIFT;
749             } else {
750                 for (i = 0; i < len; ++i) {
751                     if (sym[i] == '<' || sym[i] == '=' || sym[i] == '>') {
752                         prec = EXPREC_COMPARE;
753                         break;
754                     }
755                 }
756             }
757             if (prec != EXPREC_COMPARE && sym[len - 1] == '=') {
758                 prec = EXPREC_ASS;
759                 rtl = 1;
760             }
761             break;
762         case TOK_DOT:
763         case TOK_STRIND:
764             prec = EXPREC_DOT;
765             break;
766         case TOK_OBRACKET:
767             prec = EXPREC_CLOSURE;
768             break;
769         case TOK_CALL:
770             prec = EXPREC_CALL;
771             break;
772         case TOK_ANDAND:
773             prec = EXPREC_ANDAND;
774             break;
775         case TOK_ASS:
776             prec = EXPREC_ASS;
777             rtl = 1;
778             break;
779         case TOK_OROR:
780             prec = EXPREC_OROR;
781             break;
782         default:
783             dassert_parse(p, TOK_ERR_UNKNOWN, 0);
784         }
785     } else {
786         prec = EXPREC_UNARY;
787         rtl = 1;
788     }
789
790     /*
791      * Construct the expression
792      */
793     exp = AllocExp(&p->p_Token);
794     exp->ex_Prec = prec;
795     if (len)
796         exp->ex_Id = runeid_hash(sym, len);
797     exp->ex_Token = t;
798     exp->ex_Flags |= flags;
799
800     /*
801      * Pop-off any operators with a >= precedence.  Handle special
802      * right-to-left ordering for assignments and unary operators simply by
803      * delaying the pop.
804      */
805     while (*op) {
806         if ((*op)->ex_Prec > prec) {
807             popExp(op, val);
808             continue;
809         }
810         if (rtl == 0 && (*op)->ex_Prec == prec) {
811             popExp(op, val);
812             continue;
813         }
814         break;
815     }
816     exp->ex_Next = *op;
817     *op = exp;
818
819     return (exp);
820 }
821
822 static Exp *
823 pushValue(Parse *p, Exp **op __unused, Exp **val, int t)
824 {
825     Exp    *exp = AllocExp(&p->p_Token);
826
827     exp->ex_Token = t;
828     exp->ex_Next = *val;
829     *val = exp;
830
831     return (exp);
832 }
833
834 static Exp *
835 pushValueId(Parse *p, Exp **op __unused, Exp **val, int t, runeid_t id)
836 {
837     Exp    *exp = AllocExp(&p->p_Token);
838
839     exp->ex_Token = t;
840     exp->ex_Id = id;
841     exp->ex_Next = *val;
842     *val = exp;
843
844     return (exp);
845 }
846
847 static Exp *
848 pushValueStr(Parse *p, Exp **op __unused, Exp **val, int t, string_t str)
849 {
850     Exp    *exp = AllocExp(&p->p_Token);
851
852     exp->ex_Token = t;
853     exp->ex_Str = str;
854     exp->ex_Next = *val;
855     *val = exp;
856
857     return (exp);
858 }
859
860 static void
861 pushValueExp(Exp **op __unused, Exp **val, Exp *exp)
862 {
863     exp->ex_Next = *val;
864     *val = exp;
865 }
866
867 static int
868 popExp(Exp **op, Exp **val)
869 {
870     Exp    *exp;
871     int     r = 0;
872
873     if ((exp = *op) != NULL) {
874         if (exp->ex_Flags & EXF_BINARY) {
875             Exp    *rhs = *val;
876             Exp    *lhs = (rhs) ? rhs->ex_Next : NULL;
877
878             /*
879              * The expression parser will generate an error if this situation
880              * occurs so we can just return.
881              */
882             if (lhs && rhs) {
883                 *val = lhs->ex_Next;
884                 lhs->ex_Next = NULL;
885                 rhs->ex_Next = NULL;
886                 exp->ex_Lhs = lhs;
887                 exp->ex_Rhs = rhs;
888
889                 /*
890                  * Special handling.
891                  */
892                 switch (exp->ex_Token) {
893                 case TOK_DOT:
894                     /*
895                      * Lhs may be a type, class, module, or variable id.
896                      *
897                      * Rhs must be an identifier which we convert to
898                      * TOK_STRUCT_ID.
899                      */
900                     dassert_exp(rhs, rhs->ex_Token == TOK_ID ||
901                                 rhs->ex_Token == TOK_CLASSID);
902                     rhs->ex_Token = TOK_STRUCT_ID;
903                     break;
904                 case TOK_STRIND:
905                     /*
906                      * Lhs must an lvalue or rvalue (not checked), Rhs must
907                      * must be an identifier which we convert to
908                      * TOK_STRUCT_ID.
909                      */
910                     dassert_exp(rhs, rhs->ex_Token == TOK_ID ||
911                                 rhs->ex_Token == TOK_CLASSID);
912                     rhs->ex_Token = TOK_STRUCT_ID;
913                     break;
914                 case TOK_CALL:
915                     /*
916                      * The rhs of a procedure call is a compound expression,
917                      * denoted by TOK_COMPOUND.  The compound expression is
918                      * necessary to govern the context the arguments will
919                      * eventually be stored in, so we do not collapse this
920                      * even if its a void call.
921                      */
922                     dassert_exp(rhs, rhs->ex_Token == TOK_COMPOUND);
923 #if 0
924                     exp->ex_Rhs = rhs->ex_Lhs;
925                     rhs->ex_Lhs = NULL;
926                     FreeExp(rhs);
927                     rhs = NULL;
928 #endif
929                     break;
930                 case TOK_ANDAND:
931                 case TOK_OROR:
932                 default:
933                     break;
934                 }
935             } else {
936                 r = -1;
937             }
938         } else {
939             Exp    *lhs = *val;
940
941             if (lhs) {
942                 exp->ex_Lhs = lhs;
943                 *val = lhs->ex_Next;
944                 lhs->ex_Next = NULL;
945             } else {
946                 r = -1;
947             }
948         }
949         *op = exp->ex_Next;
950         exp->ex_Next = *val;
951         *val = exp;
952     }
953     return (r);
954 }