1 /*****************************************************************************/
5 /* Expression parser */
9 /* (C) 2000-2001 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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. */
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: */
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 */
32 /*****************************************************************************/
63 /*****************************************************************************/
65 /*****************************************************************************/
69 static ExprNode* UnaryExpr (void);
70 ExprNode* AssignExpr (void);
71 ExprNode* Expression (void);
75 /*****************************************************************************/
76 /* Helper functions */
77 /*****************************************************************************/
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).
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 &&
99 static int GetBoolRep (const ExprNode* N)
100 /* Get the boolean representation of a constant expression node */
102 if (IsClassInt (N->Type)) {
103 /* An integer constant */
104 return (N->IVal != 0);
105 } else if (IsClassFloat (N->Type)) {
106 /* A float constant */
107 return (N->FVal != 0.0);
108 } else if (IsTypeArray (N->Type) && IsTypeChar (Indirect (N->Type))) {
109 /* A string constant - useless but allowed */
112 Internal ("GetBoolRep: Unknown type");
120 /*****************************************************************************/
121 /* Expression node helper functions */
122 /*****************************************************************************/
126 static ExprNode* GetIntNode (int Value)
127 /* Allocate a new expression node from the tree, make it a valid integer
128 * node and return it. Often used if an error occurs to get a safe expression
132 ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
139 /*****************************************************************************/
141 /*****************************************************************************/
145 ExprNode* DoAsm (void)
146 /* This function parses ASM statements. The syntax of the ASM directive
147 * looks like the one defined for C++ (C has no ASM directive), that is,
148 * a string literal in parenthesis.
157 /* Need left parenthesis */
160 /* Create a new expression node and assign a void type */
161 N = AllocExprNode (NT_ASM, type_void, RVALUE);
164 if (CurTok.Tok != TOK_SCONST) {
167 Error ("String literal expected");
169 /* To be on the safe side later, insert an empty asm string */
170 AppendItem (N, xstrdup (""));
174 /* Insert a copy of the string into the expression node */
175 AppendItem (N, xstrdup (GetLiteral (CurTok.IVal)));
177 /* Reset the string pointer, effectivly clearing the string from the
178 * string table. Since we're working with one token lookahead, this
179 * will fail if the next token is also a string token, but that's a
180 * syntax error anyway, because we expect a right paren.
182 ResetLiteralPoolOffs (CurTok.IVal);
185 /* Skip the string token */
188 /* Closing paren needed */
191 /* Return the created node */
197 static ExprNode* Primary (void)
198 /* Evaluate a primary expression */
202 /* Process a parenthesized subexpression. In this case we don't need to
203 * allocate a new node ourselves.
205 if (CurTok.Tok == TOK_LPAREN) {
212 /* Check for an integer or character constant */
213 if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
215 /* Create the new node */
216 N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
217 N->IVal = CurTok.IVal;
219 /* Skip the token and return the result */
224 /* Check for a float constant */
225 if (CurTok.Tok == TOK_FCONST) {
227 /* Create the new node */
228 N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
229 N->FVal = CurTok.FVal;
231 /* Skip the token and return the result */
236 /* All others may only be used if the expression evaluation is not called
237 * recursively by the preprocessor.
240 /* Illegal expression in PP mode */
241 Error ("Preprocessor expression expected");
243 /* Skip the token for error recovery */
246 /* Return an integer constant */
247 return GetIntNode (0);
251 if (CurTok.Tok == TOK_IDENT) {
257 /* Get a pointer to the symbol table entry */
258 Sym = FindSym (CurTok.Ident);
260 /* Is the symbol known? */
263 /* We found the symbol - skip the name token */
266 /* Check for illegal symbol types */
267 if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
268 /* Cannot use labels in expressions */
269 Error ("Cannot use a label in an expression");
270 return GetIntNode (0);
271 } else if (Sym->Flags & SC_TYPE) {
272 /* Cannot use type symbols */
273 Error ("Cannot use a type in an expression");
274 /* Assume an int type to make lval valid */
275 return GetIntNode (0);
278 /* Handle constants including enum values */
279 if ((Sym->Flags & SC_CONST) == SC_CONST) {
281 N = AllocExprNode (NT_CONST, Sym->Type, RVALUE);
282 N->IVal = Sym->V.ConstVal;
286 /* All symbols besides functions and arrays are lvalues */
287 int LVal = (!IsTypeFunc (Sym->Type) && !IsTypeArray (Sym->Type));
289 /* Create the node */
290 N = AllocExprNode (NT_SYM, Sym->Type, LVal);
292 /* Set the symbol pointer */
296 /* The symbol is referenced now */
297 Sym->Flags |= SC_REF;
301 /* We did not find the symbol. Remember the name, then skip it */
302 strcpy (Ident, CurTok.Ident);
305 /* IDENT is either an auto-declared function or an undefined
308 if (CurTok.Tok == TOK_LPAREN) {
310 /* Warn about the use of a function without prototype */
311 Warning ("Function call without a prototype");
313 /* Declare a function returning int. For that purpose, prepare
314 * a function signature for a function having an empty param
315 * list and returning int.
317 Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
318 N = AllocExprNode (NT_SYM, Sym->Type, RVALUE);
323 /* Print an error about an undeclared variable */
324 Error ("Undefined symbiol: `%s'", Ident);
326 /* Undeclared Variable */
327 Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
328 N = AllocExprNode (NT_SYM, Sym->Type, LVALUE);
335 } else if (CurTok.Tok == TOK_SCONST) {
338 N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (CurTok.IVal))), RVALUE);
339 N->IVal = CurTok.IVal;
341 } else if (CurTok.Tok == TOK_ASM) {
346 } else if (CurTok.Tok == TOK_A) {
349 N = AllocExprNode (NT_REG_A, type_uchar, LVALUE);
351 } else if (CurTok.Tok == TOK_X) {
354 N = AllocExprNode (NT_REG_X, type_uchar, LVALUE);
356 } else if (CurTok.Tok == TOK_Y) {
359 N = AllocExprNode (NT_REG_Y, type_uchar, LVALUE);
361 } else if (CurTok.Tok == TOK_AX) {
363 /* AX pseudo register */
364 N = AllocExprNode (NT_REG_AX, type_uint, LVALUE);
366 } else if (CurTok.Tok == TOK_EAX) {
368 /* EAX pseudo register */
369 N = AllocExprNode (NT_REG_EAX, type_ulong, LVALUE);
373 /* Illegal primary. */
374 Error ("Expression expected");
379 /* Return the new node */
385 static ExprNode* DoArray (ExprNode* Left)
393 /* Skip the bracket */
397 Right = Expression ();
399 /* Check the types. As special "C" feature, accept a reversal of base and
400 * index types: char C = 3["abcdefg"] is legal C!
402 if (IsClassPtr (Left->Type)) {
403 /* Right side must be some sort of integer */
404 if (!IsClassInt (Right->Type)) {
406 Error ("Invalid subscript");
407 /* To avoid problems later, create a new, legal subscript
410 Right = GetIntNode (0);
412 } else if (IsClassPtr (Right->Type)) {
416 /* Left side must be some sort of integer */
417 if (!IsClassInt (Left->Type)) {
419 Error ("Invalid subscript");
420 /* To avoid problems later, create a new, legal subscript
423 Left = GetIntNode (0);
426 /* Swap the expression to it's normal form */
432 /* Invalid array expression. Skip the closing bracket, then return
433 * an integer instead of the array expression to be safe later.
435 Error ("Invalid subscript");
437 return GetIntNode (0);
440 /* Skip the right bracket */
443 /* Get the type of the array elements */
444 ElementType = Indirect (Left->Type);
446 /* Allocate the branch node for the array expression */
447 Root = AllocExprNode (NT_ARRAY_SUBSCRIPT,
449 IsTypeArray (ElementType)? RVALUE : LVALUE);
451 /* Setup the branches */
452 SetLeftNode (Root, Left);
453 SetRightNode (Root, Right);
455 /* ...and return it */
461 static ExprNode* DoStruct (ExprNode* Left)
462 /* Process struct field access */
473 StructType = Left->Type;
474 if (CurTok.Tok == TOK_PTR_REF) {
475 NT = NT_STRUCTPTR_ACCESS;
476 if (!IsTypePtr (StructType)) {
477 Error ("Struct pointer expected");
478 return GetIntNode (0);
480 StructType = Indirect (StructType);
482 NT = NT_STRUCT_ACCESS;
484 if (!IsClassStruct (StructType)) {
485 Error ("Struct expected");
486 return GetIntNode (0);
489 /* Skip the token and check for an identifier */
491 if (CurTok.Tok != TOK_IDENT) {
493 Error ("Identifier expected");
494 /* Return an integer expression instead */
495 return GetIntNode (0);
498 /* Get the symbol table entry and check for a struct field */
499 strcpy (Ident, CurTok.Ident);
501 Field = FindStructField (StructType, Ident);
503 /* Struct field not found */
504 Error ("Struct/union has no field named `%s'", Ident);
505 /* Return an integer expression instead */
506 return GetIntNode (0);
509 /* Allocate and set up the right (== field) node */
510 Right = AllocExprNode (NT_SYM, Field->Type, RVALUE);
511 SetNodeSym (Right, Field);
513 /* Allocate the branch node for the resulting expression */
514 Root = AllocExprNode (NT, Right->Type,
515 IsTypeArray (Right->Type)? RVALUE : LVALUE);
517 /* Setup the branches */
518 SetLeftNode (Root, Left);
519 SetRightNode (Root, Right);
521 /* ...and return it */
527 static ExprNode* DoFunctionCall (ExprNode* Left)
528 /* Process a function call */
530 type* ResultType; /* Type of function result */
531 FuncDesc* Func; /* Function descriptor */
532 ExprNode* Root; /* Function call node */
533 int Ellipsis; /* True if we have an open param list */
534 SymEntry* Param; /* Current formal parameter */
535 unsigned ParamCount; /* Actual parameter count */
536 unsigned ParamSize; /* Number of parameter bytes */
540 if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
542 /* Call to non function */
543 Error ("Illegal function call");
545 /* Free the old tree */
548 /* Return something safe */
549 return GetIntNode (0);
552 /* Get the type of the function result */
553 ResultType = Left->Type;
554 if (IsTypeFuncPtr (Left->Type)) {
557 ResultType += DECODE_SIZE + 1; /* Set to result type */
559 /* Skip the opening parenthesis */
562 /* Allocate the function call node */
563 Root = AllocExprNode (NT_FUNCTION_CALL, ResultType, RVALUE);
565 /* Get a pointer to the function descriptor from the type string */
566 Func = GetFuncDesc (Left->Type);
568 /* Initialize vars to keep gcc silent */
571 /* Parse the parameter list */
575 while (CurTok.Tok != TOK_RPAREN) {
577 /* Count arguments */
580 /* Fetch the pointer to the next argument, check for too many args */
581 if (ParamCount <= Func->ParamCount) {
582 if (ParamCount == 1) {
584 Param = Func->SymTab->SymHead;
587 Param = Param->NextSym;
588 CHECK ((Param->Flags & SC_PARAM) != 0);
590 } else if (!Ellipsis) {
591 /* Too many arguments. Do we have an open param list? */
592 if ((Func->Flags & FD_VARIADIC) == 0) {
593 /* End of param list reached, no ellipsis */
594 Error ("Too many function arguments");
596 /* Assume an ellipsis even in case of errors to avoid an error
597 * message for each other argument.
602 /* Get the parameter value expression tree and add it to the parameter
605 AppendItem (Root, AssignExpr ());
607 /* Check for end of argument list */
608 if (CurTok.Tok != TOK_COMMA) {
614 /* We need the closing bracket here */
617 /* Check if we had enough parameters */
618 if (ParamCount < Func->ParamCount) {
619 Error ("Too few function arguments");
622 /* Return the function call node */
628 static ExprNode* DoPostIncDec (ExprNode* Left)
629 /* Handle postincrement and postdecrement */
633 /* Determine the type of the node */
634 nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
636 /* Skip the operator token */
639 /* The operand must be an lvalue */
640 if (Left->LValue == 0) {
642 /* Print a diagnostics */
643 Error ("lvalue expected");
645 /* It is safe to return the operand expression and probably better
646 * than returning an int, since the operand expression already has
647 * the correct type as expected by the program at this place, and
648 * it is even an rvalue.
653 /* Setup the expression tree */
654 Root = AllocExprNode (NT, Left->Type, RVALUE);
655 SetLeftNode (Root, Left);
657 /* Return the new node */
663 static ExprNode* PostfixExpr (void)
665 /* Get the lower level expression */
666 ExprNode* Root = Primary ();
669 while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN ||
670 CurTok.Tok == TOK_DOT || CurTok.Tok == TOK_PTR_REF ||
671 CurTok.Tok == TOK_INC || CurTok.Tok == TOK_DEC) {
674 switch (CurTok.Tok) {
677 Root = DoArray (Root);
681 Root = DoFunctionCall (Root);
686 Root = DoStruct (Root);
691 Root = DoPostIncDec (Root);
695 Internal ("Unexpected token");
700 /* Return the result */
706 static ExprNode* DoPreIncDec (void)
707 /* Handle preincrement and predecrement */
712 /* Determine the type of the node */
713 nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
715 /* Skip the operator token */
718 /* Get the expression to increment or decrement */
721 /* The operand must be an lvalue */
722 if (Op->LValue == 0) {
724 /* Print a diagnostics */
725 Error ("lvalue expected");
727 /* It is safe to return the operand expression and probably better
728 * than returning an int, since the operand expression already has
729 * the correct type as expected by the program at this place, and
730 * it is even an rvalue.
735 /* Setup the expression tree */
736 Root = AllocExprNode (NT, Op->Type, RVALUE);
737 SetLeftNode (Root, Op);
739 /* Return the new node */
745 static ExprNode* DoUnaryPlusMinus (void)
746 /* Handle unary +/- */
751 /* Remember the current token for later, then skip it */
752 token_t Tok = CurTok.Tok;
755 /* Get the operand */
759 if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
761 /* Output diagnostic */
762 Error ("Syntax error");
764 /* Free the errorneous node */
767 /* Return something that makes sense later */
768 return GetIntNode (0);
771 /* In case of PLUS, we must do nothing */
772 if (Tok == TOK_PLUS) {
774 /* Return the operand unchanged */
777 } else if (Op->NT == NT_CONST) {
779 /* The value is constant, change it according to the insn */
780 if (IsClassInt (Op->Type)) {
782 Op->IVal = -Op->IVal;
785 Op->FVal = -Op->FVal;
788 /* Return the operand itself */
793 /* Non constant value, setup the expression tree */
794 Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
795 SetLeftNode (Root, Op);
799 /* Return the new node */
805 static ExprNode* DoComplement (void)
811 /* Skip the operator token */
814 /* Get the operand */
818 if (!IsClassInt (Op->Type)) {
820 /* Display diagnostic */
821 Error ("Operation not allowed on this type");
823 /* Free the errorneous node */
826 /* Return something that makes sense later */
827 return GetIntNode (0);
830 /* If the operand is constant, handle the operation directly */
831 if (Op->NT == NT_CONST) {
833 /* Change the value and return the operand node */
834 Op->IVal = ~Op->IVal;
839 /* Setup the expression tree and return the new node */
840 Root = AllocExprNode (NT_COMPLEMENT, Op->Type, RVALUE);
841 SetLeftNode (Root, Op);
848 static ExprNode* DoBoolNot (void)
854 /* Skip the operator token */
857 /* Get the operand */
860 /* The boolean NOT operator eats anything - no need for a type check. */
862 /* Setup the expression tree and return the new node */
863 Root = AllocExprNode (NT_BOOL_NOT, type_int, RVALUE);
864 SetLeftNode (Root, Op);
870 static ExprNode* DoAddress (void)
871 /* Handle the address operator & */
875 /* Skip the operator */
878 /* Get the operand */
881 /* Accept using the address operator with arrays. This is harmless, it
882 * will just be as using the array without the operator.
884 if (IsTypeArray (Op->Type)) {
888 /* We cannot operate on rvalues */
889 if (Op->LValue == 0) {
893 /* Print diagnostics */
894 Error ("Cannot take address of rvalue");
896 /* Free the problematic tree */
899 /* Return something that is safe later */
900 Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
905 /* Create the operator node and return it */
906 return AllocExprNode (NT_ADDRESS, PointerTo (Op->Type), RVALUE);
911 static ExprNode* DoIndirect (void)
912 /* Handle the indirection operaror * */
918 /* Skip the operator */
921 /* Get the operand */
925 if (!IsClassPtr (Op->Type)) {
927 /* Print diagnostics */
928 Error ("Illegal indirection");
930 /* Free the problematic tree */
933 /* Return something that is safe later ### */
934 return GetIntNode (0);
938 /* Get the type of the result */
939 ResultType = Indirect (Op->Type);
941 /* The result is an lvalue if it is not an array */
942 LVal = IsTypeArray (ResultType)? RVALUE : LVALUE;
944 /* Create the operator node and return it */
945 return AllocExprNode (NT_INDIRECT, ResultType, LVal);
950 static ExprNode* DoSizeOf (void)
951 /* Handle the sizeof operator */
956 /* Skip the left paren */
959 /* A type or an actual variable access may follow */
962 type Type[MAXTYPELEN];
964 /* A type in parenthesis. Skip the left paren. */
967 /* Read the type and calculate the size. */
968 Size = SizeOf (ParseType (Type));
970 /* Closing paren must follow */
975 /* Some other entity */
979 Size = SizeOf (N->Type);
986 /* Create a constant node with type size_t and return it */
987 N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
994 static ExprNode* DoTypeCast (void)
995 /* Handle type casts */
997 type TargetType[MAXTYPELEN];
1001 /* Skip the left paren */
1005 ParseType (TargetType);
1010 /* Read the expression we have to cast */
1013 /* As a minor optimization, check if the type is already correct. If so,
1016 if (TypeCmp (TargetType, Op->Type) >= TC_EQUAL) {
1018 /* Just return the operand as is */
1023 /* Must be casted. Setup the expression tree and return the new node */
1024 Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
1025 SetLeftNode (Root, Op);
1033 static ExprNode* UnaryExpr (void)
1036 if (CurTok.Tok == TOK_INC || CurTok.Tok == TOK_DEC ||
1037 CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS ||
1038 CurTok.Tok == TOK_COMP || CurTok.Tok == TOK_BOOL_NOT ||
1039 CurTok.Tok == TOK_AND || CurTok.Tok == TOK_STAR ||
1040 CurTok.Tok == TOK_SIZEOF || IsTypeExpr ()) {
1042 /* Check the token */
1043 switch (CurTok.Tok) {
1047 return DoPreIncDec ();
1051 return DoUnaryPlusMinus ();
1054 return DoComplement ();
1057 return DoBoolNot ();
1060 return DoAddress ();
1063 return DoIndirect ();
1070 return DoTypeCast ();
1076 /* Call the lower level */
1077 return PostfixExpr ();
1084 static ExprNode* DoMul (ExprNode* Left)
1085 /* Handle multiplication */
1087 type TargetType[MAXTYPELEN];
1091 /* Check the type of the left operand */
1092 if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
1093 Error ("Invalid left operand to binary operator `*'");
1094 FreeExprTree (Left);
1095 Left = GetIntNode (0);
1098 /* Skip the operator token */
1101 /* Read the right expression */
1102 Right = UnaryExpr ();
1104 /* Check the type of the right operand */
1105 if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
1106 Error ("Invalid right operand to binary operator `*'");
1107 FreeExprTree (Right);
1108 Right = GetIntNode (0);
1111 /* Make the root node */
1112 Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
1113 SetLeftNode (Root, Left);
1114 SetRightNode (Root, Right);
1121 static ExprNode* MultExpr (void)
1122 /* Handle multiplicative expressions: '*' '/' and '%' */
1124 /* Get the left leave */
1125 ExprNode* Root = UnaryExpr ();
1127 /* Check if this is for us */
1128 while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV || CurTok.Tok == TOK_MOD) {
1130 switch (CurTok.Tok) {
1133 Root = DoMul (Root);
1143 Internal ("Unexpected token");
1148 /* Return the resulting expression */
1154 static ExprNode* AddExpr (void)
1155 /* Handle additive expressions: '+' and '-' */
1157 /* Get the left leave */
1158 ExprNode* Root = MultExpr ();
1160 /* Check if this is for us */
1161 while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
1163 switch (CurTok.Tok) {
1172 Internal ("Unexpected token");
1177 /* Return the resulting expression */
1183 static ExprNode* ShiftExpr (void)
1184 /* Handle shift expressions: '<<' and '>>' */
1186 /* Get the left leave */
1187 ExprNode* Root = AddExpr ();
1189 /* Check if this is for us */
1190 while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
1192 switch (CurTok.Tok) {
1201 Internal ("Unexpected token");
1206 /* Return the resulting expression */
1212 static ExprNode* RelationalExpr (void)
1213 /* Handle relational expressions: '<=', '<', '>=' and '>' */
1215 /* Get the left leave */
1216 ExprNode* Root = ShiftExpr ();
1218 /* Check if this is for us */
1219 while (CurTok.Tok == TOK_LE || CurTok.Tok == TOK_LT ||
1220 CurTok.Tok == TOK_GE || CurTok.Tok == TOK_GT) {
1222 switch (CurTok.Tok) {
1237 Internal ("Unexpected token");
1242 /* Return the resulting expression */
1248 static ExprNode* EqualityExpr (void)
1249 /* Handle equality expressions: '==' and '!=' */
1251 /* Get the left leave */
1252 ExprNode* Root = RelationalExpr ();
1254 /* Check if this is for us */
1255 while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE) {
1257 switch (CurTok.Tok) {
1266 Internal ("Unexpected token");
1271 /* Return the resulting expression */
1277 static ExprNode* AndExpr (void)
1278 /* Handle and expressions: '&' */
1280 /* Get the left leave */
1281 ExprNode* Root = EqualityExpr ();
1283 /* Check if this is for us */
1284 while (CurTok.Tok == TOK_AND) {
1286 ExprNode* Left = Root;
1289 /* Skip the token */
1292 /* Get the right operand */
1293 Right = EqualityExpr ();
1296 if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
1298 /* Print a diagnostic */
1299 Error ("Operation not allowed for these types");
1301 /* Remove the unneeded nodes */
1302 FreeExprTree (Right);
1303 FreeExprTree (Left);
1305 /* Create something safe */
1306 Root = GetIntNode (0);
1310 /* Check if both operands are constant */
1311 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1313 /* Get the constant result */
1314 int Result = GetBoolRep (Left) & GetBoolRep (Right);
1316 /* Remove the unneeded nodes */
1317 FreeExprTree (Right);
1318 FreeExprTree (Left);
1320 /* Create a constant result */
1321 Root = GetIntNode (Result);
1325 /* Make an operator node */
1326 Root = AllocExprNode (NT_AND, type_int, RVALUE);
1327 SetRightNode (Root, Right);
1328 SetLeftNode (Root, Left);
1334 /* Return the resulting expression */
1340 static ExprNode* XorExpr (void)
1341 /* Handle xor expressions: '^' */
1343 /* Get the left leave */
1344 ExprNode* Root = AndExpr ();
1346 /* Check if this is for us */
1347 while (CurTok.Tok == TOK_XOR) {
1349 ExprNode* Left = Root;
1352 /* Skip the token */
1355 /* Get the right operand */
1359 if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
1361 /* Print a diagnostic */
1362 Error ("Operation not allowed for these types");
1364 /* Remove the unneeded nodes */
1365 FreeExprTree (Right);
1366 FreeExprTree (Left);
1368 /* Create something safe */
1369 Root = GetIntNode (0);
1373 /* Check if both operands are constant */
1374 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1376 /* Get the constant result */
1377 int Result = GetBoolRep (Left) ^ GetBoolRep (Right);
1379 /* Remove the unneeded nodes */
1380 FreeExprTree (Right);
1381 FreeExprTree (Left);
1383 /* Create a constant result */
1384 Root = GetIntNode (Result);
1388 /* Make an operator node */
1389 Root = AllocExprNode (NT_XOR, type_int, RVALUE);
1390 SetRightNode (Root, Right);
1391 SetLeftNode (Root, Left);
1397 /* Return the resulting expression */
1403 static ExprNode* OrExpr (void)
1404 /* Handle or expressions: '|' */
1406 /* Get the left leave */
1407 ExprNode* Root = XorExpr ();
1409 /* Check if this is for us */
1410 while (CurTok.Tok == TOK_OR) {
1412 ExprNode* Left = Root;
1415 /* Skip the token */
1418 /* Get the right operand */
1422 if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
1424 /* Print a diagnostic */
1425 Error ("Operation not allowed for these types");
1427 /* Remove the unneeded nodes */
1428 FreeExprTree (Right);
1429 FreeExprTree (Left);
1431 /* Create something safe */
1432 Root = GetIntNode (0);
1436 /* Check if both operands are constant */
1437 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1439 /* Get the constant result */
1440 int Result = GetBoolRep (Left) | GetBoolRep (Right);
1442 /* Remove the unneeded nodes */
1443 FreeExprTree (Right);
1444 FreeExprTree (Left);
1446 /* Create a constant result */
1447 Root = GetIntNode (Result);
1451 /* Make an operator node */
1452 Root = AllocExprNode (NT_OR, type_int, RVALUE);
1453 SetRightNode (Root, Right);
1454 SetLeftNode (Root, Left);
1460 /* Return the resulting expression */
1466 static ExprNode* BoolAndExpr (void)
1467 /* Handle boolean and expressions: '&&' */
1469 /* Get the left leave */
1470 ExprNode* Root = OrExpr ();
1472 /* Check if this is for us */
1473 while (CurTok.Tok == TOK_BOOL_AND) {
1475 ExprNode* Left = Root;
1478 /* Skip the token */
1481 /* Get the right operand */
1484 /* Check if both operands are constant */
1485 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1487 /* Get the constant result */
1488 int Result = GetBoolRep (Left) && GetBoolRep (Right);
1490 /* Remove the unneeded nodes */
1491 FreeExprTree (Right);
1492 FreeExprTree (Left);
1494 /* Create a constant result */
1495 Root = GetIntNode (Result);
1499 /* Make an operator node */
1500 Root = AllocExprNode (NT_BOOL_AND, type_int, RVALUE);
1501 SetRightNode (Root, Right);
1502 SetLeftNode (Root, Left);
1508 /* Return the resulting expression */
1514 static ExprNode* BoolOrExpr (void)
1515 /* Handle boolean or expressions: '||' */
1517 /* Get the left leave */
1518 ExprNode* Root = BoolAndExpr ();
1520 /* Check if this is for us */
1521 while (CurTok.Tok == TOK_BOOL_OR) {
1523 ExprNode* Left = Root;
1526 /* Skip the token */
1529 /* Get the right operand */
1530 Right = BoolAndExpr ();
1532 /* Check if both operands are constant */
1533 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1535 /* Get the constant result */
1536 int Result = GetBoolRep (Left) && GetBoolRep (Right);
1538 /* Remove the unneeded nodes */
1539 FreeExprTree (Right);
1540 FreeExprTree (Left);
1542 /* Create a constant result */
1543 Root = GetIntNode (Result);
1547 /* Make an operator node */
1548 Root = AllocExprNode (NT_BOOL_OR, type_int, RVALUE);
1549 SetRightNode (Root, Right);
1550 SetLeftNode (Root, Left);
1556 /* Return the resulting expression */
1562 static ExprNode* ConditionalExpr (void)
1563 /* Handle the ternary operator: ':?' */
1565 /* Get the left leave */
1566 ExprNode* Cond = BoolOrExpr ();
1568 /* Check if this is for us */
1569 if (CurTok.Tok == TOK_QUEST) {
1577 /* Skip the token */
1580 /* Get the first expression */
1581 Expr1 = Expression ();
1583 /* Colon must follow */
1586 /* Get the second expression */
1587 Expr2 = ConditionalExpr ();
1589 /* Get the common type of the two expressions */
1590 Type = CommonType (Expr1->Type, Expr2->Type);
1592 /* Create a new ternary token node */
1593 Root = AllocExprNode (NT_TERNARY, Type, RVALUE);
1594 AppendItem (Root, Cond);
1595 AppendItem (Root, Expr1);
1596 AppendItem (Root, Expr2);
1598 /* Return the result */
1603 /* Just return the lower level expression */