]> git.sur5r.net Git - cc65/blob - src/cc65/parser.c
62aedd667d4896c2d71c68abbd23522ab0004d6c
[cc65] / src / cc65 / parser.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 parser.c                                  */
4 /*                                                                           */
5 /*                             Expression parser                             */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000      Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@musoftware.de                                            */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 /* common */
41 #include "check.h"
42 #include "xmalloc.h"
43
44 /* cc65 */
45 #include "datatype.h"
46 #include "declare.h"
47 #include "error.h"
48 #include "exprheap.h"
49 #include "funcdesc.h"
50 #include "function.h"
51 #include "global.h"
52 #include "litpool.h"
53 #include "macrotab.h"
54 #include "preproc.h"
55 #include "scanner.h"
56 #include "stdfunc.h"
57 #include "symtab.h"
58 #include "typecmp.h"
59 #include "parser.h"
60
61
62
63 /*****************************************************************************/
64 /*                                 Forwards                                  */
65 /*****************************************************************************/
66
67
68
69 static ExprNode* UnaryExpr (void);
70 ExprNode* AssignExpr (void);
71 ExprNode* Expression (void);
72
73
74
75 /*****************************************************************************/
76 /*                             Helper functions                              */
77 /*****************************************************************************/
78
79
80
81 static int IsTypeExpr (void)
82 /* Return true if some sort of variable or type is waiting (helper for cast
83  * and sizeof() in hie10).
84  */
85 {
86     SymEntry* Entry;
87
88     return CurTok.Tok == TOK_LPAREN && (
89             (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
90             (nxttok == TOK_CONST)                               ||
91             (nxttok  == TOK_IDENT                               &&
92             (Entry = FindSym (NextTok.Ident)) != 0              &&
93             IsTypeDef (Entry))
94            );
95 }
96
97
98
99 /*****************************************************************************/
100 /*                     Expression node helper functions                      */
101 /*****************************************************************************/
102
103
104
105 static ExprNode* GetIntNode (int Value)
106 /* Allocate a new expression node from the tree, make it a valid integer
107  * node and return it. Often used if an error occurs to get a safe expression
108  * tree.
109  */
110 {
111     ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
112     N->V.I = Value;
113     return N;
114 }
115
116
117
118 /*****************************************************************************/
119 /*                                   Code                                    */
120 /*****************************************************************************/
121
122
123
124 ExprNode* DoAsm (void)
125 /* This function parses ASM statements. The syntax of the ASM directive
126  * looks like the one defined for C++ (C has no ASM directive), that is,
127  * a string literal in parenthesis.
128  */
129 {
130     ExprNode* N;
131
132
133     /* Skip the ASM */
134     NextToken ();
135
136     /* Need left parenthesis */
137     ConsumeLParen ();
138
139     /* Create a new expression node and assign a void type */
140     N = AllocExprNode (NT_ASM, type_void, RVALUE);
141
142     /* String literal */
143     if (CurTok.Tok != TOK_SCONST) {
144
145         /* Print an error */
146         Error (ERR_STRLIT_EXPECTED);
147
148         /* To be on the safe side later, insert an empty asm string */
149         AppendItem (N, xstrdup (""));
150
151     } else {
152
153         /* Insert a copy of the string into the expression node */
154         AppendItem (N, xstrdup (GetLiteral (curval)));
155
156         /* Reset the string pointer, effectivly clearing the string from the
157          * string table. Since we're working with one token lookahead, this
158          * will fail if the next token is also a string token, but that's a
159          * syntax error anyway, because we expect a right paren.
160          */
161         ResetLiteralOffs (curval);
162     }
163
164     /* Skip the string token */
165     NextToken ();
166
167     /* Closing paren needed */
168     ConsumeRParen ();
169
170     /* Return the created node */
171     return N;
172 }
173
174
175
176 static ExprNode* Primary (void)
177 /* Evaluate a primary expression */
178 {
179     ExprNode* N;
180
181     /* Process a parenthesized subexpression. In this case we don't need to
182      * allocate a new node ourselves.
183      */
184     if (CurTok.Tok == TOK_LPAREN) {
185         NextToken ();
186         N = Expression ();
187         ConsumeRParen ();
188         return N;
189     }
190
191     /* Check for an integer or character constant */
192     if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
193
194         /* Create the new node */
195         N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
196         N->V.I = CurTok.IVal;
197
198         /* Skip the token and return the result */
199         NextToken ();
200         return N;
201     }
202
203     /* Check for a float constant */
204     if (CurTok.Tok == TOK_FCONST) {
205
206         /* Create the new node */
207         N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
208         N->V.F = CurTok.FVal;
209
210         /* Skip the token and return the result */
211         NextToken ();
212         return N;
213     }
214
215     /* All others may only be used if the expression evaluation is not called
216      * recursively by the preprocessor.
217      */
218     if (Preprocessing) {
219         /* Illegal expression in PP mode */
220         Error (ERR_CPP_EXPR_EXPECTED);
221
222         /* Skip the token for error recovery */
223         NextToken ();
224
225         /* Return an integer constant */
226         return GetIntNode (0);
227     }
228
229     /* Identifier? */
230     if (CurTok.Tok == TOK_IDENT) {
231
232         /* Identifier */
233         SymEntry* Sym;
234         ident Ident;
235
236         /* Get a pointer to the symbol table entry */
237         Sym = FindSym (CurTok.Ident);
238
239         /* Is the symbol known? */
240         if (Sym) {
241
242             /* We found the symbol - skip the name token */
243             NextToken ();
244
245             /* Check for illegal symbol types */
246             if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
247                 /* Cannot use labels in expressions */
248                 Error (ERR_SYMBOL_KIND);
249                 return GetIntNode (0);
250             } else if (Sym->Flags & SC_TYPE) {
251                 /* Cannot use type symbols */
252                 Error (ERR_VAR_IDENT_EXPECTED);
253                 /* Assume an int type to make lval valid */
254                 return GetIntNode (0);
255             }
256
257             /* Handle enum values as constant integers */
258             if ((Sym->Flags & SC_ENUM) == SC_ENUM) {
259
260                 N = GetIntNode (Sym->V.EnumVal);
261
262             } else {
263
264                 /* All symbols besides functions and arrays are lvalues */
265                 int LVal = (!IsTypeFunc (Sym->Type) && !IsTypeArray (Sym->Type));
266
267                 /* Create the node */
268                 N = AllocExprNode (NT_SYM, Sym->Type, LVal);
269
270                 /* Set the symbol pointer */
271                 SetNodeSym (N, Sym);
272             }
273
274             /* The symbol is referenced now */
275             Sym->Flags |= SC_REF;
276
277         } else {
278
279             /* We did not find the symbol. Remember the name, then skip it */
280             strcpy (Ident, CurTok.Ident);
281             NextToken ();
282
283             /* IDENT is either an auto-declared function or an undefined
284              * variable.
285              */
286             if (CurTok.Tok == TOK_LPAREN) {
287
288                 /* Warn about the use of a function without prototype */
289                 Warning (WARN_FUNC_WITHOUT_PROTO);
290
291                 /* Declare a function returning int. For that purpose, prepare
292                  * a function signature for a function having an empty param
293                  * list and returning int.
294                  */
295                 Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
296                 N   = AllocExprNode (NT_SYM, Sym->Type, RVALUE);
297                 SetNodeSym (N, Sym);
298
299             } else {
300
301                 /* Print an error about an undeclared variable */
302                 Error (ERR_UNDEFINED_SYMBOL, Ident);
303
304                 /* Undeclared Variable */
305                 Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
306                 N   = AllocExprNode (NT_SYM, Sym->Type, LVALUE);
307                 SetNodeSym (N, Sym);
308
309             }
310
311         }
312
313     } else if (CurTok.Tok == TOK_SCONST) {
314
315         /* String literal */
316         N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (curval))), RVALUE);
317         N->V.I = curval;
318
319     } else if (CurTok.Tok == TOK_ASM) {
320
321         /* ASM statement? */
322         N = DoAsm ();
323
324     } else if (CurTok.Tok == TOK_A) {
325
326         /* A register */
327         N = AllocExprNode (NT_REG_A, type_uchar, LVALUE);
328
329     } else if (CurTok.Tok == TOK_X) {
330
331         /* X register */
332         N = AllocExprNode (NT_REG_X, type_uchar, LVALUE);
333
334     } else if (CurTok.Tok == TOK_Y) {
335
336         /* Y register */
337         N = AllocExprNode (NT_REG_Y, type_uchar, LVALUE);
338
339     } else if (CurTok.Tok == TOK_AX) {
340
341         /* AX pseudo register */
342         N = AllocExprNode (NT_REG_AX, type_uint, LVALUE);
343
344     } else if (CurTok.Tok == TOK_EAX) {
345
346         /* EAX pseudo register */
347         N = AllocExprNode (NT_REG_EAX, type_ulong, LVALUE);
348
349     } else {
350
351         /* Illegal primary. */
352         Error (ERR_EXPR_EXPECTED);
353         N = GetIntNode (0);
354
355     }
356
357     /* Return the new node */
358     return N;
359 }
360
361
362
363 static ExprNode* DoArray (ExprNode* Left)
364 /* Handle arrays */
365 {
366     ExprNode* Right;
367     ExprNode* Root;
368     type*     ElementType;
369
370
371     /* Skip the bracket */
372     NextToken ();
373
374     /* Get the index */
375     Right = Expression ();
376
377     /* Check the types. As special "C" feature, accept a reversal of base and
378      * index types:
379      *   char C = 3["abcdefg"];
380      * is legal C!
381      */
382     if (IsClassPtr (Left->Type)) {
383         /* Right side must be some sort of integer */
384         if (!IsClassInt (Right->Type)) {
385             /* Print an error */
386             Error (ERR_CANNOT_SUBSCRIPT);
387             /* To avoid problems later, create a new, legal subscript
388              * expression
389              */
390             Right = GetIntNode (0);
391         }
392     } else if (IsClassPtr (Right->Type)) {
393
394         ExprNode* Tmp;
395
396         /* Left side must be some sort of integer */
397         if (!IsClassInt (Right->Type)) {
398             /* Print an error */
399             Error (ERR_CANNOT_SUBSCRIPT);
400             /* To avoid problems later, create a new, legal subscript
401              * expression
402              */
403             Left = GetIntNode (0);
404         }
405
406         /* Swap the expression to it's normal form */
407         Tmp   = Right;
408         Right = Left;
409         Left  = Tmp;
410
411     } else {
412         /* Invalid array expression. Skip the closing bracket, then return
413          * an integer instead of the array expression to be safe later.
414          */
415         Error (ERR_CANNOT_SUBSCRIPT);
416         ConsumeRBrack ();
417         return GetIntNode (0);
418     }
419
420     /* Skip the right bracket */
421     ConsumeRBrack ();
422
423     /* Get the type of the array elements */
424     ElementType = Indirect (Left->Type);
425
426     /* Allocate the branch node for the array expression */
427     Root = AllocExprNode (NT_ARRAY_SUBSCRIPT,
428                           ElementType,
429                           IsTypeArray (ElementType)? RVALUE : LVALUE);
430
431     /* Setup the branches */
432     SetLeftNode (Root, Left);
433     SetRightNode (Root, Right);
434
435     /* ...and return it */
436     return Root;
437 }
438
439
440
441 static ExprNode* DoStruct (ExprNode* Left)
442 /* Process struct field access */
443 {
444     nodetype_t  NT;
445     ident       Ident;
446     type*       StructType;
447     ExprNode*   Right;
448     ExprNode*   Root;
449     SymEntry*   Field;
450
451
452     /* Type check */
453     StructType = Left->Type;
454     if (CurTok.Tok == TOK_PTR_REF) {
455         NT = NT_STRUCTPTR_ACCESS;
456         if (!IsTypePtr (StructType)) {
457             Error (ERR_STRUCT_PTR_EXPECTED);
458             return GetIntNode (0);
459         }
460         StructType = Indirect (StructType);
461     } else {
462         NT = NT_STRUCT_ACCESS;
463     }
464     if (!IsClassStruct (StructType)) {
465         Error (ERR_STRUCT_EXPECTED);
466         return GetIntNode (0);
467     }
468
469     /* Skip the token and check for an identifier */
470     NextToken ();
471     if (CurTok.Tok != TOK_IDENT) {
472         /* Print an error */
473         Error (ERR_IDENT_EXPECTED);
474         /* Return an integer expression instead */
475         return GetIntNode (0);
476     }
477
478     /* Get the symbol table entry and check for a struct field */
479     strcpy (Ident, CurTok.Ident);
480     NextToken ();
481     Field = FindStructField (StructType, Ident);
482     if (Field == 0) {
483         /* Struct field not found */
484         Error (ERR_STRUCT_FIELD_MISMATCH, Ident);
485         /* Return an integer expression instead */
486         return GetIntNode (0);
487     }
488
489     /* Allocate and set up the right (== field) node */
490     Right = AllocExprNode (NT_SYM, Field->Type, RVALUE);
491     SetNodeSym (Right, Field);
492
493     /* Allocate the branch node for the resulting expression */
494     Root = AllocExprNode (NT, Right->Type,
495                           IsTypeArray (Right->Type)? RVALUE : LVALUE);
496
497     /* Setup the branches */
498     SetLeftNode (Root, Left);
499     SetRightNode (Root, Right);
500
501     /* ...and return it */
502     return Root;
503 }
504
505
506
507 static ExprNode* DoFunctionCall (ExprNode* Left)
508 /* Process a function call */
509 {
510     type*       ResultType;     /* Type of function result */
511     FuncDesc*   Func;           /* Function descriptor */
512     ExprNode*   Root;           /* Function call node */
513     int         Ellipsis;       /* True if we have an open param list */
514     SymEntry*   Param;          /* Current formal parameter */
515     unsigned    ParamCount;     /* Actual parameter count */
516     unsigned    ParamSize;      /* Number of parameter bytes */
517
518
519     /* Type check */
520     if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
521
522         /* Call to non function */
523         Error (ERR_ILLEGAL_FUNC_CALL);
524
525         /* Free the old node */
526         FreeExprNode (Left);
527
528         /* Return something safe */
529         return GetIntNode (0);
530     }
531
532     /* Get the type of the function result */
533     ResultType = Left->Type;
534     if (IsTypeFuncPtr (Left->Type)) {
535         ++ResultType;
536     }
537     ResultType += DECODE_SIZE + 1;      /* Set to result type */
538
539     /* Skip the opening parenthesis */
540     NextToken ();
541
542     /* Allocate the function call node */
543     Root = AllocExprNode (NT_FUNCTION_CALL, ResultType, RVALUE);
544
545     /* Get a pointer to the function descriptor from the type string */
546     Func = GetFuncDesc (Left->Type);
547
548     /* Initialize vars to keep gcc silent */
549     Param = 0;
550
551     /* Parse the parameter list */
552     ParamSize  = 0;
553     ParamCount = 0;
554     Ellipsis   = 0;
555     while (CurTok.Tok != TOK_RPAREN) {
556
557         /* Count arguments */
558         ++ParamCount;
559
560         /* Fetch the pointer to the next argument, check for too many args */
561         if (ParamCount <= Func->ParamCount) {
562             if (ParamCount == 1) {
563                 /* First argument */
564                 Param = Func->SymTab->SymHead;
565             } else {
566                 /* Next argument */
567                 Param = Param->NextSym;
568                 CHECK ((Param->Flags & SC_PARAM) != 0);
569             }
570         } else if (!Ellipsis) {
571             /* Too many arguments. Do we have an open param list? */
572             if ((Func->Flags & FD_ELLIPSIS) == 0) {
573                 /* End of param list reached, no ellipsis */
574                 Error (ERR_TOO_MANY_FUNC_ARGS);
575             }
576             /* Assume an ellipsis even in case of errors to avoid an error
577              * message for each other argument.
578              */
579             Ellipsis = 1;
580         }
581
582         /* Get the parameter value expression tree and add it to the parameter
583          * list.
584          */
585         AppendItem (Root, AssignExpr ());
586
587         /* Check for end of argument list */
588         if (CurTok.Tok != TOK_COMMA) {
589             break;
590         }
591         NextToken ();
592     }
593
594     /* We need the closing bracket here */
595     ConsumeRParen ();
596
597     /* Check if we had enough parameters */
598     if (ParamCount < Func->ParamCount) {
599         Error (ERR_TOO_FEW_FUNC_ARGS);
600     }
601
602     /* Return the function call node */
603     return Root;
604 }
605
606
607
608 static ExprNode* DoPostIncDec (ExprNode* Left)
609 /* Handle postincrement and postdecrement */
610 {
611     ExprNode* Root;
612
613     /* Determine the type of the node */
614     nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
615
616     /* Skip the operator token */
617     NextToken ();
618
619     /* The operand must be an lvalue */
620     if (Left->LValue == 0) {
621
622         /* Print a diagnostics */
623         Error (ERR_LVALUE_EXPECTED);
624
625         /* It is safe to return the operand expression and probably better
626          * than returning an int, since the operand expression already has
627          * the correct type as expected by the program at this place, and
628          * it is even an rvalue.
629          */
630         return Left;
631     }
632
633     /* Setup the expression tree */
634     Root = AllocExprNode (NT, Left->Type, RVALUE);
635     SetLeftNode (Root, Left);
636
637     /* Return the new node */
638     return Root;
639 }
640
641
642
643 static ExprNode* PostfixExpr (void)
644 {
645     /* Get the lower level expression */
646     ExprNode* Root = Primary ();
647
648     /* */
649     while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN  ||
650            CurTok.Tok == TOK_DOT    || CurTok.Tok == TOK_PTR_REF ||
651            CurTok.Tok == TOK_INC    || CurTok.Tok == TOK_DEC) {
652
653         /* This is for us */
654         switch (CurTok.Tok) {
655
656             case TOK_LBRACK:
657                 Root = DoArray (Root);
658                 break;
659
660             case TOK_LPAREN:
661                 Root = DoFunctionCall (Root);
662                 break;
663
664             case TOK_DOT:
665             case TOK_PTR_REF:
666                 Root = DoStruct (Root);
667                 break;
668
669             case TOK_INC:
670             case TOK_DEC:
671                 Root = DoPostIncDec (Root);
672                 break;
673
674             default:
675                 Internal ("Unexpected token");
676
677         }
678     }
679
680     /* Return the result */
681     return Root;
682 }
683
684
685
686 static ExprNode* DoPreIncDec (void)
687 /* Handle preincrement and predecrement */
688 {
689     ExprNode* Op;
690     ExprNode* Root;
691
692     /* Determine the type of the node */
693     nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
694
695     /* Skip the operator token */
696     NextToken ();
697
698     /* Get the expression to increment or decrement */
699     Op = UnaryExpr ();
700
701     /* The operand must be an lvalue */
702     if (Op->LValue == 0) {
703
704         /* Print a diagnostics */
705         Error (ERR_LVALUE_EXPECTED);
706
707         /* It is safe to return the operand expression and probably better
708          * than returning an int, since the operand expression already has
709          * the correct type as expected by the program at this place, and
710          * it is even an rvalue.
711          */
712         return Op;
713     }
714
715     /* Setup the expression tree */
716     Root = AllocExprNode (NT, Op->Type, RVALUE);
717     SetLeftNode (Root, Op);
718
719     /* Return the new node */
720     return Root;
721 }
722
723
724
725 static ExprNode* DoUnaryPlusMinus (void)
726 /* Handle unary +/- */
727 {
728     ExprNode* Op;
729     ExprNode* Root;
730
731     /* Remember the current token for later, then skip it */
732     token_t Tok = CurTok.Tok;
733     NextToken ();
734
735     /* Get the operand */
736     Op = UnaryExpr ();
737
738     /* Type check */
739     if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
740
741         /* Display diagnostic */
742         Error (ERR_SYNTAX);
743
744         /* Free the errorneous node */
745         FreeExprNode (Op);
746
747         /* Return something that makes sense later */
748         return GetIntNode (0);
749     }
750
751     /* In case of PLUS, we must do nothing */
752     if (Tok == TOK_PLUS) {
753
754         /* Return the operand unchanged */
755         return Op;
756
757     } else if (Op->NT == NT_CONST) {
758
759         /* The value is constant, change it according to the insn */
760         if (IsClassInt (Op->Type)) {
761             /* Integer */
762             Op->V.I = -Op->V.I;
763         } else {
764             /* Float */
765             Op->V.F = -Op->V.F;
766         }
767
768         /* Return the operand itself */
769         return Op;
770
771     } else {
772
773         /* Non constant value, setup the expression tree */
774         Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
775         SetLeftNode (Root, Op);
776
777     }
778
779     /* Return the new node */
780     return Root;
781 }
782
783
784
785 static ExprNode* DoComplement (void)
786 /* Handle ~ */
787 {
788     ExprNode* Op;
789     ExprNode* Root;
790
791     /* Skip the operator token */
792     NextToken ();
793
794     /* Get the operand */
795     Op = UnaryExpr ();
796
797     /* Type check */
798     if (!IsClassInt (Op->Type)) {
799
800         /* Display diagnostic */
801         Error (ERR_OP_NOT_ALLOWED);
802
803         /* Free the errorneous node */
804         FreeExprNode (Op);
805
806         /* Return something that makes sense later */
807         return GetIntNode (0);
808     }
809
810     /* If the operand is constant, handle the operation directly */
811     if (Op->NT == NT_CONST) {
812
813         /* Change the value and return the operand node */
814         Op->V.I = ~Op->V.I;
815         return Op;
816
817     } else {
818
819         /* Setup the expression tree and return the new node */
820         Root = AllocExprNode (NT_COMPLEMENT, Op->Type, RVALUE);
821         SetLeftNode (Root, Op);
822         return Root;
823     }
824 }
825
826
827
828 static ExprNode* DoBoolNot (void)
829 /* Handle ! */
830 {
831     ExprNode* Op;
832     ExprNode* Root;
833
834     /* Skip the operator token */
835     NextToken ();
836
837     /* Get the operand */
838     Op = UnaryExpr ();
839
840     /* The boolean NOT operator eats anything - no need for a type check. */
841
842     /* Setup the expression tree and return the new node */
843     Root = AllocExprNode (NT_BOOL_NOT, type_int, RVALUE);
844     SetLeftNode (Root, Op);
845     return Root;
846 }
847
848
849
850 static ExprNode* DoAddress (void)
851 /* Handle the address operator & */
852 {
853     ExprNode* Op;
854
855     /* Skip the operator */
856     NextToken ();
857
858     /* Get the operand */
859     Op = UnaryExpr ();
860
861     /* Accept using the address operator with arrays. This is harmless, it
862      * will just be as using the array without the operator.
863      */
864     if (IsTypeArray (Op->Type)) {
865         return Op;
866     }
867
868     /* We cannot operate on rvalues */
869     if (Op->LValue == 0) {
870
871         ExprNode* Root;
872
873         /* Print diagnostics */
874         Error (ERR_ILLEGAL_ADDRESS);
875
876         /* Free the problematic node */
877         FreeExprNode (Op);
878
879         /* Return something that is safe later */
880         Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
881         Root->V.I = 0;
882         return Root;
883
884     }
885
886     /* Create the operator node and return it */
887     return AllocExprNode (NT_ADDRESS, PointerTo (Op->Type), RVALUE);
888 }
889
890
891
892 static ExprNode* DoIndirect (void)
893 /* Handle the indirection operaror * */
894 {
895     ExprNode* Op;
896     type*     ResultType;
897     int       LVal;
898
899     /* Skip the operator */
900     NextToken ();
901
902     /* Get the operand */
903     Op = UnaryExpr ();
904
905     /* Type check */
906     if (!IsClassPtr (Op->Type)) {
907
908         /* Print diagnostics */
909         Error (ERR_ILLEGAL_INDIRECT);
910
911         /* Free the problematic node */
912         FreeExprNode (Op);
913
914         /* Return something that is safe later ### */
915         return GetIntNode (0);
916
917     }
918
919     /* Get the type of the result */
920     ResultType = Indirect (Op->Type);
921
922     /* The result is an lvalue if it is not an array */
923     LVal = IsTypeArray (ResultType)? RVALUE : LVALUE;
924
925     /* Create the operator node and return it */
926     return AllocExprNode (NT_INDIRECT, ResultType, LVal);
927 }
928
929
930
931 static ExprNode* DoSizeOf (void)
932 /* Handle the sizeof operator */
933 {
934     ExprNode*     N;
935     unsigned long Size;
936
937     /* Skip the left paren */
938     NextToken ();
939
940     /* A type or an actual variable access may follow */
941     if (IsTypeExpr ()) {
942
943         type    Type[MAXTYPELEN];
944
945         /* A type in parenthesis. Skip the left paren. */
946         NextToken ();
947
948         /* Read the type and calculate the size. */
949         Size = SizeOf (ParseType (Type));
950
951         /* Closing paren must follow */
952         ConsumeRParen ();
953
954     } else {
955
956         /* Some other entity */
957         N = UnaryExpr ();
958
959         /* Get the size */
960         Size = SizeOf (N->Type);
961
962         /* Free the node */
963         FreeExprNode (N);
964
965     }
966
967     /* Create a constant node with type size_t and return it */
968     N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
969     N->V.I = Size;
970     return N;
971 }
972
973
974
975 static ExprNode* DoTypeCast (void)
976 /* Handle type casts */
977 {
978     type      TargetType[MAXTYPELEN];
979     ExprNode* Op;
980     ExprNode* Root;
981
982     /* Skip the left paren */
983     NextToken ();
984
985     /* Read the type */
986     ParseType (TargetType);
987
988     /* Closing paren */
989     ConsumeRParen ();
990
991     /* Read the expression we have to cast */
992     Op = UnaryExpr ();
993
994     /* As a minor optimization, check if the type is already correct. If so,
995      * do nothing.
996      */
997     if (TypeCmp (TargetType, Op->Type) >= TC_EQUAL) {
998
999         /* Just return the operand as is */
1000         return Op;
1001
1002     } else {
1003
1004         /* Must be casted. Setup the expression tree and return the new node */
1005         Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
1006         SetLeftNode (Root, Op);
1007         return Root;
1008
1009     }
1010 }
1011
1012
1013
1014 static ExprNode* UnaryExpr (void)
1015 {
1016     /* */
1017     if (CurTok.Tok == TOK_INC    || CurTok.Tok == TOK_DEC      ||
1018         CurTok.Tok == TOK_PLUS   || CurTok.Tok == TOK_MINUS    ||
1019         CurTok.Tok == TOK_COMP   || CurTok.Tok == TOK_BOOL_NOT ||
1020         CurTok.Tok == TOK_AND    || CurTok.Tok == TOK_STAR     ||
1021         CurTok.Tok == TOK_SIZEOF || IsTypeExpr ()) {
1022
1023         /* Check the token */
1024         switch (CurTok.Tok) {
1025
1026             case TOK_INC:
1027             case TOK_DEC:
1028                 return DoPreIncDec ();
1029
1030             case TOK_PLUS:
1031             case TOK_MINUS:
1032                 return DoUnaryPlusMinus ();
1033
1034             case TOK_COMP:
1035                 return DoComplement ();
1036
1037             case TOK_BOOL_NOT:
1038                 return DoBoolNot ();
1039
1040             case TOK_AND:
1041                 return DoAddress ();
1042
1043             case TOK_STAR:
1044                 return DoIndirect ();
1045
1046             case TOK_SIZEOF:
1047                 return DoSizeOf ();
1048
1049             default:
1050                 /* Type cast */
1051                 return DoTypeCast ();
1052
1053         }
1054
1055     } else {
1056
1057         /* Call the lower level */
1058         return PostfixExpr ();
1059
1060     }
1061 }
1062
1063
1064
1065 static ExprNode* MultExpr (void)
1066 /* Handle multiplicative expressions: '*' '/' and '%' */
1067 {
1068     /* Get the left leave */
1069     ExprNode* Root = UnaryExpr ();
1070
1071     /* Check if this is for us */
1072     while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV || CurTok.Tok == TOK_MOD) {
1073
1074         switch (CurTok.Tok) {
1075
1076             case TOK_MUL:
1077                 break;
1078
1079             case TOK_DIV:
1080                 break;
1081
1082             case TOK_MOD:
1083                 break;
1084
1085             default:
1086                 Internal ("Unexpected token");
1087         }
1088
1089     }
1090
1091     /* Return the resulting expression */
1092     return Root;
1093 }
1094
1095
1096
1097 static ExprNode* AddExpr (void)
1098 /* Handle additive expressions: '+' and '-' */
1099 {
1100     /* Get the left leave */
1101     ExprNode* Root = MultExpr ();
1102
1103     /* Check if this is for us */
1104     while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
1105
1106         switch (CurTok.Tok) {
1107
1108             case TOK_PLUS:
1109                 break;
1110
1111             case TOK_MINUS:
1112                 break;
1113
1114             default:
1115                 Internal ("Unexpected token");
1116         }
1117
1118     }
1119
1120     /* Return the resulting expression */
1121     return Root;
1122 }
1123
1124
1125
1126 static ExprNode* ShiftExpr (void)
1127 /* Handle shift expressions: '<<' and '>>' */
1128 {
1129     /* Get the left leave */
1130     ExprNode* Root = AddExpr ();
1131
1132     /* Check if this is for us */
1133     while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
1134
1135         switch (CurTok.Tok) {
1136
1137             case TOK_SHL:
1138                 break;
1139
1140             case TOK_SHR:
1141                 break;
1142
1143             default:
1144                 Internal ("Unexpected token");
1145         }
1146
1147     }
1148
1149     /* Return the resulting expression */
1150     return Root;
1151 }
1152
1153
1154
1155 static ExprNode* RelationalExpr (void)
1156 /* Handle relational expressions: '<=', '<', '>=' and '>' */
1157 {
1158     /* Get the left leave */
1159     ExprNode* Root = ShiftExpr ();
1160
1161     /* Check if this is for us */
1162     while (CurTok.Tok == TOK_LE || CurTok.Tok == TOK_LT ||
1163            CurTok.Tok == TOK_GE || CurTok.Tok == TOK_GT) {
1164
1165         switch (CurTok.Tok) {
1166
1167             case TOK_LE:
1168                 break;
1169
1170             case TOK_LT:
1171                 break;
1172
1173             case TOK_GE:
1174                 break;
1175
1176             case TOK_GT:
1177                 break;
1178
1179             default:
1180                 Internal ("Unexpected token");
1181         }
1182
1183     }
1184
1185     /* Return the resulting expression */
1186     return Root;
1187 }
1188
1189
1190
1191 static ExprNode* EqualityExpr (void)
1192 /* Handle equality expressions: '==' and '!=' */
1193 {
1194     /* Get the left leave */
1195     ExprNode* Root = RelationalExpr ();
1196
1197     /* Check if this is for us */
1198     while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE) {
1199
1200         switch (CurTok.Tok) {
1201
1202             case TOK_EQ:
1203                 break;
1204
1205             case TOK_NE:
1206                 break;
1207
1208             default:
1209                 Internal ("Unexpected token");
1210         }
1211
1212     }
1213
1214     /* Return the resulting expression */
1215     return Root;
1216 }
1217
1218
1219
1220 static ExprNode* AndExpr (void)
1221 /* Handle and expressions: '&' */
1222 {
1223     /* Get the left leave */
1224     ExprNode* Root = EqualityExpr ();
1225
1226     /* Check if this is for us */
1227     while (CurTok.Tok == TOK_AND) {
1228
1229         switch (CurTok.Tok) {
1230
1231             case TOK_AND:
1232                 break;
1233
1234             default:
1235                 Internal ("Unexpected token");
1236         }
1237
1238     }
1239
1240     /* Return the resulting expression */
1241     return Root;
1242 }
1243
1244
1245
1246 static ExprNode* XorExpr (void)
1247 /* Handle xor expressions: '^' */
1248 {
1249     /* Get the left leave */
1250     ExprNode* Root = AndExpr ();
1251
1252     /* Check if this is for us */
1253     while (CurTok.Tok == TOK_XOR) {
1254
1255         switch (CurTok.Tok) {
1256
1257             case TOK_XOR:
1258                 break;
1259
1260             default:
1261                 Internal ("Unexpected token");
1262         }
1263
1264     }
1265
1266     /* Return the resulting expression */
1267     return Root;
1268 }
1269
1270
1271
1272 static ExprNode* OrExpr (void)
1273 /* Handle or expressions: '|' */
1274 {
1275     /* Get the left leave */
1276     ExprNode* Root = XorExpr ();
1277
1278     /* Check if this is for us */
1279     while (CurTok.Tok == TOK_OR) {
1280
1281         switch (CurTok.Tok) {
1282
1283             case TOK_OR:
1284                 break;
1285
1286             default:
1287                 Internal ("Unexpected token");
1288         }
1289
1290     }
1291
1292     /* Return the resulting expression */
1293     return Root;
1294 }
1295
1296
1297
1298 static ExprNode* BoolAndExpr (void)
1299 /* Handle boolean and expressions: '&&' */
1300 {
1301     /* Get the left leave */
1302     ExprNode* Root = OrExpr ();
1303
1304     /* Check if this is for us */
1305     while (CurTok.Tok == TOK_BOOL_AND) {
1306
1307         switch (CurTok.Tok) {
1308
1309             case TOK_BOOL_AND:
1310                 break;
1311
1312             default:
1313                 Internal ("Unexpected token");
1314         }
1315
1316     }
1317
1318     /* Return the resulting expression */
1319     return Root;
1320 }
1321
1322
1323
1324 static ExprNode* BoolOrExpr (void)
1325 /* Handle boolean or expressions: '||' */
1326 {
1327     /* Get the left leave */
1328     ExprNode* Root = BoolAndExpr ();
1329
1330     /* Check if this is for us */
1331     while (CurTok.Tok == TOK_BOOL_OR) {
1332
1333         switch (CurTok.Tok) {
1334
1335             case TOK_BOOL_OR:
1336                 break;
1337
1338             default:
1339                 Internal ("Unexpected token");
1340         }
1341
1342     }
1343
1344     /* Return the resulting expression */
1345     return Root;
1346 }
1347
1348
1349
1350 static ExprNode* ConditionalExpr (void)
1351 /* Handle the ternary operator: ':?' */
1352 {
1353     /* Get the left leave */
1354     ExprNode* Cond = BoolOrExpr ();
1355
1356     /* Check if this is for us */
1357     if (CurTok.Tok == TOK_QUEST) {
1358
1359         ExprNode* Expr1;
1360         ExprNode* Expr2;
1361         ExprNode* Root;
1362         type*     Type;
1363
1364
1365         /* Skip the token */
1366         NextToken ();
1367
1368         /* Get the first expression */
1369         Expr1 = Expression ();
1370
1371         /* Colon must follow */
1372         ConsumeColon ();
1373
1374         /* Get the second expression */
1375         Expr2 = ConditionalExpr ();
1376
1377         /* Get the common type of the two expressions */
1378         Type = CommonType (Expr1->Type, Expr2->Type);
1379
1380         /* Create a new ternary token node */
1381         Root = AllocExprNode (NT_TERNARY, Type, RVALUE);
1382         AppendItem (Root, Cond);
1383         AppendItem (Root, Expr1);
1384         AppendItem (Root, Expr2);
1385                                  
1386         /* Return the result */
1387         return Root;
1388
1389     } else {
1390
1391         /* Just return the lower level expression */
1392         return Cond;
1393
1394     }
1395 }
1396
1397
1398
1399