X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fparser.c;h=932d3875a0e4710c518dbf78773cba9b14c9ace6;hb=4357bb47604774ded7900ed13d139c32cf854c0a;hp=1cd0297ae5bde9ccbafb20561019090940a0d102;hpb=7e59a882c579ae8d6c70ec88fa83e89a1012504c;p=cc65 diff --git a/src/cc65/parser.c b/src/cc65/parser.c index 1cd0297ae..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 */ @@ -67,8 +67,8 @@ static ExprNode* UnaryExpr (void); -ExprNode* Expr1 (void); -ExprNode* Expr0 (void); +ExprNode* AssignExpr (void); +ExprNode* Expression (void); @@ -85,7 +85,7 @@ static int IsTypeExpr (void) { 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 +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; } @@ -140,10 +161,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 +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 */ @@ -181,19 +202,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 +222,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 +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 (); @@ -227,7 +248,7 @@ static ExprNode* Primary (void) } /* Identifier? */ - if (curtok == TOK_IDENT) { + if (CurTok.Tok == TOK_IDENT) { /* Identifier */ SymEntry* Sym; @@ -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); } @@ -283,10 +304,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 +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); @@ -310,38 +331,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 +370,7 @@ static ExprNode* Primary (void) } else { /* Illegal primary. */ - Error (ERR_EXPR_EXPECTED); + Error ("Expression expected"); N = GetIntNode (0); } @@ -372,18 +393,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 +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); } @@ -451,10 +470,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 +481,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 +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); @@ -552,7 +571,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left) ParamSize = 0; ParamCount = 0; Ellipsis = 0; - while (curtok != TOK_RPAREN) { + while (CurTok.Tok != TOK_RPAREN) { /* Count arguments */ ++ParamCount; @@ -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. @@ -580,12 +599,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 +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 */ @@ -605,18 +624,53 @@ 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) { /* 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 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 ("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_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_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,564 @@ 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: + 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; - default: + 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; } } + + + +