/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
+/* (C) 2000-2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
static ExprNode* UnaryExpr (void);
-ExprNode* Expr1 (void);
-ExprNode* Expr0 (void);
+ExprNode* AssignExpr (void);
+ExprNode* Expression (void);
static int IsTypeExpr (void)
-/* Return true if some sort of variable or type is waiting (helper for cast
- * and sizeof() in hie10).
- */
+/* Return true if some sort of variable or type is waiting */
{
SymEntry* Entry;
- return curtok == TOK_LPAREN && (
+ return CurTok.Tok == TOK_LPAREN && (
(nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
(nxttok == TOK_CONST) ||
(nxttok == TOK_IDENT &&
+static int GetBoolRep (const ExprNode* N)
+/* Get the boolean representation of a constant expression node */
+{
+ if (IsClassInt (N->Type)) {
+ /* An integer constant */
+ return (N->IVal != 0);
+ } else if (IsClassFloat (N->Type)) {
+ /* A float constant */
+ return (N->FVal != 0.0);
+ } else if (IsTypeArray (N->Type) && IsTypeChar (Indirect (N->Type))) {
+ /* A string constant - useless but allowed */
+ return 1;
+ } else {
+ Internal ("GetBoolRep: Unknown type");
+ /* NOTREACHED */
+ return 0;
+ }
+}
+
+
+
/*****************************************************************************/
/* Expression node helper functions */
/*****************************************************************************/
*/
{
ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
- N->V.I = Value;
+ N->IVal = Value;
return N;
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
N = AllocExprNode (NT_ASM, type_void, RVALUE);
/* String literal */
- if (curtok != TOK_SCONST) {
+ if (CurTok.Tok != TOK_SCONST) {
/* Print an error */
- Error (ERR_STRLIT_EXPECTED);
+ Error ("String literal expected");
/* To be on the safe side later, insert an empty asm string */
AppendItem (N, xstrdup (""));
} else {
/* Insert a copy of the string into the expression node */
- AppendItem (N, xstrdup (GetLiteral (curval)));
+ AppendItem (N, xstrdup (GetLiteral (CurTok.IVal)));
/* Reset the string pointer, effectivly clearing the string from the
* string table. Since we're working with one token lookahead, this
* will fail if the next token is also a string token, but that's a
* syntax error anyway, because we expect a right paren.
*/
- ResetLiteralOffs (curval);
+ ResetLiteralPoolOffs (CurTok.IVal);
}
/* Skip the string token */
/* Process a parenthesized subexpression. In this case we don't need to
* allocate a new node ourselves.
*/
- if (curtok == TOK_LPAREN) {
+ if (CurTok.Tok == TOK_LPAREN) {
NextToken ();
- N = Expr0 ();
+ N = Expression ();
ConsumeRParen ();
return N;
}
/* Check for an integer or character constant */
- if (curtok == TOK_ICONST || curtok == TOK_CCONST) {
+ if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
/* Create the new node */
N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
- N->V.I = CurTok.IVal;
+ N->IVal = CurTok.IVal;
/* Skip the token and return the result */
NextToken ();
}
/* Check for a float constant */
- if (curtok == TOK_FCONST) {
+ if (CurTok.Tok == TOK_FCONST) {
/* Create the new node */
N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
- N->V.F = CurTok.FVal;
+ N->FVal = CurTok.FVal;
/* Skip the token and return the result */
NextToken ();
*/
if (Preprocessing) {
/* Illegal expression in PP mode */
- Error (ERR_CPP_EXPR_EXPECTED);
+ Error ("Preprocessor expression expected");
/* Skip the token for error recovery */
NextToken ();
}
/* Identifier? */
- if (curtok == TOK_IDENT) {
+ if (CurTok.Tok == TOK_IDENT) {
/* Identifier */
SymEntry* Sym;
/* Check for illegal symbol types */
if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
/* Cannot use labels in expressions */
- Error (ERR_SYMBOL_KIND);
+ Error ("Cannot use a label in an expression");
return GetIntNode (0);
} else if (Sym->Flags & SC_TYPE) {
/* Cannot use type symbols */
- Error (ERR_VAR_IDENT_EXPECTED);
+ Error ("Cannot use a type in an expression");
/* Assume an int type to make lval valid */
return GetIntNode (0);
}
- /* Handle enum values as constant integers */
- if ((Sym->Flags & SC_ENUM) == SC_ENUM) {
+ /* Handle constants including enum values */
+ if ((Sym->Flags & SC_CONST) == SC_CONST) {
- N = GetIntNode (Sym->V.EnumVal);
+ N = AllocExprNode (NT_CONST, Sym->Type, RVALUE);
+ N->IVal = Sym->V.ConstVal;
} else {
/* IDENT is either an auto-declared function or an undefined
* variable.
*/
- if (curtok == TOK_LPAREN) {
+ if (CurTok.Tok == TOK_LPAREN) {
/* Warn about the use of a function without prototype */
- Warning (WARN_FUNC_WITHOUT_PROTO);
+ Warning ("Function call without a prototype");
/* Declare a function returning int. For that purpose, prepare
* a function signature for a function having an empty param
} else {
/* Print an error about an undeclared variable */
- Error (ERR_UNDEFINED_SYMBOL, Ident);
+ Error ("Undefined symbiol: `%s'", Ident);
/* Undeclared Variable */
Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
}
- } else if (curtok == TOK_SCONST) {
+ } else if (CurTok.Tok == TOK_SCONST) {
/* String literal */
- N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (curval))), RVALUE);
- N->V.I = curval;
+ N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (CurTok.IVal))), RVALUE);
+ N->IVal = CurTok.IVal;
- } else if (curtok == TOK_ASM) {
+ } else if (CurTok.Tok == TOK_ASM) {
/* ASM statement? */
N = DoAsm ();
- } else if (curtok == TOK_A) {
+ } else if (CurTok.Tok == TOK_A) {
/* A register */
N = AllocExprNode (NT_REG_A, type_uchar, LVALUE);
- } else if (curtok == TOK_X) {
+ } else if (CurTok.Tok == TOK_X) {
/* X register */
N = AllocExprNode (NT_REG_X, type_uchar, LVALUE);
- } else if (curtok == TOK_Y) {
+ } else if (CurTok.Tok == TOK_Y) {
/* Y register */
N = AllocExprNode (NT_REG_Y, type_uchar, LVALUE);
- } else if (curtok == TOK_AX) {
+ } else if (CurTok.Tok == TOK_AX) {
/* AX pseudo register */
N = AllocExprNode (NT_REG_AX, type_uint, LVALUE);
- } else if (curtok == TOK_EAX) {
+ } else if (CurTok.Tok == TOK_EAX) {
/* EAX pseudo register */
N = AllocExprNode (NT_REG_EAX, type_ulong, LVALUE);
} else {
/* Illegal primary. */
- Error (ERR_EXPR_EXPECTED);
+ Error ("Expression expected");
N = GetIntNode (0);
}
NextToken ();
/* Get the index */
- Right = Expr0 ();
+ Right = Expression ();
/* Check the types. As special "C" feature, accept a reversal of base and
- * index types:
- * char C = 3["abcdefg"];
- * is legal C!
+ * index types: char C = 3["abcdefg"] is legal C!
*/
if (IsClassPtr (Left->Type)) {
/* Right side must be some sort of integer */
if (!IsClassInt (Right->Type)) {
/* Print an error */
- Error (ERR_CANNOT_SUBSCRIPT);
+ Error ("Invalid subscript");
/* To avoid problems later, create a new, legal subscript
* expression
*/
ExprNode* Tmp;
/* Left side must be some sort of integer */
- if (!IsClassInt (Right->Type)) {
+ if (!IsClassInt (Left->Type)) {
/* Print an error */
- Error (ERR_CANNOT_SUBSCRIPT);
+ Error ("Invalid subscript");
/* To avoid problems later, create a new, legal subscript
* expression
*/
/* Invalid array expression. Skip the closing bracket, then return
* an integer instead of the array expression to be safe later.
*/
- Error (ERR_CANNOT_SUBSCRIPT);
+ Error ("Invalid subscript");
ConsumeRBrack ();
return GetIntNode (0);
}
/* Type check */
StructType = Left->Type;
- if (curtok == TOK_PTR_REF) {
+ if (CurTok.Tok == TOK_PTR_REF) {
NT = NT_STRUCTPTR_ACCESS;
if (!IsTypePtr (StructType)) {
- Error (ERR_STRUCT_PTR_EXPECTED);
+ Error ("Struct pointer expected");
return GetIntNode (0);
}
StructType = Indirect (StructType);
NT = NT_STRUCT_ACCESS;
}
if (!IsClassStruct (StructType)) {
- Error (ERR_STRUCT_EXPECTED);
+ Error ("Struct expected");
return GetIntNode (0);
}
/* Skip the token and check for an identifier */
NextToken ();
- if (curtok != TOK_IDENT) {
+ if (CurTok.Tok != TOK_IDENT) {
/* Print an error */
- Error (ERR_IDENT_EXPECTED);
+ Error ("Identifier expected");
/* Return an integer expression instead */
return GetIntNode (0);
}
Field = FindStructField (StructType, Ident);
if (Field == 0) {
/* Struct field not found */
- Error (ERR_STRUCT_FIELD_MISMATCH, Ident);
+ Error ("Struct/union has no field named `%s'", Ident);
/* Return an integer expression instead */
return GetIntNode (0);
}
if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
/* Call to non function */
- Error (ERR_ILLEGAL_FUNC_CALL);
+ Error ("Illegal function call");
- /* Free the old node */
- FreeExprNode (Left);
+ /* Free the old tree */
+ FreeExprTree (Left);
/* Return something safe */
return GetIntNode (0);
ParamSize = 0;
ParamCount = 0;
Ellipsis = 0;
- while (curtok != TOK_RPAREN) {
+ while (CurTok.Tok != TOK_RPAREN) {
/* Count arguments */
++ParamCount;
}
} else if (!Ellipsis) {
/* Too many arguments. Do we have an open param list? */
- if ((Func->Flags & FD_ELLIPSIS) == 0) {
+ if ((Func->Flags & FD_VARIADIC) == 0) {
/* End of param list reached, no ellipsis */
- Error (ERR_TOO_MANY_FUNC_ARGS);
+ Error ("Too many function arguments");
}
/* Assume an ellipsis even in case of errors to avoid an error
* message for each other argument.
}
/* Get the parameter value expression tree and add it to the parameter
- * list. (### check expr level)
+ * list.
*/
- AppendItem (Root, Expr1 ());
+ AppendItem (Root, AssignExpr ());
/* Check for end of argument list */
- if (curtok != TOK_COMMA) {
+ if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
/* Check if we had enough parameters */
if (ParamCount < Func->ParamCount) {
- Error (ERR_TOO_FEW_FUNC_ARGS);
+ Error ("Too few function arguments");
}
/* Return the function call node */
ExprNode* Root;
/* Determine the type of the node */
- nodetype_t NT = (curtok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
+ nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
/* Skip the operator token */
NextToken ();
if (Left->LValue == 0) {
/* Print a diagnostics */
- Error (ERR_LVALUE_EXPECTED);
+ Error ("lvalue expected");
/* It is safe to return the operand expression and probably better
* than returning an int, since the operand expression already has
static ExprNode* PostfixExpr (void)
+/* Handle a postfix expression */
{
/* Get the lower level expression */
ExprNode* Root = Primary ();
/* */
- while (curtok == TOK_LBRACK || curtok == TOK_LPAREN ||
- curtok == TOK_DOT || curtok == TOK_PTR_REF ||
- curtok == TOK_INC || curtok == TOK_DEC) {
+ while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN ||
+ CurTok.Tok == TOK_DOT || CurTok.Tok == TOK_PTR_REF ||
+ CurTok.Tok == TOK_INC || CurTok.Tok == TOK_DEC) {
/* This is for us */
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_LBRACK:
Root = DoArray (Root);
ExprNode* Root;
/* Determine the type of the node */
- nodetype_t NT = (curtok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
+ nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
/* Skip the operator token */
NextToken ();
if (Op->LValue == 0) {
/* Print a diagnostics */
- Error (ERR_LVALUE_EXPECTED);
+ Error ("lvalue expected");
/* It is safe to return the operand expression and probably better
* than returning an int, since the operand expression already has
ExprNode* Root;
/* Remember the current token for later, then skip it */
- token_t Tok = curtok;
+ token_t Tok = CurTok.Tok;
NextToken ();
/* Get the operand */
/* Type check */
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
- /* Display diagnostic */
- Error (ERR_SYNTAX);
+ /* Output diagnostic */
+ Error ("Syntax error");
/* Free the errorneous node */
- FreeExprNode (Op);
+ FreeExprTree (Op);
/* Return something that makes sense later */
return GetIntNode (0);
/* The value is constant, change it according to the insn */
if (IsClassInt (Op->Type)) {
/* Integer */
- Op->V.I = -Op->V.I;
+ Op->IVal = -Op->IVal;
} else {
/* Float */
- Op->V.F = -Op->V.F;
+ Op->FVal = -Op->FVal;
}
/* Return the operand itself */
if (!IsClassInt (Op->Type)) {
/* Display diagnostic */
- Error (ERR_OP_NOT_ALLOWED);
+ Error ("Operation not allowed on this type");
/* Free the errorneous node */
- FreeExprNode (Op);
+ FreeExprTree (Op);
/* Return something that makes sense later */
return GetIntNode (0);
if (Op->NT == NT_CONST) {
/* Change the value and return the operand node */
- Op->V.I = ~Op->V.I;
+ Op->IVal = ~Op->IVal;
return Op;
} else {
ExprNode* Root;
/* Print diagnostics */
- Error (ERR_ILLEGAL_ADDRESS);
+ Error ("Cannot take address of rvalue");
- /* Free the problematic node */
- FreeExprNode (Op);
+ /* Free the problematic tree */
+ FreeExprTree (Op);
/* Return something that is safe later */
Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
- Root->V.I = 0;
return Root;
}
static ExprNode* DoIndirect (void)
-/* Handle the indirection operaror * */
+/* Handle the indirection operator * */
{
ExprNode* Op;
type* ResultType;
if (!IsClassPtr (Op->Type)) {
/* Print diagnostics */
- Error (ERR_ILLEGAL_INDIRECT);
+ Error ("Illegal indirection");
- /* Free the problematic node */
- FreeExprNode (Op);
+ /* Free the problematic tree */
+ FreeExprTree (Op);
/* Return something that is safe later ### */
return GetIntNode (0);
Size = SizeOf (N->Type);
/* Free the node */
- FreeExprNode (N);
+ FreeExprTree (N);
}
/* Create a constant node with type size_t and return it */
N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
- N->V.I = Size;
+ N->IVal = Size;
return N;
}
} else {
- /* Must be casted. Setup the expression tree and return the new node */
- Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
+ /* Must be casted. Setup the expression tree and return the new node */
+ Root = AllocExprNode (NT_TYPECAST, TargetType, RVALUE);
SetLeftNode (Root, Op);
return Root;
static ExprNode* UnaryExpr (void)
{
/* */
- if (curtok == TOK_INC || curtok == TOK_DEC ||
- curtok == TOK_PLUS || curtok == TOK_MINUS ||
- curtok == TOK_COMP || curtok == TOK_BOOL_NOT ||
- curtok == TOK_AND || curtok == TOK_STAR ||
- curtok == TOK_SIZEOF || IsTypeExpr ()) {
+ if (CurTok.Tok == TOK_INC || CurTok.Tok == TOK_DEC ||
+ CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS ||
+ CurTok.Tok == TOK_COMP || CurTok.Tok == TOK_BOOL_NOT ||
+ CurTok.Tok == TOK_AND || CurTok.Tok == TOK_STAR ||
+ CurTok.Tok == TOK_SIZEOF || IsTypeExpr ()) {
/* Check the token */
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_INC:
case TOK_DEC:
case TOK_PLUS:
case TOK_MINUS:
- return DoUnaryPlusMinus ();
+ return DoUnaryPlusMinus ();
case TOK_COMP:
return DoComplement ();
case TOK_SIZEOF:
return DoSizeOf ();
- default:
- /* Type cast */
- return DoTypeCast ();
+ default:
+ /* Type cast */
+ return DoTypeCast ();
+
+ }
+
+ } else {
+
+ /* Call the lower level */
+ return PostfixExpr ();
+
+ }
+}
+
+
+
+static ExprNode* DoMul (ExprNode* Left)
+/* Handle multiplication */
+{
+ type TargetType[MAXTYPELEN];
+ ExprNode* Right;
+ ExprNode* Root;
+
+ /* Check the type of the left operand */
+ if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
+ Error ("Invalid left operand to binary operator `*'");
+ FreeExprTree (Left);
+ Left = GetIntNode (0);
+ }
+
+ /* Skip the operator token */
+ NextToken ();
+
+ /* Read the right expression */
+ Right = UnaryExpr ();
+
+ /* Check the type of the right operand */
+ if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
+ Error ("Invalid right operand to binary operator `*'");
+ FreeExprTree (Right);
+ Right = GetIntNode (0);
+ }
+
+ /* Make the root node */
+ Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
+ SetLeftNode (Root, Left);
+ SetRightNode (Root, Right);
+
+ return Root;
+}
+
+
+
+static ExprNode* MultExpr (void)
+/* Handle multiplicative expressions: '*' '/' and '%' */
+{
+ /* Get the left leave */
+ ExprNode* Root = UnaryExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV || CurTok.Tok == TOK_MOD) {
+
+ switch (CurTok.Tok) {
+
+ case TOK_MUL:
+ Root = DoMul (Root);
+ break;
+
+ case TOK_DIV:
+ break;
+
+ case TOK_MOD:
+ break;
+
+ default:
+ Internal ("Unexpected token");
+ }
+
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* AddExpr (void)
+/* Handle additive expressions: '+' and '-' */
+{
+ /* Get the left leave */
+ ExprNode* Root = MultExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
+
+ switch (CurTok.Tok) {
+
+ case TOK_PLUS:
+ break;
+
+ case TOK_MINUS:
+ break;
+
+ default:
+ Internal ("Unexpected token");
+ }
+
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* ShiftExpr (void)
+/* Handle shift expressions: '<<' and '>>' */
+{
+ /* Get the left leave */
+ ExprNode* Root = AddExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) {
+
+ switch (CurTok.Tok) {
+
+ case TOK_SHL:
+ break;
+
+ case TOK_SHR:
+ break;
+
+ default:
+ Internal ("Unexpected token");
+ }
+
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* RelationalExpr (void)
+/* Handle relational expressions: '<=', '<', '>=' and '>' */
+{
+ /* Get the left leave */
+ ExprNode* Root = ShiftExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_LE || CurTok.Tok == TOK_LT ||
+ CurTok.Tok == TOK_GE || CurTok.Tok == TOK_GT) {
+
+ switch (CurTok.Tok) {
+
+ case TOK_LE:
+ break;
+
+ case TOK_LT:
+ break;
+
+ case TOK_GE:
+ break;
+
+ case TOK_GT:
+ break;
+
+ default:
+ Internal ("Unexpected token");
+ }
+
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* EqualityExpr (void)
+/* Handle equality expressions: '==' and '!=' */
+{
+ /* Get the left leave */
+ ExprNode* Root = RelationalExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE) {
+
+ switch (CurTok.Tok) {
+
+ case TOK_EQ:
+ break;
+
+ case TOK_NE:
+ break;
+
+ default:
+ Internal ("Unexpected token");
+ }
+
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* AndExpr (void)
+/* Handle and expressions: '&' */
+{
+ /* Get the left leave */
+ ExprNode* Root = EqualityExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_AND) {
+
+ ExprNode* Left = Root;
+ ExprNode* Right;
+
+ /* Skip the token */
+ NextToken ();
+
+ /* Get the right operand */
+ Right = EqualityExpr ();
+
+ /* Type check */
+ if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
+ /* Print a diagnostic */
+ Error ("Operation not allowed for these types");
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create something safe */
+ Root = GetIntNode (0);
+
+ } else {
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) & GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_AND, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
}
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* XorExpr (void)
+/* Handle xor expressions: '^' */
+{
+ /* Get the left leave */
+ ExprNode* Root = AndExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_XOR) {
+
+ ExprNode* Left = Root;
+ ExprNode* Right;
+
+ /* Skip the token */
+ NextToken ();
+
+ /* Get the right operand */
+ Right = AndExpr ();
+
+ /* Type check */
+ if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
+
+ /* Print a diagnostic */
+ Error ("Operation not allowed for these types");
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create something safe */
+ Root = GetIntNode (0);
+
+ } else {
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) ^ GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_XOR, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
+ }
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* OrExpr (void)
+/* Handle or expressions: '|' */
+{
+ /* Get the left leave */
+ ExprNode* Root = XorExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_OR) {
+
+ ExprNode* Left = Root;
+ ExprNode* Right;
+
+ /* Skip the token */
+ NextToken ();
+
+ /* Get the right operand */
+ Right = XorExpr ();
+
+ /* Type check */
+ if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
+
+ /* Print a diagnostic */
+ Error ("Operation not allowed for these types");
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create something safe */
+ Root = GetIntNode (0);
+
+ } else {
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) | GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_OR, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
+ }
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* BoolAndExpr (void)
+/* Handle boolean and expressions: '&&' */
+{
+ /* Get the left leave */
+ ExprNode* Root = OrExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_BOOL_AND) {
+
+ ExprNode* Left = Root;
+ ExprNode* Right;
+
+ /* Skip the token */
+ NextToken ();
+
+ /* Get the right operand */
+ Right = OrExpr ();
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) && GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_BOOL_AND, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
+
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* BoolOrExpr (void)
+/* Handle boolean or expressions: '||' */
+{
+ /* Get the left leave */
+ ExprNode* Root = BoolAndExpr ();
+
+ /* Check if this is for us */
+ while (CurTok.Tok == TOK_BOOL_OR) {
+
+ ExprNode* Left = Root;
+ ExprNode* Right;
+
+ /* Skip the token */
+ NextToken ();
+
+ /* Get the right operand */
+ Right = BoolAndExpr ();
+
+ /* Check if both operands are constant */
+ if (Left->NT == NT_CONST && Right->NT == NT_CONST) {
+
+ /* Get the constant result */
+ int Result = GetBoolRep (Left) && GetBoolRep (Right);
+
+ /* Remove the unneeded nodes */
+ FreeExprTree (Right);
+ FreeExprTree (Left);
+
+ /* Create a constant result */
+ Root = GetIntNode (Result);
+
+ } else {
+
+ /* Make an operator node */
+ Root = AllocExprNode (NT_BOOL_OR, type_int, RVALUE);
+ SetRightNode (Root, Right);
+ SetLeftNode (Root, Left);
+
+ }
+
+ }
+
+ /* Return the resulting expression */
+ return Root;
+}
+
+
+
+static ExprNode* ConditionalExpr (void)
+/* Handle the ternary operator: ':?' */
+{
+ /* Get the left leave */
+ ExprNode* Cond = BoolOrExpr ();
+
+ /* Check if this is for us */
+ if (CurTok.Tok == TOK_QUEST) {
+
+ ExprNode* Expr1;
+ ExprNode* Expr2;
+ ExprNode* Root;
+ type* Type;
+
+
+ /* Skip the token */
+ NextToken ();
+
+ /* Get the first expression */
+ Expr1 = Expression ();
+
+ /* Colon must follow */
+ ConsumeColon ();
+
+ /* Get the second expression */
+ Expr2 = ConditionalExpr ();
+
+ /* Get the common type of the two expressions */
+ Type = CommonType (Expr1->Type, Expr2->Type);
+
+ /* Create a new ternary token node */
+ Root = AllocExprNode (NT_TERNARY, Type, RVALUE);
+ AppendItem (Root, Cond);
+ AppendItem (Root, Expr1);
+ AppendItem (Root, Expr2);
+
+ /* Return the result */
+ return Root;
} else {
- /* Call the lower level */
- return PostfixExpr ();
+ /* Just return the lower level expression */
+ return Cond;
}
}
+
+
+