1 /*****************************************************************************/
5 /* Expression parser */
9 /* (C) 2000 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 /*****************************************************************************/
100 /* Expression node helper functions */
101 /*****************************************************************************/
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
111 ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
118 /*****************************************************************************/
120 /*****************************************************************************/
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.
136 /* Need left parenthesis */
139 /* Create a new expression node and assign a void type */
140 N = AllocExprNode (NT_ASM, type_void, RVALUE);
143 if (CurTok.Tok != TOK_SCONST) {
146 Error (ERR_STRLIT_EXPECTED);
148 /* To be on the safe side later, insert an empty asm string */
149 AppendItem (N, xstrdup (""));
153 /* Insert a copy of the string into the expression node */
154 AppendItem (N, xstrdup (GetLiteral (curval)));
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.
161 ResetLiteralOffs (curval);
164 /* Skip the string token */
167 /* Closing paren needed */
170 /* Return the created node */
176 static ExprNode* Primary (void)
177 /* Evaluate a primary expression */
181 /* Process a parenthesized subexpression. In this case we don't need to
182 * allocate a new node ourselves.
184 if (CurTok.Tok == TOK_LPAREN) {
191 /* Check for an integer or character constant */
192 if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
194 /* Create the new node */
195 N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
196 N->V.I = CurTok.IVal;
198 /* Skip the token and return the result */
203 /* Check for a float constant */
204 if (CurTok.Tok == TOK_FCONST) {
206 /* Create the new node */
207 N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
208 N->V.F = CurTok.FVal;
210 /* Skip the token and return the result */
215 /* All others may only be used if the expression evaluation is not called
216 * recursively by the preprocessor.
219 /* Illegal expression in PP mode */
220 Error (ERR_CPP_EXPR_EXPECTED);
222 /* Skip the token for error recovery */
225 /* Return an integer constant */
226 return GetIntNode (0);
230 if (CurTok.Tok == TOK_IDENT) {
236 /* Get a pointer to the symbol table entry */
237 Sym = FindSym (CurTok.Ident);
239 /* Is the symbol known? */
242 /* We found the symbol - skip the name token */
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);
257 /* Handle enum values as constant integers */
258 if ((Sym->Flags & SC_ENUM) == SC_ENUM) {
260 N = GetIntNode (Sym->V.EnumVal);
264 /* All symbols besides functions and arrays are lvalues */
265 int LVal = (!IsTypeFunc (Sym->Type) && !IsTypeArray (Sym->Type));
267 /* Create the node */
268 N = AllocExprNode (NT_SYM, Sym->Type, LVal);
270 /* Set the symbol pointer */
274 /* The symbol is referenced now */
275 Sym->Flags |= SC_REF;
279 /* We did not find the symbol. Remember the name, then skip it */
280 strcpy (Ident, CurTok.Ident);
283 /* IDENT is either an auto-declared function or an undefined
286 if (CurTok.Tok == TOK_LPAREN) {
288 /* Warn about the use of a function without prototype */
289 Warning (WARN_FUNC_WITHOUT_PROTO);
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.
295 Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
296 N = AllocExprNode (NT_SYM, Sym->Type, RVALUE);
301 /* Print an error about an undeclared variable */
302 Error (ERR_UNDEFINED_SYMBOL, Ident);
304 /* Undeclared Variable */
305 Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
306 N = AllocExprNode (NT_SYM, Sym->Type, LVALUE);
313 } else if (CurTok.Tok == TOK_SCONST) {
316 N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (curval))), RVALUE);
319 } else if (CurTok.Tok == TOK_ASM) {
324 } else if (CurTok.Tok == TOK_A) {
327 N = AllocExprNode (NT_REG_A, type_uchar, LVALUE);
329 } else if (CurTok.Tok == TOK_X) {
332 N = AllocExprNode (NT_REG_X, type_uchar, LVALUE);
334 } else if (CurTok.Tok == TOK_Y) {
337 N = AllocExprNode (NT_REG_Y, type_uchar, LVALUE);
339 } else if (CurTok.Tok == TOK_AX) {
341 /* AX pseudo register */
342 N = AllocExprNode (NT_REG_AX, type_uint, LVALUE);
344 } else if (CurTok.Tok == TOK_EAX) {
346 /* EAX pseudo register */
347 N = AllocExprNode (NT_REG_EAX, type_ulong, LVALUE);
351 /* Illegal primary. */
352 Error (ERR_EXPR_EXPECTED);
357 /* Return the new node */
363 static ExprNode* DoArray (ExprNode* Left)
371 /* Skip the bracket */
375 Right = Expression ();
377 /* Check the types. As special "C" feature, accept a reversal of base and
379 * char C = 3["abcdefg"];
382 if (IsClassPtr (Left->Type)) {
383 /* Right side must be some sort of integer */
384 if (!IsClassInt (Right->Type)) {
386 Error (ERR_CANNOT_SUBSCRIPT);
387 /* To avoid problems later, create a new, legal subscript
390 Right = GetIntNode (0);
392 } else if (IsClassPtr (Right->Type)) {
396 /* Left side must be some sort of integer */
397 if (!IsClassInt (Right->Type)) {
399 Error (ERR_CANNOT_SUBSCRIPT);
400 /* To avoid problems later, create a new, legal subscript
403 Left = GetIntNode (0);
406 /* Swap the expression to it's normal form */
412 /* Invalid array expression. Skip the closing bracket, then return
413 * an integer instead of the array expression to be safe later.
415 Error (ERR_CANNOT_SUBSCRIPT);
417 return GetIntNode (0);
420 /* Skip the right bracket */
423 /* Get the type of the array elements */
424 ElementType = Indirect (Left->Type);
426 /* Allocate the branch node for the array expression */
427 Root = AllocExprNode (NT_ARRAY_SUBSCRIPT,
429 IsTypeArray (ElementType)? RVALUE : LVALUE);
431 /* Setup the branches */
432 SetLeftNode (Root, Left);
433 SetRightNode (Root, Right);
435 /* ...and return it */
441 static ExprNode* DoStruct (ExprNode* Left)
442 /* Process struct field access */
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);
460 StructType = Indirect (StructType);
462 NT = NT_STRUCT_ACCESS;
464 if (!IsClassStruct (StructType)) {
465 Error (ERR_STRUCT_EXPECTED);
466 return GetIntNode (0);
469 /* Skip the token and check for an identifier */
471 if (CurTok.Tok != TOK_IDENT) {
473 Error (ERR_IDENT_EXPECTED);
474 /* Return an integer expression instead */
475 return GetIntNode (0);
478 /* Get the symbol table entry and check for a struct field */
479 strcpy (Ident, CurTok.Ident);
481 Field = FindStructField (StructType, Ident);
483 /* Struct field not found */
484 Error (ERR_STRUCT_FIELD_MISMATCH, Ident);
485 /* Return an integer expression instead */
486 return GetIntNode (0);
489 /* Allocate and set up the right (== field) node */
490 Right = AllocExprNode (NT_SYM, Field->Type, RVALUE);
491 SetNodeSym (Right, Field);
493 /* Allocate the branch node for the resulting expression */
494 Root = AllocExprNode (NT, Right->Type,
495 IsTypeArray (Right->Type)? RVALUE : LVALUE);
497 /* Setup the branches */
498 SetLeftNode (Root, Left);
499 SetRightNode (Root, Right);
501 /* ...and return it */
507 static ExprNode* DoFunctionCall (ExprNode* Left)
508 /* Process a function call */
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 */
520 if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
522 /* Call to non function */
523 Error (ERR_ILLEGAL_FUNC_CALL);
525 /* Free the old node */
528 /* Return something safe */
529 return GetIntNode (0);
532 /* Get the type of the function result */
533 ResultType = Left->Type;
534 if (IsTypeFuncPtr (Left->Type)) {
537 ResultType += DECODE_SIZE + 1; /* Set to result type */
539 /* Skip the opening parenthesis */
542 /* Allocate the function call node */
543 Root = AllocExprNode (NT_FUNCTION_CALL, ResultType, RVALUE);
545 /* Get a pointer to the function descriptor from the type string */
546 Func = GetFuncDesc (Left->Type);
548 /* Initialize vars to keep gcc silent */
551 /* Parse the parameter list */
555 while (CurTok.Tok != TOK_RPAREN) {
557 /* Count arguments */
560 /* Fetch the pointer to the next argument, check for too many args */
561 if (ParamCount <= Func->ParamCount) {
562 if (ParamCount == 1) {
564 Param = Func->SymTab->SymHead;
567 Param = Param->NextSym;
568 CHECK ((Param->Flags & SC_PARAM) != 0);
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);
576 /* Assume an ellipsis even in case of errors to avoid an error
577 * message for each other argument.
582 /* Get the parameter value expression tree and add it to the parameter
585 AppendItem (Root, AssignExpr ());
587 /* Check for end of argument list */
588 if (CurTok.Tok != TOK_COMMA) {
594 /* We need the closing bracket here */
597 /* Check if we had enough parameters */
598 if (ParamCount < Func->ParamCount) {
599 Error (ERR_TOO_FEW_FUNC_ARGS);
602 /* Return the function call node */
608 static ExprNode* DoPostIncDec (ExprNode* Left)
609 /* Handle postincrement and postdecrement */
613 /* Determine the type of the node */
614 nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
616 /* Skip the operator token */
619 /* The operand must be an lvalue */
620 if (Left->LValue == 0) {
622 /* Print a diagnostics */
623 Error (ERR_LVALUE_EXPECTED);
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.
633 /* Setup the expression tree */
634 Root = AllocExprNode (NT, Left->Type, RVALUE);
635 SetLeftNode (Root, Left);
637 /* Return the new node */
643 static ExprNode* PostfixExpr (void)
645 /* Get the lower level expression */
646 ExprNode* Root = Primary ();
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) {
654 switch (CurTok.Tok) {
657 Root = DoArray (Root);
661 Root = DoFunctionCall (Root);
666 Root = DoStruct (Root);
671 Root = DoPostIncDec (Root);
675 Internal ("Unexpected token");
680 /* Return the result */
686 static ExprNode* DoPreIncDec (void)
687 /* Handle preincrement and predecrement */
692 /* Determine the type of the node */
693 nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
695 /* Skip the operator token */
698 /* Get the expression to increment or decrement */
701 /* The operand must be an lvalue */
702 if (Op->LValue == 0) {
704 /* Print a diagnostics */
705 Error (ERR_LVALUE_EXPECTED);
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.
715 /* Setup the expression tree */
716 Root = AllocExprNode (NT, Op->Type, RVALUE);
717 SetLeftNode (Root, Op);
719 /* Return the new node */
725 static ExprNode* DoUnaryPlusMinus (void)
726 /* Handle unary +/- */
731 /* Remember the current token for later, then skip it */
732 token_t Tok = CurTok.Tok;
735 /* Get the operand */
739 if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
741 /* Display diagnostic */
744 /* Free the errorneous node */
747 /* Return something that makes sense later */
748 return GetIntNode (0);
751 /* In case of PLUS, we must do nothing */
752 if (Tok == TOK_PLUS) {
754 /* Return the operand unchanged */
757 } else if (Op->NT == NT_CONST) {
759 /* The value is constant, change it according to the insn */
760 if (IsClassInt (Op->Type)) {
768 /* Return the operand itself */
773 /* Non constant value, setup the expression tree */
774 Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
775 SetLeftNode (Root, Op);
779 /* Return the new node */
785 static ExprNode* DoComplement (void)
791 /* Skip the operator token */
794 /* Get the operand */
798 if (!IsClassInt (Op->Type)) {
800 /* Display diagnostic */
801 Error (ERR_OP_NOT_ALLOWED);
803 /* Free the errorneous node */
806 /* Return something that makes sense later */
807 return GetIntNode (0);
810 /* If the operand is constant, handle the operation directly */
811 if (Op->NT == NT_CONST) {
813 /* Change the value and return the operand node */
819 /* Setup the expression tree and return the new node */
820 Root = AllocExprNode (NT_COMPLEMENT, Op->Type, RVALUE);
821 SetLeftNode (Root, Op);
828 static ExprNode* DoBoolNot (void)
834 /* Skip the operator token */
837 /* Get the operand */
840 /* The boolean NOT operator eats anything - no need for a type check. */
842 /* Setup the expression tree and return the new node */
843 Root = AllocExprNode (NT_BOOL_NOT, type_int, RVALUE);
844 SetLeftNode (Root, Op);
850 static ExprNode* DoAddress (void)
851 /* Handle the address operator & */
855 /* Skip the operator */
858 /* Get the operand */
861 /* Accept using the address operator with arrays. This is harmless, it
862 * will just be as using the array without the operator.
864 if (IsTypeArray (Op->Type)) {
868 /* We cannot operate on rvalues */
869 if (Op->LValue == 0) {
873 /* Print diagnostics */
874 Error (ERR_ILLEGAL_ADDRESS);
876 /* Free the problematic node */
879 /* Return something that is safe later */
880 Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
886 /* Create the operator node and return it */
887 return AllocExprNode (NT_ADDRESS, PointerTo (Op->Type), RVALUE);
892 static ExprNode* DoIndirect (void)
893 /* Handle the indirection operaror * */
899 /* Skip the operator */
902 /* Get the operand */
906 if (!IsClassPtr (Op->Type)) {
908 /* Print diagnostics */
909 Error (ERR_ILLEGAL_INDIRECT);
911 /* Free the problematic node */
914 /* Return something that is safe later ### */
915 return GetIntNode (0);
919 /* Get the type of the result */
920 ResultType = Indirect (Op->Type);
922 /* The result is an lvalue if it is not an array */
923 LVal = IsTypeArray (ResultType)? RVALUE : LVALUE;
925 /* Create the operator node and return it */
926 return AllocExprNode (NT_INDIRECT, ResultType, LVal);
931 static ExprNode* DoSizeOf (void)
932 /* Handle the sizeof operator */
937 /* Skip the left paren */
940 /* A type or an actual variable access may follow */
943 type Type[MAXTYPELEN];
945 /* A type in parenthesis. Skip the left paren. */
948 /* Read the type and calculate the size. */
949 Size = SizeOf (ParseType (Type));
951 /* Closing paren must follow */
956 /* Some other entity */
960 Size = SizeOf (N->Type);
967 /* Create a constant node with type size_t and return it */
968 N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
975 static ExprNode* DoTypeCast (void)
976 /* Handle type casts */
978 type TargetType[MAXTYPELEN];
982 /* Skip the left paren */
986 ParseType (TargetType);
991 /* Read the expression we have to cast */
994 /* As a minor optimization, check if the type is already correct. If so,
997 if (TypeCmp (TargetType, Op->Type) >= TC_EQUAL) {
999 /* Just return the operand as is */
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);
1014 static ExprNode* UnaryExpr (void)
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 ()) {
1023 /* Check the token */
1024 switch (CurTok.Tok) {
1028 return DoPreIncDec ();
1032 return DoUnaryPlusMinus ();
1035 return DoComplement ();
1038 return DoBoolNot ();
1041 return DoAddress ();
1044 return DoIndirect ();
1051 return DoTypeCast ();
1057 /* Call the lower level */
1058 return PostfixExpr ();
1065 static ExprNode* MultExpr (void)
1066 /* Handle multiplicative expressions: '*' '/' and '%' */
1068 /* Get the left leave */
1069 ExprNode* Root = UnaryExpr ();
1071 /* Check if this is for us */
1072 while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV || CurTok.Tok == TOK_MOD) {
1074 switch (CurTok.Tok) {
1086 Internal ("Unexpected token");
1091 /* Return the resulting expression */
1097 static ExprNode* AddExpr (void)
1098 /* Handle additive expressions: '+' and '-' */
1100 /* Get the left leave */
1101 ExprNode* Root = MultExpr ();
1103 /* Check if this is for us */
1104 while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
1106 switch (CurTok.Tok) {
1115 Internal ("Unexpected token");
1120 /* Return the resulting expression */
1126 static ExprNode* ShiftExpr (void)
1127 /* Handle shift expressions: '<<' and '>>' */
1129 /* Get the left leave */
1130 ExprNode* Root = AddExpr ();
1132 /* Check if this is for us */
1133 while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
1135 switch (CurTok.Tok) {
1144 Internal ("Unexpected token");
1149 /* Return the resulting expression */
1155 static ExprNode* RelationalExpr (void)
1156 /* Handle relational expressions: '<=', '<', '>=' and '>' */
1158 /* Get the left leave */
1159 ExprNode* Root = ShiftExpr ();
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) {
1165 switch (CurTok.Tok) {
1180 Internal ("Unexpected token");
1185 /* Return the resulting expression */
1191 static ExprNode* EqualityExpr (void)
1192 /* Handle equality expressions: '==' and '!=' */
1194 /* Get the left leave */
1195 ExprNode* Root = RelationalExpr ();
1197 /* Check if this is for us */
1198 while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE) {
1200 switch (CurTok.Tok) {
1209 Internal ("Unexpected token");
1214 /* Return the resulting expression */
1220 static ExprNode* AndExpr (void)
1221 /* Handle and expressions: '&' */
1223 /* Get the left leave */
1224 ExprNode* Root = EqualityExpr ();
1226 /* Check if this is for us */
1227 while (CurTok.Tok == TOK_AND) {
1229 switch (CurTok.Tok) {
1235 Internal ("Unexpected token");
1240 /* Return the resulting expression */
1246 static ExprNode* XorExpr (void)
1247 /* Handle xor expressions: '^' */
1249 /* Get the left leave */
1250 ExprNode* Root = AndExpr ();
1252 /* Check if this is for us */
1253 while (CurTok.Tok == TOK_XOR) {
1255 switch (CurTok.Tok) {
1261 Internal ("Unexpected token");
1266 /* Return the resulting expression */
1272 static ExprNode* OrExpr (void)
1273 /* Handle or expressions: '|' */
1275 /* Get the left leave */
1276 ExprNode* Root = XorExpr ();
1278 /* Check if this is for us */
1279 while (CurTok.Tok == TOK_OR) {
1281 switch (CurTok.Tok) {
1287 Internal ("Unexpected token");
1292 /* Return the resulting expression */
1298 static ExprNode* BoolAndExpr (void)
1299 /* Handle boolean and expressions: '&&' */
1301 /* Get the left leave */
1302 ExprNode* Root = OrExpr ();
1304 /* Check if this is for us */
1305 while (CurTok.Tok == TOK_BOOL_AND) {
1307 switch (CurTok.Tok) {
1313 Internal ("Unexpected token");
1318 /* Return the resulting expression */
1324 static ExprNode* BoolOrExpr (void)
1325 /* Handle boolean or expressions: '||' */
1327 /* Get the left leave */
1328 ExprNode* Root = BoolAndExpr ();
1330 /* Check if this is for us */
1331 while (CurTok.Tok == TOK_BOOL_OR) {
1333 switch (CurTok.Tok) {
1339 Internal ("Unexpected token");
1344 /* Return the resulting expression */
1350 static ExprNode* ConditionalExpr (void)
1351 /* Handle the ternary operator: ':?' */
1353 /* Get the left leave */
1354 ExprNode* Cond = BoolOrExpr ();
1356 /* Check if this is for us */
1357 if (CurTok.Tok == TOK_QUEST) {
1365 /* Skip the token */
1368 /* Get the first expression */
1369 Expr1 = Expression ();
1371 /* Colon must follow */
1374 /* Get the second expression */
1375 Expr2 = ConditionalExpr ();
1377 /* Get the common type of the two expressions */
1378 Type = CommonType (Expr1->Type, Expr2->Type);
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);
1386 /* Return the result */
1391 /* Just return the lower level expression */