]> git.sur5r.net Git - cc65/commitdiff
Working on the new parser
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 20 Aug 2000 09:25:47 +0000 (09:25 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 20 Aug 2000 09:25:47 +0000 (09:25 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@291 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/datatype.c
src/cc65/datatype.h
src/cc65/error.c
src/cc65/exprnode.h
src/cc65/parser.c

index 59a0adddd3b49da88e1e3d7b196eb99d0746c0c1..ba72fc1a8ec81d2fb62bf4c75d0b4fef7c850fd3 100644 (file)
@@ -51,7 +51,7 @@
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                  Data                                    */
 /*****************************************************************************/
 
 
@@ -63,6 +63,7 @@ type type_uint []     = { T_UINT,     T_END };
 type type_long []      = { T_LONG,     T_END };
 type type_ulong []     = { T_ULONG,    T_END };
 type type_void []      = { T_VOID,     T_END };
+type type_size_t []    = { T_UINT,     T_END };
 
 
 
@@ -190,13 +191,34 @@ type* GetImplicitFuncType (void)
 
 
 
+type* PointerTo (const type* T)
+/* Return a type string that is "pointer to T". The type string is allocated
+ * on the heap and may be freed after use.
+ */                           
+{
+    /* Get the size of the type string including the terminator */
+    unsigned Size = TypeLen (T) + 1;
+
+    /* Allocate the new type string */
+    type* P = TypeAlloc        (Size + 1);
+
+    /* Create the return type... */
+    P[0] = T_PTR;
+    memcpy (P+1, T, Size * sizeof (type));
+
+    /* ...and return it */
+    return P;
+}
+
+
+
 static type PrintTypeComp (FILE* F, type T, type Mask, const char* Name)
 /* Check for a specific component of the type. If it is there, print the
  * name and remove it. Return the type with the component removed.
  */
 {
     if ((T & Mask) == Mask) {
-       fprintf (F, "%s ", Name);
+       fprintf (F, "%s ", Name);
        T &= ~Mask;
     }
     return T;
@@ -361,7 +383,7 @@ unsigned SizeOf (const type* T)
 
        case T_VOID:
            Error (ERR_ILLEGAL_SIZE);
-           return 0;
+           return 1;   /* Return something that makes sense */
 
        case T_SCHAR:
        case T_UCHAR:
index 680428c128ebb5036e2da4f2e1ed5c57f260f1a7..07889cb0138ba12a5dd7adecbfe365ffb06fa724 100644 (file)
@@ -147,6 +147,7 @@ extern type type_uint [];
 extern type type_long [];
 extern type type_ulong [];
 extern type type_void [];
+extern type type_size_t [];
 
 
 
@@ -185,6 +186,11 @@ type* GetCharArrayType (unsigned Len);
 type* GetImplicitFuncType (void);
 /* Return a type string for an inplicitly declared function */
 
+type* PointerTo (const type* T);
+/* Return a type string that is "pointer to T". The type string is allocated
+ * on the heap and may be freed after use.
+ */
+
 void PrintType (FILE* F, const type* Type);
 /* Output translation of type array. */
 
index 13cb24db51a0d73daa61030c8909e94891bd18b0..9d0455ae99793fb23346a760885d9105fc5deda7 100644 (file)
@@ -121,7 +121,7 @@ static char* ErrMsg [ERR_COUNT-1] = {
     "Too many initializers",
     "Cannot initialize incomplete type",
     "Cannot subscript",
-    "Operation not allowed on these types",
+    "Operation not allowed with this type of argument",
     "Struct expected",
     "Struct/union has no field named `%s'",
     "Struct pointer expected",
index 83065d1127931dd7de626e53ac4eea3090153a0b..9637fbe4acc0f0c6ce02afdeb3c783a794cc9ebf 100644 (file)
@@ -81,10 +81,14 @@ typedef enum {
     NT_STRUCT_ACCESS,          /* Access of a struct field */
     NT_STRUCTPTR_ACCESS,               /* Access via struct ptr */
     NT_FUNCTION_CALL,          /* Call a function */
+    NT_TYPECAST,               /* A cast */
+    NT_ADDRESS,                        /* Address operator (&) */
+    NT_INDIRECT,               /* Indirection operator (*) */
 
     NT_UNARY_MINUS,
+    NT_COMPLEMENT,             /* ~ */
+    NT_BOOL_NOT,                       /* ! */
 
-    NT_NOT,                            /* ~ */
     NT_PLUS,                           /* + */
     NT_MINUS,                          /* - */
     NT_MUL,                            /* * */
@@ -111,7 +115,6 @@ typedef enum {
     NT_PRE_INC,                        /* ++ */
     NT_POST_INC,                       /* ++ */
 
-    NT_BOOL_NOT,                       /* ! */
     NT_BOOL_OR,                        /* || */
     NT_BOOL_AND,                       /* && */
 
index 1cd0297ae5bde9ccbafb20561019090940a0d102..e4ba5be4ccea4461a17c10516b417741f77fad9a 100644 (file)
@@ -605,6 +605,41 @@ 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_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 (ERR_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)
 {
     /* Get the lower level expression */
@@ -632,9 +667,8 @@ static ExprNode* PostfixExpr (void)
                break;
 
            case TOK_INC:
-               break;
-
            case TOK_DEC:
+               Root = DoPostIncDec (Root);
                break;
 
            default:
@@ -717,12 +751,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->V.I = -Op->V.I;
+       } else {
+           /* Float */
+           Op->V.F = -Op->V.F;
+       }
+
+       /* 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,13 +782,242 @@ 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 (ERR_OP_NOT_ALLOWED);
+
+       /* Free the errorneous node */
+       FreeExprNode (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->V.I = ~Op->V.I;
+       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 (ERR_ILLEGAL_ADDRESS);
+
+       /* Free the problematic node */
+       FreeExprNode (Op);
+
+       /* Return something that is safe later */
+       Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
+       Root->V.I = 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 operaror * */
+{
+    ExprNode* Op;
+    type*     ResultType;
+    int              LVal;
+
+    /* Skip the operator */
+    NextToken ();
+
+    /* Get the operand */
+    Op = UnaryExpr ();
+
+    /* Type check */
+    if (!IsClassPtr (Op->Type)) {
+
+       /* Print diagnostics */
+       Error (ERR_ILLEGAL_INDIRECT);
+
+       /* Free the problematic node */
+       FreeExprNode (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 */
+               FreeExprNode (N);
+
+    }
+
+    /* Create a constant node with type size_t and return it */
+    N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
+    N->V.I = 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_BOOL_NOT, 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_AND    || curtok == TOK_STAR     ||
                curtok == TOK_SIZEOF || IsTypeExpr ()) {
 
        /* Check the token */
@@ -754,23 +1031,24 @@ static ExprNode* UnaryExpr (void)
            case TOK_MINUS:
                return DoUnaryPlusMinus ();
 
-           case TOK_AND:
-               break;
-
-           case TOK_STAR:
-               break;
-
            case TOK_COMP:
-               break;
+               return DoComplement ();
 
            case TOK_BOOL_NOT:
-               break;
+               return DoBoolNot ();
+
+           case TOK_AND:
+               return DoAddress ();
+
+           case TOK_STAR:
+               return DoIndirect ();
 
            case TOK_SIZEOF:
-               break;
+               return DoSizeOf ();
 
            default:
-               break;
+               /* Type cast */
+               return DoTypeCast ();
 
        }