X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fparser.c;h=932d3875a0e4710c518dbf78773cba9b14c9ace6;hb=4357bb47604774ded7900ed13d139c32cf854c0a;hp=62aedd667d4896c2d71c68abbd23522ab0004d6c;hpb=1c14beb82d0e4a25174604c876e46c8080dc1919;p=cc65 diff --git a/src/cc65/parser.c b/src/cc65/parser.c index 62aedd667..932d3875a 100644 --- a/src/cc65/parser.c +++ b/src/cc65/parser.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000 Ullrich von Bassewitz */ +/* (C) 2000-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ @@ -96,6 +96,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,7 +130,7 @@ static ExprNode* GetIntNode (int Value) */ { ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE); - N->V.I = Value; + N->IVal = Value; return N; } @@ -143,7 +164,7 @@ ExprNode* DoAsm (void) 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 +172,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); + ResetLiteralOffs (CurTok.IVal); } /* Skip the string token */ @@ -193,7 +214,7 @@ static ExprNode* Primary (void) /* 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 (); @@ -205,7 +226,7 @@ static ExprNode* Primary (void) /* 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 +238,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 (); @@ -245,11 +266,11 @@ 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); } @@ -286,7 +307,7 @@ static ExprNode* Primary (void) 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 +320,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); @@ -313,8 +334,8 @@ static ExprNode* Primary (void) } 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 == TOK_ASM) { @@ -349,7 +370,7 @@ static ExprNode* Primary (void) } else { /* Illegal primary. */ - Error (ERR_EXPR_EXPECTED); + Error ("Expression expected"); N = GetIntNode (0); } @@ -375,15 +396,13 @@ static ExprNode* DoArray (ExprNode* Left) 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 +413,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 +431,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); } @@ -454,7 +473,7 @@ static ExprNode* DoStruct (ExprNode* Left) 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,7 +481,7 @@ static ExprNode* DoStruct (ExprNode* Left) NT = NT_STRUCT_ACCESS; } if (!IsClassStruct (StructType)) { - Error (ERR_STRUCT_EXPECTED); + Error ("Struct expected"); return GetIntNode (0); } @@ -470,7 +489,7 @@ static ExprNode* DoStruct (ExprNode* Left) NextToken (); 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 +500,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 +539,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); @@ -571,7 +590,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left) /* Too many arguments. Do we have an open param list? */ if ((Func->Flags & FD_ELLIPSIS) == 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. @@ -596,7 +615,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 */ @@ -620,7 +639,7 @@ static ExprNode* DoPostIncDec (ExprNode* Left) 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 @@ -702,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 @@ -738,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); @@ -759,10 +778,10 @@ static ExprNode* DoUnaryPlusMinus (void) /* 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 */ @@ -798,10 +817,10 @@ static ExprNode* DoComplement (void) 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); @@ -811,7 +830,7 @@ static ExprNode* DoComplement (void) 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 { @@ -871,14 +890,13 @@ static ExprNode* DoAddress (void) 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; } @@ -906,10 +924,10 @@ static ExprNode* DoIndirect (void) 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); @@ -960,13 +978,13 @@ static ExprNode* DoSizeOf (void) 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; } @@ -1001,8 +1019,8 @@ static ExprNode* DoTypeCast (void) } 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_BOOL_NOT, TargetType, RVALUE); SetLeftNode (Root, Op); return Root; @@ -1029,7 +1047,7 @@ static ExprNode* UnaryExpr (void) case TOK_PLUS: case TOK_MINUS: - return DoUnaryPlusMinus (); + return DoUnaryPlusMinus (); case TOK_COMP: return DoComplement (); @@ -1046,22 +1064,59 @@ static ExprNode* UnaryExpr (void) case TOK_SIZEOF: return DoSizeOf (); - default: - /* Type cast */ - return DoTypeCast (); + default: + /* Type cast */ + return DoTypeCast (); - } + } } else { - /* Call the lower level */ - return PostfixExpr (); + /* 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 '%' */ { @@ -1074,6 +1129,7 @@ static ExprNode* MultExpr (void) switch (CurTok.Tok) { case TOK_MUL: + Root = DoMul (Root); break; case TOK_DIV: @@ -1226,15 +1282,52 @@ static ExprNode* AndExpr (void) /* Check if this is for us */ while (CurTok.Tok == TOK_AND) { - switch (CurTok.Tok) { + ExprNode* Left = Root; + ExprNode* Right; - case TOK_AND: - break; + /* Skip the token */ + NextToken (); - default: - Internal ("Unexpected token"); - } + /* 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 */ @@ -1252,15 +1345,52 @@ static ExprNode* XorExpr (void) /* Check if this is for us */ while (CurTok.Tok == TOK_XOR) { - switch (CurTok.Tok) { + ExprNode* Left = Root; + ExprNode* Right; - case TOK_XOR: - break; + /* Skip the token */ + NextToken (); - default: - Internal ("Unexpected token"); - } + /* 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 */ @@ -1278,15 +1408,52 @@ static ExprNode* OrExpr (void) /* Check if this is for us */ while (CurTok.Tok == TOK_OR) { - switch (CurTok.Tok) { + ExprNode* Left = Root; + ExprNode* Right; - case TOK_OR: - break; + /* Skip the token */ + NextToken (); - default: - Internal ("Unexpected token"); - } + /* 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 */ @@ -1304,14 +1471,36 @@ static ExprNode* BoolAndExpr (void) /* Check if this is for us */ while (CurTok.Tok == TOK_BOOL_AND) { - switch (CurTok.Tok) { + ExprNode* Left = Root; + ExprNode* Right; - case TOK_BOOL_AND: - break; + /* Skip the token */ + NextToken (); - default: - Internal ("Unexpected token"); - } + /* 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); + + } } @@ -1330,14 +1519,36 @@ static ExprNode* BoolOrExpr (void) /* Check if this is for us */ while (CurTok.Tok == TOK_BOOL_OR) { - switch (CurTok.Tok) { + ExprNode* Left = Root; + ExprNode* Right; - case TOK_BOOL_OR: - break; + /* Skip the token */ + NextToken (); - default: - Internal ("Unexpected token"); - } + /* 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); + + } } @@ -1382,7 +1593,7 @@ static ExprNode* ConditionalExpr (void) AppendItem (Root, Cond); AppendItem (Root, Expr1); AppendItem (Root, Expr2); - + /* Return the result */ return Root;