]> git.sur5r.net Git - cc65/blobdiff - src/cc65/parser.c
Improved implementation of OptPushPop
[cc65] / src / cc65 / parser.c
index 1cd0297ae5bde9ccbafb20561019090940a0d102..ec1dfcc43941a6bac49116d27103676969179b81 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000     Ullrich von Bassewitz                                       */
+/* (C) 2000-2001 Ullrich von Bassewitz                                       */
 /*               Wacholderweg 14                                             */
 /*               D-70597 Stuttgart                                           */
 /* EMail:        uz@musoftware.de                                            */
@@ -67,8 +67,8 @@
 
 
 static ExprNode* UnaryExpr (void);
-ExprNode* Expr1 (void);
-ExprNode* Expr0 (void);
+ExprNode* AssignExpr (void);
+ExprNode* Expression (void);
 
 
 
@@ -79,13 +79,11 @@ ExprNode* Expr0 (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                               &&
@@ -96,6 +94,27 @@ static int IsTypeExpr (void)
 
 
 
+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                      */
 /*****************************************************************************/
@@ -109,14 +128,14 @@ static ExprNode* GetIntNode (int Value)
  */
 {
     ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
-    N->V.I = Value;
+    N->IVal = Value;
     return N;
 }
 
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                  Code                                    */
 /*****************************************************************************/
 
 
@@ -140,10 +159,10 @@ ExprNode* DoAsm (void)
     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 (""));
@@ -151,14 +170,14 @@ ExprNode* DoAsm (void)
     } 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 */
@@ -181,19 +200,19 @@ static ExprNode* Primary (void)
     /* 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 ();
@@ -201,11 +220,11 @@ static ExprNode* Primary (void)
     }
 
     /* 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 ();
@@ -217,7 +236,7 @@ static ExprNode* Primary (void)
      */
     if (Preprocessing) {
                /* Illegal expression in PP mode */
-       Error (ERR_CPP_EXPR_EXPECTED);
+       Error ("Preprocessor expression expected");
 
        /* Skip the token for error recovery */
        NextToken ();
@@ -227,7 +246,7 @@ static ExprNode* Primary (void)
     }
 
     /* Identifier? */
-    if (curtok == TOK_IDENT) {
+    if (CurTok.Tok == TOK_IDENT) {
 
        /* Identifier */
        SymEntry* Sym;
@@ -245,19 +264,20 @@ static ExprNode* Primary (void)
            /* 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 {
 
@@ -283,10 +303,10 @@ static ExprNode* Primary (void)
            /* 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
@@ -299,7 +319,7 @@ static ExprNode* Primary (void)
            } 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);
@@ -310,38 +330,38 @@ static ExprNode* Primary (void)
 
        }
 
-    } 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);
@@ -349,7 +369,7 @@ static ExprNode* Primary (void)
     } else {
 
        /* Illegal primary. */
-       Error (ERR_EXPR_EXPECTED);
+       Error ("Expression expected");
                N = GetIntNode (0);
 
     }
@@ -372,18 +392,16 @@ static ExprNode* DoArray (ExprNode* Left)
     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
             */
@@ -394,9 +412,9 @@ static ExprNode* DoArray (ExprNode* Left)
        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
             */
@@ -412,7 +430,7 @@ static ExprNode* DoArray (ExprNode* Left)
        /* 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);
     }
@@ -451,10 +469,10 @@ static ExprNode* DoStruct (ExprNode* Left)
 
     /* 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);
@@ -462,15 +480,15 @@ static ExprNode* DoStruct (ExprNode* Left)
        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);
     }
@@ -481,7 +499,7 @@ static ExprNode* DoStruct (ExprNode* Left)
     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);
     }
@@ -520,10 +538,10 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
     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);
@@ -552,7 +570,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
     ParamSize  = 0;
     ParamCount = 0;
     Ellipsis   = 0;
-    while (curtok != TOK_RPAREN) {
+    while (CurTok.Tok != TOK_RPAREN) {
 
        /* Count arguments */
        ++ParamCount;
@@ -569,9 +587,9 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
            }
        } 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.
@@ -580,12 +598,12 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
        }
 
                /* 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 ();
@@ -596,7 +614,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
 
     /* 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 */
@@ -605,18 +623,54 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
 
 
 
+static ExprNode* DoPostIncDec (ExprNode* Left)
+/* Handle postincrement and postdecrement */
+{
+    ExprNode* Root;
+
+    /* Determine the type of the node */
+    nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
+
+    /* Skip the operator token */
+    NextToken ();
+
+    /* The operand must be an lvalue */
+    if (Left->LValue == 0) {
+
+       /* Print a diagnostics */
+       Error ("lvalue expected");
+
+       /* It is safe to return the operand expression and probably better
+        * than returning an int, since the operand expression already has
+        * the correct type as expected by the program at this place, and
+        * it is even an rvalue.
+        */
+       return Left;
+    }
+
+    /* Setup the expression tree */
+    Root = AllocExprNode (NT, Left->Type, RVALUE);
+    SetLeftNode (Root, Left);
+
+    /* Return the new node */
+    return Root;
+}
+
+
+
 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);
@@ -632,9 +686,8 @@ static ExprNode* PostfixExpr (void)
                break;
 
            case TOK_INC:
-               break;
-
            case TOK_DEC:
+               Root = DoPostIncDec (Root);
                break;
 
            default:
@@ -656,7 +709,7 @@ static ExprNode* DoPreIncDec (void)
     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 ();
@@ -668,7 +721,7 @@ static ExprNode* DoPreIncDec (void)
     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
@@ -695,7 +748,7 @@ static ExprNode* DoUnaryPlusMinus (void)
     ExprNode* Root;
 
     /* Remember the current token for later, then skip it */
-    token_t Tok = curtok;
+    token_t Tok = CurTok.Tok;
     NextToken ();
 
     /* Get the operand */
@@ -704,11 +757,11 @@ static ExprNode* DoUnaryPlusMinus (void)
     /* 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);
@@ -717,12 +770,26 @@ static ExprNode* DoUnaryPlusMinus (void)
     /* In case of PLUS, we must do nothing */
     if (Tok == TOK_PLUS) {
 
-       /* Use the operand unchanged */
-       Root = Op;
+               /* Return the operand unchanged */
+       return Op;
+
+    } else if (Op->NT == NT_CONST) {
+
+       /* The value is constant, change it according to the insn */
+       if (IsClassInt (Op->Type)) {
+           /* Integer */
+           Op->IVal = -Op->IVal;
+       } else {
+           /* Float */
+           Op->FVal = -Op->FVal;
+       }
+
+       /* Return the operand itself */
+       return Op;
 
     } else {
 
-       /* Setup the expression tree */
+               /* Non constant value, setup the expression tree */
        Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
        SetLeftNode (Root, Op);
 
@@ -734,17 +801,245 @@ static ExprNode* DoUnaryPlusMinus (void)
 
 
 
+static ExprNode* DoComplement (void)
+/* Handle ~ */
+{
+    ExprNode* Op;
+    ExprNode* Root;
+
+    /* Skip the operator token */
+    NextToken ();
+
+    /* Get the operand */
+    Op = UnaryExpr ();
+
+    /* Type check */
+    if (!IsClassInt (Op->Type)) {
+
+       /* Display diagnostic */
+       Error ("Operation not allowed on this type");
+
+       /* Free the errorneous node */
+       FreeExprTree (Op);
+
+       /* Return something that makes sense later */
+       return GetIntNode (0);
+    }
+
+    /* If the operand is constant, handle the operation directly */
+    if (Op->NT == NT_CONST) {
+
+       /* Change the value and return the operand node */
+       Op->IVal = ~Op->IVal;
+       return Op;
+
+    } else {
+
+       /* Setup the expression tree and return the new node */
+       Root = AllocExprNode (NT_COMPLEMENT, Op->Type, RVALUE);
+       SetLeftNode (Root, Op);
+       return Root;
+    }
+}
+
+
+
+static ExprNode* DoBoolNot (void)
+/* Handle ! */
+{
+    ExprNode* Op;
+    ExprNode* Root;
+
+    /* Skip the operator token */
+    NextToken ();
+
+    /* Get the operand */
+    Op = UnaryExpr ();
+
+    /* The boolean NOT operator eats anything - no need for a type check. */
+
+    /* Setup the expression tree and return the new node */
+    Root = AllocExprNode (NT_BOOL_NOT, type_int, RVALUE);
+    SetLeftNode (Root, Op);
+    return Root;
+}
+
+
+
+static ExprNode* DoAddress (void)
+/* Handle the address operator & */
+{
+    ExprNode* Op;
+
+    /* Skip the operator */
+    NextToken ();
+
+    /* Get the operand */
+    Op = UnaryExpr ();
+
+    /* Accept using the address operator with arrays. This is harmless, it
+     * will just be as using the array without the operator.
+     */
+    if (IsTypeArray (Op->Type)) {
+       return Op;
+    }
+
+    /* We cannot operate on rvalues */
+    if (Op->LValue == 0) {
+
+       ExprNode* Root;
+
+       /* Print diagnostics */
+       Error ("Cannot take address of rvalue");
+
+       /* Free the problematic tree */
+       FreeExprTree (Op);
+
+       /* Return something that is safe later */
+       Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
+       return Root;
+
+    }
+
+    /* Create the operator node and return it */
+    return AllocExprNode (NT_ADDRESS, PointerTo (Op->Type), RVALUE);
+}
+
+
+
+static ExprNode* DoIndirect (void)
+/* Handle the indirection operator * */
+{
+    ExprNode* Op;
+    type*     ResultType;
+    int              LVal;
+
+    /* Skip the operator */
+    NextToken ();
+
+    /* Get the operand */
+    Op = UnaryExpr ();
+
+    /* Type check */
+    if (!IsClassPtr (Op->Type)) {
+
+       /* Print diagnostics */
+       Error ("Illegal indirection");
+
+       /* Free the problematic tree */
+       FreeExprTree (Op);
+
+       /* Return something that is safe later ### */
+       return GetIntNode (0);
+
+    }
+
+    /* Get the type of the result */
+    ResultType = Indirect (Op->Type);
+
+    /* The result is an lvalue if it is not an array */
+    LVal = IsTypeArray (ResultType)? RVALUE : LVALUE;
+
+    /* Create the operator node and return it */
+    return AllocExprNode (NT_INDIRECT, ResultType, LVal);
+}
+
+
+
+static ExprNode* DoSizeOf (void)
+/* Handle the sizeof operator */
+{
+    ExprNode*     N;
+    unsigned long Size;
+
+    /* Skip the left paren */
+    NextToken ();
+
+    /* A type or an actual variable access may follow */
+    if (IsTypeExpr ()) {
+
+               type    Type[MAXTYPELEN];
+
+               /* A type in parenthesis. Skip the left paren. */
+               NextToken ();
+
+               /* Read the type and calculate the size. */
+               Size = SizeOf (ParseType (Type));
+
+               /* Closing paren must follow */
+               ConsumeRParen ();
+
+    } else {
+
+               /* Some other entity */
+               N = UnaryExpr ();
+
+               /* Get the size */
+               Size = SizeOf (N->Type);
+
+               /* Free the node */
+               FreeExprTree (N);
+
+    }
+
+    /* Create a constant node with type size_t and return it */
+    N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
+    N->IVal = Size;
+    return N;
+}
+
+
+
+static ExprNode* DoTypeCast (void)
+/* Handle type casts */
+{
+    type      TargetType[MAXTYPELEN];
+    ExprNode* Op;
+    ExprNode* Root;
+
+    /* Skip the left paren */
+    NextToken ();
+
+    /* Read the type */
+    ParseType (TargetType);
+
+    /* Closing paren */
+    ConsumeRParen ();
+
+    /* Read the expression we have to cast */
+    Op = UnaryExpr ();
+
+    /* As a minor optimization, check if the type is already correct. If so,
+     * do nothing.
+     */
+    if (TypeCmp (TargetType, Op->Type) >= TC_EQUAL) {
+
+       /* Just return the operand as is */
+       return Op;
+
+    } else {
+
+       /* 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_AND    || curtok == TOK_STAR     ||
-               curtok == TOK_COMP   || curtok == TOK_BOOL_NOT ||
-               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:
@@ -752,32 +1047,563 @@ static ExprNode* UnaryExpr (void)
 
            case TOK_PLUS:
            case TOK_MINUS:
-               return DoUnaryPlusMinus ();
+                       return DoUnaryPlusMinus ();
+
+           case TOK_COMP:
+               return DoComplement ();
+
+           case TOK_BOOL_NOT:
+               return DoBoolNot ();
 
            case TOK_AND:
-               break;
+               return DoAddress ();
 
            case TOK_STAR:
-               break;
+               return DoIndirect ();
 
-           case TOK_COMP:
-               break;
+           case TOK_SIZEOF:
+               return DoSizeOf ();
 
-           case TOK_BOOL_NOT:
-               break;
+           default:
+               /* Type cast */
+               return DoTypeCast ();
 
-           case TOK_SIZEOF:
+       }
+
+    } 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:
+           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;
 
     }
 }
+
+
+