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 */
86 return CurTok.Tok == TOK_LPAREN && (
87 (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
88 (nxttok == TOK_CONST) ||
89 (nxttok == TOK_IDENT &&
90 (Entry = FindSym (NextTok.Ident)) != 0 &&
97 static int GetBoolRep (const ExprNode* N)
98 /* Get the boolean representation of a constant expression node */
100 if (IsClassInt (N->Type)) {
101 /* An integer constant */
102 return (N->IVal != 0);
103 } else if (IsClassFloat (N->Type)) {
104 /* A float constant */
105 return (N->FVal != 0.0);
106 } else if (IsTypeArray (N->Type) && IsTypeChar (Indirect (N->Type))) {
107 /* A string constant - useless but allowed */
110 Internal ("GetBoolRep: Unknown type");
118 /*****************************************************************************/
119 /* Expression node helper functions */
120 /*****************************************************************************/
124 static ExprNode* GetIntNode (int Value)
125 /* Allocate a new expression node from the tree, make it a valid integer
126 * node and return it. Often used if an error occurs to get a safe expression
130 ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
137 /*****************************************************************************/
139 /*****************************************************************************/
143 ExprNode* DoAsm (void)
144 /* This function parses ASM statements. The syntax of the ASM directive
145 * looks like the one defined for C++ (C has no ASM directive), that is,
146 * a string literal in parenthesis.
155 /* Need left parenthesis */
158 /* Create a new expression node and assign a void type */
159 N = AllocExprNode (NT_ASM, type_void, RVALUE);
162 if (CurTok.Tok != TOK_SCONST) {
165 Error ("String literal expected");
167 /* To be on the safe side later, insert an empty asm string */
168 AppendItem (N, xstrdup (""));
172 /* Insert a copy of the string into the expression node */
173 AppendItem (N, xstrdup (GetLiteral (CurTok.IVal)));
175 /* Reset the string pointer, effectivly clearing the string from the
176 * string table. Since we're working with one token lookahead, this
177 * will fail if the next token is also a string token, but that's a
178 * syntax error anyway, because we expect a right paren.
180 ResetLiteralPoolOffs (CurTok.IVal);
183 /* Skip the string token */
186 /* Closing paren needed */
189 /* Return the created node */
195 static ExprNode* Primary (void)
196 /* Evaluate a primary expression */
200 /* Process a parenthesized subexpression. In this case we don't need to
201 * allocate a new node ourselves.
203 if (CurTok.Tok == TOK_LPAREN) {
210 /* Check for an integer or character constant */
211 if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
213 /* Create the new node */
214 N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
215 N->IVal = CurTok.IVal;
217 /* Skip the token and return the result */
222 /* Check for a float constant */
223 if (CurTok.Tok == TOK_FCONST) {
225 /* Create the new node */
226 N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
227 N->FVal = CurTok.FVal;
229 /* Skip the token and return the result */
234 /* All others may only be used if the expression evaluation is not called
235 * recursively by the preprocessor.
238 /* Illegal expression in PP mode */
239 Error ("Preprocessor expression expected");
241 /* Skip the token for error recovery */
244 /* Return an integer constant */
245 return GetIntNode (0);
249 if (CurTok.Tok == TOK_IDENT) {
255 /* Get a pointer to the symbol table entry */
256 Sym = FindSym (CurTok.Ident);
258 /* Is the symbol known? */
261 /* We found the symbol - skip the name token */
264 /* Check for illegal symbol types */
265 if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
266 /* Cannot use labels in expressions */
267 Error ("Cannot use a label in an expression");
268 return GetIntNode (0);
269 } else if (Sym->Flags & SC_TYPE) {
270 /* Cannot use type symbols */
271 Error ("Cannot use a type in an expression");
272 /* Assume an int type to make lval valid */
273 return GetIntNode (0);
276 /* Handle constants including enum values */
277 if ((Sym->Flags & SC_CONST) == SC_CONST) {
279 N = AllocExprNode (NT_CONST, Sym->Type, RVALUE);
280 N->IVal = Sym->V.ConstVal;
284 /* All symbols besides functions and arrays are lvalues */
285 int LVal = (!IsTypeFunc (Sym->Type) && !IsTypeArray (Sym->Type));
287 /* Create the node */
288 N = AllocExprNode (NT_SYM, Sym->Type, LVal);
290 /* Set the symbol pointer */
294 /* The symbol is referenced now */
295 Sym->Flags |= SC_REF;
299 /* We did not find the symbol. Remember the name, then skip it */
300 strcpy (Ident, CurTok.Ident);
303 /* IDENT is either an auto-declared function or an undefined
306 if (CurTok.Tok == TOK_LPAREN) {
308 /* Warn about the use of a function without prototype */
309 Warning ("Function call without a prototype");
311 /* Declare a function returning int. For that purpose, prepare
312 * a function signature for a function having an empty param
313 * list and returning int.
315 Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
316 N = AllocExprNode (NT_SYM, Sym->Type, RVALUE);
321 /* Print an error about an undeclared variable */
322 Error ("Undefined symbiol: `%s'", Ident);
324 /* Undeclared Variable */
325 Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
326 N = AllocExprNode (NT_SYM, Sym->Type, LVALUE);
333 } else if (CurTok.Tok == TOK_SCONST) {
336 N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (CurTok.IVal))), RVALUE);
337 N->IVal = CurTok.IVal;
339 } else if (CurTok.Tok == TOK_ASM) {
344 } else if (CurTok.Tok == TOK_A) {
347 N = AllocExprNode (NT_REG_A, type_uchar, LVALUE);
349 } else if (CurTok.Tok == TOK_X) {
352 N = AllocExprNode (NT_REG_X, type_uchar, LVALUE);
354 } else if (CurTok.Tok == TOK_Y) {
357 N = AllocExprNode (NT_REG_Y, type_uchar, LVALUE);
359 } else if (CurTok.Tok == TOK_AX) {
361 /* AX pseudo register */
362 N = AllocExprNode (NT_REG_AX, type_uint, LVALUE);
364 } else if (CurTok.Tok == TOK_EAX) {
366 /* EAX pseudo register */
367 N = AllocExprNode (NT_REG_EAX, type_ulong, LVALUE);
371 /* Illegal primary. */
372 Error ("Expression expected");
377 /* Return the new node */
383 static ExprNode* DoArray (ExprNode* Left)
391 /* Skip the bracket */
395 Right = Expression ();
397 /* Check the types. As special "C" feature, accept a reversal of base and
398 * index types: char C = 3["abcdefg"] is legal C!
400 if (IsClassPtr (Left->Type)) {
401 /* Right side must be some sort of integer */
402 if (!IsClassInt (Right->Type)) {
404 Error ("Invalid subscript");
405 /* To avoid problems later, create a new, legal subscript
408 Right = GetIntNode (0);
410 } else if (IsClassPtr (Right->Type)) {
414 /* Left side must be some sort of integer */
415 if (!IsClassInt (Left->Type)) {
417 Error ("Invalid subscript");
418 /* To avoid problems later, create a new, legal subscript
421 Left = GetIntNode (0);
424 /* Swap the expression to it's normal form */
430 /* Invalid array expression. Skip the closing bracket, then return
431 * an integer instead of the array expression to be safe later.
433 Error ("Invalid subscript");
435 return GetIntNode (0);
438 /* Skip the right bracket */
441 /* Get the type of the array elements */
442 ElementType = Indirect (Left->Type);
444 /* Allocate the branch node for the array expression */
445 Root = AllocExprNode (NT_ARRAY_SUBSCRIPT,
447 IsTypeArray (ElementType)? RVALUE : LVALUE);
449 /* Setup the branches */
450 SetLeftNode (Root, Left);
451 SetRightNode (Root, Right);
453 /* ...and return it */
459 static ExprNode* DoStruct (ExprNode* Left)
460 /* Process struct field access */
471 StructType = Left->Type;
472 if (CurTok.Tok == TOK_PTR_REF) {
473 NT = NT_STRUCTPTR_ACCESS;
474 if (!IsTypePtr (StructType)) {
475 Error ("Struct pointer expected");
476 return GetIntNode (0);
478 StructType = Indirect (StructType);
480 NT = NT_STRUCT_ACCESS;
482 if (!IsClassStruct (StructType)) {
483 Error ("Struct expected");
484 return GetIntNode (0);
487 /* Skip the token and check for an identifier */
489 if (CurTok.Tok != TOK_IDENT) {
491 Error ("Identifier expected");
492 /* Return an integer expression instead */
493 return GetIntNode (0);
496 /* Get the symbol table entry and check for a struct field */
497 strcpy (Ident, CurTok.Ident);
499 Field = FindStructField (StructType, Ident);
501 /* Struct field not found */
502 Error ("Struct/union has no field named `%s'", Ident);
503 /* Return an integer expression instead */
504 return GetIntNode (0);
507 /* Allocate and set up the right (== field) node */
508 Right = AllocExprNode (NT_SYM, Field->Type, RVALUE);
509 SetNodeSym (Right, Field);
511 /* Allocate the branch node for the resulting expression */
512 Root = AllocExprNode (NT, Right->Type,
513 IsTypeArray (Right->Type)? RVALUE : LVALUE);
515 /* Setup the branches */
516 SetLeftNode (Root, Left);
517 SetRightNode (Root, Right);
519 /* ...and return it */
525 static ExprNode* DoFunctionCall (ExprNode* Left)
526 /* Process a function call */
528 type* ResultType; /* Type of function result */
529 FuncDesc* Func; /* Function descriptor */
530 ExprNode* Root; /* Function call node */
531 int Ellipsis; /* True if we have an open param list */
532 SymEntry* Param; /* Current formal parameter */
533 unsigned ParamCount; /* Actual parameter count */
534 unsigned ParamSize; /* Number of parameter bytes */
538 if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
540 /* Call to non function */
541 Error ("Illegal function call");
543 /* Free the old tree */
546 /* Return something safe */
547 return GetIntNode (0);
550 /* Get the type of the function result */
551 ResultType = Left->Type;
552 if (IsTypeFuncPtr (Left->Type)) {
555 ResultType += DECODE_SIZE + 1; /* Set to result type */
557 /* Skip the opening parenthesis */
560 /* Allocate the function call node */
561 Root = AllocExprNode (NT_FUNCTION_CALL, ResultType, RVALUE);
563 /* Get a pointer to the function descriptor from the type string */
564 Func = GetFuncDesc (Left->Type);
566 /* Initialize vars to keep gcc silent */
569 /* Parse the parameter list */
573 while (CurTok.Tok != TOK_RPAREN) {
575 /* Count arguments */
578 /* Fetch the pointer to the next argument, check for too many args */
579 if (ParamCount <= Func->ParamCount) {
580 if (ParamCount == 1) {
582 Param = Func->SymTab->SymHead;
585 Param = Param->NextSym;
586 CHECK ((Param->Flags & SC_PARAM) != 0);
588 } else if (!Ellipsis) {
589 /* Too many arguments. Do we have an open param list? */
590 if ((Func->Flags & FD_VARIADIC) == 0) {
591 /* End of param list reached, no ellipsis */
592 Error ("Too many function arguments");
594 /* Assume an ellipsis even in case of errors to avoid an error
595 * message for each other argument.
600 /* Get the parameter value expression tree and add it to the parameter
603 AppendItem (Root, AssignExpr ());
605 /* Check for end of argument list */
606 if (CurTok.Tok != TOK_COMMA) {
612 /* We need the closing bracket here */
615 /* Check if we had enough parameters */
616 if (ParamCount < Func->ParamCount) {
617 Error ("Too few function arguments");
620 /* Return the function call node */
626 static ExprNode* DoPostIncDec (ExprNode* Left)
627 /* Handle postincrement and postdecrement */
631 /* Determine the type of the node */
632 nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
634 /* Skip the operator token */
637 /* The operand must be an lvalue */
638 if (Left->LValue == 0) {
640 /* Print a diagnostics */
641 Error ("lvalue expected");
643 /* It is safe to return the operand expression and probably better
644 * than returning an int, since the operand expression already has
645 * the correct type as expected by the program at this place, and
646 * it is even an rvalue.
651 /* Setup the expression tree */
652 Root = AllocExprNode (NT, Left->Type, RVALUE);
653 SetLeftNode (Root, Left);
655 /* Return the new node */
661 static ExprNode* PostfixExpr (void)
662 /* Handle a postfix expression */
664 /* Get the lower level expression */
665 ExprNode* Root = Primary ();
668 while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN ||
669 CurTok.Tok == TOK_DOT || CurTok.Tok == TOK_PTR_REF ||
670 CurTok.Tok == TOK_INC || CurTok.Tok == TOK_DEC) {
673 switch (CurTok.Tok) {
676 Root = DoArray (Root);
680 Root = DoFunctionCall (Root);
685 Root = DoStruct (Root);
690 Root = DoPostIncDec (Root);
694 Internal ("Unexpected token");
699 /* Return the result */
705 static ExprNode* DoPreIncDec (void)
706 /* Handle preincrement and predecrement */
711 /* Determine the type of the node */
712 nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
714 /* Skip the operator token */
717 /* Get the expression to increment or decrement */
720 /* The operand must be an lvalue */
721 if (Op->LValue == 0) {
723 /* Print a diagnostics */
724 Error ("lvalue expected");
726 /* It is safe to return the operand expression and probably better
727 * than returning an int, since the operand expression already has
728 * the correct type as expected by the program at this place, and
729 * it is even an rvalue.
734 /* Setup the expression tree */
735 Root = AllocExprNode (NT, Op->Type, RVALUE);
736 SetLeftNode (Root, Op);
738 /* Return the new node */
744 static ExprNode* DoUnaryPlusMinus (void)
745 /* Handle unary +/- */
750 /* Remember the current token for later, then skip it */
751 token_t Tok = CurTok.Tok;
754 /* Get the operand */
758 if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
760 /* Output diagnostic */
761 Error ("Syntax error");
763 /* Free the errorneous node */
766 /* Return something that makes sense later */
767 return GetIntNode (0);
770 /* In case of PLUS, we must do nothing */
771 if (Tok == TOK_PLUS) {
773 /* Return the operand unchanged */
776 } else if (Op->NT == NT_CONST) {
778 /* The value is constant, change it according to the insn */
779 if (IsClassInt (Op->Type)) {
781 Op->IVal = -Op->IVal;
784 Op->FVal = -Op->FVal;
787 /* Return the operand itself */
792 /* Non constant value, setup the expression tree */
793 Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
794 SetLeftNode (Root, Op);
798 /* Return the new node */
804 static ExprNode* DoComplement (void)
810 /* Skip the operator token */
813 /* Get the operand */
817 if (!IsClassInt (Op->Type)) {
819 /* Display diagnostic */
820 Error ("Operation not allowed on this type");
822 /* Free the errorneous node */
825 /* Return something that makes sense later */
826 return GetIntNode (0);
829 /* If the operand is constant, handle the operation directly */
830 if (Op->NT == NT_CONST) {
832 /* Change the value and return the operand node */
833 Op->IVal = ~Op->IVal;
838 /* Setup the expression tree and return the new node */
839 Root = AllocExprNode (NT_COMPLEMENT, Op->Type, RVALUE);
840 SetLeftNode (Root, Op);
847 static ExprNode* DoBoolNot (void)
853 /* Skip the operator token */
856 /* Get the operand */
859 /* The boolean NOT operator eats anything - no need for a type check. */
861 /* Setup the expression tree and return the new node */
862 Root = AllocExprNode (NT_BOOL_NOT, type_int, RVALUE);
863 SetLeftNode (Root, Op);
869 static ExprNode* DoAddress (void)
870 /* Handle the address operator & */
874 /* Skip the operator */
877 /* Get the operand */
880 /* Accept using the address operator with arrays. This is harmless, it
881 * will just be as using the array without the operator.
883 if (IsTypeArray (Op->Type)) {
887 /* We cannot operate on rvalues */
888 if (Op->LValue == 0) {
892 /* Print diagnostics */
893 Error ("Cannot take address of rvalue");
895 /* Free the problematic tree */
898 /* Return something that is safe later */
899 Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
904 /* Create the operator node and return it */
905 return AllocExprNode (NT_ADDRESS, PointerTo (Op->Type), RVALUE);
910 static ExprNode* DoIndirect (void)
911 /* Handle the indirection operator * */
917 /* Skip the operator */
920 /* Get the operand */
924 if (!IsClassPtr (Op->Type)) {
926 /* Print diagnostics */
927 Error ("Illegal indirection");
929 /* Free the problematic tree */
932 /* Return something that is safe later ### */
933 return GetIntNode (0);
937 /* Get the type of the result */
938 ResultType = Indirect (Op->Type);
940 /* The result is an lvalue if it is not an array */
941 LVal = IsTypeArray (ResultType)? RVALUE : LVALUE;
943 /* Create the operator node and return it */
944 return AllocExprNode (NT_INDIRECT, ResultType, LVal);
949 static ExprNode* DoSizeOf (void)
950 /* Handle the sizeof operator */
955 /* Skip the left paren */
958 /* A type or an actual variable access may follow */
961 type Type[MAXTYPELEN];
963 /* A type in parenthesis. Skip the left paren. */
966 /* Read the type and calculate the size. */
967 Size = SizeOf (ParseType (Type));
969 /* Closing paren must follow */
974 /* Some other entity */
978 Size = SizeOf (N->Type);
985 /* Create a constant node with type size_t and return it */
986 N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
993 static ExprNode* DoTypeCast (void)
994 /* Handle type casts */
996 type TargetType[MAXTYPELEN];
1000 /* Skip the left paren */
1004 ParseType (TargetType);
1009 /* Read the expression we have to cast */
1012 /* As a minor optimization, check if the type is already correct. If so,
1015 if (TypeCmp (TargetType, Op->Type) >= TC_EQUAL) {
1017 /* Just return the operand as is */
1022 /* Must be casted. Setup the expression tree and return the new node */
1023 Root = AllocExprNode (NT_TYPECAST, TargetType, RVALUE);
1024 SetLeftNode (Root, Op);
1032 static ExprNode* UnaryExpr (void)
1035 if (CurTok.Tok == TOK_INC || CurTok.Tok == TOK_DEC ||
1036 CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS ||
1037 CurTok.Tok == TOK_COMP || CurTok.Tok == TOK_BOOL_NOT ||
1038 CurTok.Tok == TOK_AND || CurTok.Tok == TOK_STAR ||
1039 CurTok.Tok == TOK_SIZEOF || IsTypeExpr ()) {
1041 /* Check the token */
1042 switch (CurTok.Tok) {
1046 return DoPreIncDec ();
1050 return DoUnaryPlusMinus ();
1053 return DoComplement ();
1056 return DoBoolNot ();
1059 return DoAddress ();
1062 return DoIndirect ();
1069 return DoTypeCast ();
1075 /* Call the lower level */
1076 return PostfixExpr ();
1083 static ExprNode* DoMul (ExprNode* Left)
1084 /* Handle multiplication */
1086 type TargetType[MAXTYPELEN];
1090 /* Check the type of the left operand */
1091 if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
1092 Error ("Invalid left operand to binary operator `*'");
1093 FreeExprTree (Left);
1094 Left = GetIntNode (0);
1097 /* Skip the operator token */
1100 /* Read the right expression */
1101 Right = UnaryExpr ();
1103 /* Check the type of the right operand */
1104 if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
1105 Error ("Invalid right operand to binary operator `*'");
1106 FreeExprTree (Right);
1107 Right = GetIntNode (0);
1110 /* Make the root node */
1111 Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
1112 SetLeftNode (Root, Left);
1113 SetRightNode (Root, Right);
1120 static ExprNode* MultExpr (void)
1121 /* Handle multiplicative expressions: '*' '/' and '%' */
1123 /* Get the left leave */
1124 ExprNode* Root = UnaryExpr ();
1126 /* Check if this is for us */
1127 while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV || CurTok.Tok == TOK_MOD) {
1129 switch (CurTok.Tok) {
1132 Root = DoMul (Root);
1142 Internal ("Unexpected token");
1147 /* Return the resulting expression */
1153 static ExprNode* AddExpr (void)
1154 /* Handle additive expressions: '+' and '-' */
1156 /* Get the left leave */
1157 ExprNode* Root = MultExpr ();
1159 /* Check if this is for us */
1160 while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
1162 switch (CurTok.Tok) {
1171 Internal ("Unexpected token");
1176 /* Return the resulting expression */
1182 static ExprNode* ShiftExpr (void)
1183 /* Handle shift expressions: '<<' and '>>' */
1185 /* Get the left leave */
1186 ExprNode* Root = AddExpr ();
1188 /* Check if this is for us */
1189 while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
1191 switch (CurTok.Tok) {
1200 Internal ("Unexpected token");
1205 /* Return the resulting expression */
1211 static ExprNode* RelationalExpr (void)
1212 /* Handle relational expressions: '<=', '<', '>=' and '>' */
1214 /* Get the left leave */
1215 ExprNode* Root = ShiftExpr ();
1217 /* Check if this is for us */
1218 while (CurTok.Tok == TOK_LE || CurTok.Tok == TOK_LT ||
1219 CurTok.Tok == TOK_GE || CurTok.Tok == TOK_GT) {
1221 switch (CurTok.Tok) {
1236 Internal ("Unexpected token");
1241 /* Return the resulting expression */
1247 static ExprNode* EqualityExpr (void)
1248 /* Handle equality expressions: '==' and '!=' */
1250 /* Get the left leave */
1251 ExprNode* Root = RelationalExpr ();
1253 /* Check if this is for us */
1254 while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE) {
1256 switch (CurTok.Tok) {
1265 Internal ("Unexpected token");
1270 /* Return the resulting expression */
1276 static ExprNode* AndExpr (void)
1277 /* Handle and expressions: '&' */
1279 /* Get the left leave */
1280 ExprNode* Root = EqualityExpr ();
1282 /* Check if this is for us */
1283 while (CurTok.Tok == TOK_AND) {
1285 ExprNode* Left = Root;
1288 /* Skip the token */
1291 /* Get the right operand */
1292 Right = EqualityExpr ();
1295 if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
1297 /* Print a diagnostic */
1298 Error ("Operation not allowed for these types");
1300 /* Remove the unneeded nodes */
1301 FreeExprTree (Right);
1302 FreeExprTree (Left);
1304 /* Create something safe */
1305 Root = GetIntNode (0);
1309 /* Check if both operands are constant */
1310 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1312 /* Get the constant result */
1313 int Result = GetBoolRep (Left) & GetBoolRep (Right);
1315 /* Remove the unneeded nodes */
1316 FreeExprTree (Right);
1317 FreeExprTree (Left);
1319 /* Create a constant result */
1320 Root = GetIntNode (Result);
1324 /* Make an operator node */
1325 Root = AllocExprNode (NT_AND, type_int, RVALUE);
1326 SetRightNode (Root, Right);
1327 SetLeftNode (Root, Left);
1333 /* Return the resulting expression */
1339 static ExprNode* XorExpr (void)
1340 /* Handle xor expressions: '^' */
1342 /* Get the left leave */
1343 ExprNode* Root = AndExpr ();
1345 /* Check if this is for us */
1346 while (CurTok.Tok == TOK_XOR) {
1348 ExprNode* Left = Root;
1351 /* Skip the token */
1354 /* Get the right operand */
1358 if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
1360 /* Print a diagnostic */
1361 Error ("Operation not allowed for these types");
1363 /* Remove the unneeded nodes */
1364 FreeExprTree (Right);
1365 FreeExprTree (Left);
1367 /* Create something safe */
1368 Root = GetIntNode (0);
1372 /* Check if both operands are constant */
1373 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1375 /* Get the constant result */
1376 int Result = GetBoolRep (Left) ^ GetBoolRep (Right);
1378 /* Remove the unneeded nodes */
1379 FreeExprTree (Right);
1380 FreeExprTree (Left);
1382 /* Create a constant result */
1383 Root = GetIntNode (Result);
1387 /* Make an operator node */
1388 Root = AllocExprNode (NT_XOR, type_int, RVALUE);
1389 SetRightNode (Root, Right);
1390 SetLeftNode (Root, Left);
1396 /* Return the resulting expression */
1402 static ExprNode* OrExpr (void)
1403 /* Handle or expressions: '|' */
1405 /* Get the left leave */
1406 ExprNode* Root = XorExpr ();
1408 /* Check if this is for us */
1409 while (CurTok.Tok == TOK_OR) {
1411 ExprNode* Left = Root;
1414 /* Skip the token */
1417 /* Get the right operand */
1421 if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
1423 /* Print a diagnostic */
1424 Error ("Operation not allowed for these types");
1426 /* Remove the unneeded nodes */
1427 FreeExprTree (Right);
1428 FreeExprTree (Left);
1430 /* Create something safe */
1431 Root = GetIntNode (0);
1435 /* Check if both operands are constant */
1436 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1438 /* Get the constant result */
1439 int Result = GetBoolRep (Left) | GetBoolRep (Right);
1441 /* Remove the unneeded nodes */
1442 FreeExprTree (Right);
1443 FreeExprTree (Left);
1445 /* Create a constant result */
1446 Root = GetIntNode (Result);
1450 /* Make an operator node */
1451 Root = AllocExprNode (NT_OR, type_int, RVALUE);
1452 SetRightNode (Root, Right);
1453 SetLeftNode (Root, Left);
1459 /* Return the resulting expression */
1465 static ExprNode* BoolAndExpr (void)
1466 /* Handle boolean and expressions: '&&' */
1468 /* Get the left leave */
1469 ExprNode* Root = OrExpr ();
1471 /* Check if this is for us */
1472 while (CurTok.Tok == TOK_BOOL_AND) {
1474 ExprNode* Left = Root;
1477 /* Skip the token */
1480 /* Get the right operand */
1483 /* Check if both operands are constant */
1484 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1486 /* Get the constant result */
1487 int Result = GetBoolRep (Left) && GetBoolRep (Right);
1489 /* Remove the unneeded nodes */
1490 FreeExprTree (Right);
1491 FreeExprTree (Left);
1493 /* Create a constant result */
1494 Root = GetIntNode (Result);
1498 /* Make an operator node */
1499 Root = AllocExprNode (NT_BOOL_AND, type_int, RVALUE);
1500 SetRightNode (Root, Right);
1501 SetLeftNode (Root, Left);
1507 /* Return the resulting expression */
1513 static ExprNode* BoolOrExpr (void)
1514 /* Handle boolean or expressions: '||' */
1516 /* Get the left leave */
1517 ExprNode* Root = BoolAndExpr ();
1519 /* Check if this is for us */
1520 while (CurTok.Tok == TOK_BOOL_OR) {
1522 ExprNode* Left = Root;
1525 /* Skip the token */
1528 /* Get the right operand */
1529 Right = BoolAndExpr ();
1531 /* Check if both operands are constant */
1532 if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
1534 /* Get the constant result */
1535 int Result = GetBoolRep (Left) && GetBoolRep (Right);
1537 /* Remove the unneeded nodes */
1538 FreeExprTree (Right);
1539 FreeExprTree (Left);
1541 /* Create a constant result */
1542 Root = GetIntNode (Result);
1546 /* Make an operator node */
1547 Root = AllocExprNode (NT_BOOL_OR, type_int, RVALUE);
1548 SetRightNode (Root, Right);
1549 SetLeftNode (Root, Left);
1555 /* Return the resulting expression */
1561 static ExprNode* ConditionalExpr (void)
1562 /* Handle the ternary operator: ':?' */
1564 /* Get the left leave */
1565 ExprNode* Cond = BoolOrExpr ();
1567 /* Check if this is for us */
1568 if (CurTok.Tok == TOK_QUEST) {
1576 /* Skip the token */
1579 /* Get the first expression */
1580 Expr1 = Expression ();
1582 /* Colon must follow */
1585 /* Get the second expression */
1586 Expr2 = ConditionalExpr ();
1588 /* Get the common type of the two expressions */
1589 Type = CommonType (Expr1->Type, Expr2->Type);
1591 /* Create a new ternary token node */
1592 Root = AllocExprNode (NT_TERNARY, Type, RVALUE);
1593 AppendItem (Root, Cond);
1594 AppendItem (Root, Expr1);
1595 AppendItem (Root, Expr2);
1597 /* Return the result */
1602 /* Just return the lower level expression */