From 64dac7e7b7814a0ee5295608f47faae024825058 Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 20 Aug 2000 09:25:47 +0000 Subject: [PATCH] Working on the new parser git-svn-id: svn://svn.cc65.org/cc65/trunk@291 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/datatype.c | 28 +++- src/cc65/datatype.h | 6 + src/cc65/error.c | 2 +- src/cc65/exprnode.h | 7 +- src/cc65/parser.c | 310 +++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 331 insertions(+), 22 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 59a0adddd..ba72fc1a8 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -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: diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 680428c12..07889cb01 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -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. */ diff --git a/src/cc65/error.c b/src/cc65/error.c index 13cb24db5..9d0455ae9 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -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", diff --git a/src/cc65/exprnode.h b/src/cc65/exprnode.h index 83065d112..9637fbe4a 100644 --- a/src/cc65/exprnode.h +++ b/src/cc65/exprnode.h @@ -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, /* && */ diff --git a/src/cc65/parser.c b/src/cc65/parser.c index 1cd0297ae..e4ba5be4c 100644 --- a/src/cc65/parser.c +++ b/src/cc65/parser.c @@ -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 (); }