X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fparser.c;h=ec1dfcc43941a6bac49116d27103676969179b81;hb=c130e597b013e37c94afd6651be1e8859ba7e5ac;hp=e4ba5be4ccea4461a17c10516b417741f77fad9a;hpb=64dac7e7b7814a0ee5295608f47faae024825058;p=cc65 diff --git a/src/cc65/parser.c b/src/cc65/parser.c index e4ba5be4c..ec1dfcc43 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); @@ -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 */ @@ -611,7 +629,7 @@ static ExprNode* DoPostIncDec (ExprNode* Left) ExprNode* Root; /* Determine the type of the node */ - nodetype_t NT = (curtok == TOK_INC)? NT_POST_INC : NT_POST_DEC; + nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_POST_INC : NT_POST_DEC; /* Skip the operator token */ NextToken (); @@ -620,7 +638,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 @@ -641,17 +659,18 @@ static ExprNode* DoPostIncDec (ExprNode* Left) 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); @@ -690,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 (); @@ -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 @@ -729,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 */ @@ -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; } @@ -890,7 +908,7 @@ static ExprNode* DoAddress (void) static ExprNode* DoIndirect (void) -/* Handle the indirection operaror * */ +/* Handle the indirection operator * */ { ExprNode* Op; type* ResultType; @@ -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_TYPECAST, TargetType, RVALUE); SetLeftNode (Root, Op); return Root; @@ -1014,14 +1032,14 @@ static ExprNode* DoTypeCast (void) static ExprNode* UnaryExpr (void) { /* */ - if (curtok == TOK_INC || curtok == TOK_DEC || - curtok == TOK_PLUS || curtok == TOK_MINUS || - curtok == TOK_COMP || curtok == TOK_BOOL_NOT || - curtok == TOK_AND || curtok == TOK_STAR || - 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: @@ -1029,7 +1047,7 @@ static ExprNode* UnaryExpr (void) case TOK_PLUS: case TOK_MINUS: - return DoUnaryPlusMinus (); + return DoUnaryPlusMinus (); case TOK_COMP: return DoComplement (); @@ -1046,16 +1064,546 @@ 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 (); + + } +} + + + +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; + + 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; } } + + +