+++ /dev/null
-/*****************************************************************************/
-/* */
-/* parser.c */
-/* */
-/* Expression parser */
-/* */
-/* */
-/* */
-/* (C) 2000-2001 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
-/* */
-/* */
-/* This software is provided 'as-is', without any expressed or implied */
-/* warranty. In no event will the authors be held liable for any damages */
-/* arising from the use of this software. */
-/* */
-/* Permission is granted to anyone to use this software for any purpose, */
-/* including commercial applications, and to alter it and redistribute it */
-/* freely, subject to the following restrictions: */
-/* */
-/* 1. The origin of this software must not be misrepresented; you must not */
-/* claim that you wrote the original software. If you use this software */
-/* in a product, an acknowledgment in the product documentation would be */
-/* appreciated but is not required. */
-/* 2. Altered source versions must be plainly marked as such, and must not */
-/* be misrepresented as being the original software. */
-/* 3. This notice may not be removed or altered from any source */
-/* distribution. */
-/* */
-/*****************************************************************************/
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* common */
-#include "check.h"
-#include "xmalloc.h"
-
-/* cc65 */
-#include "datatype.h"
-#include "declare.h"
-#include "error.h"
-#include "exprheap.h"
-#include "funcdesc.h"
-#include "function.h"
-#include "global.h"
-#include "litpool.h"
-#include "macrotab.h"
-#include "preproc.h"
-#include "scanner.h"
-#include "stdfunc.h"
-#include "symtab.h"
-#include "typecmp.h"
-#include "parser.h"
-
-
-
-/*****************************************************************************/
-/* Forwards */
-/*****************************************************************************/
-
-
-
-static ExprNode* UnaryExpr (void);
-ExprNode* AssignExpr (void);
-ExprNode* Expression (void);
-
-
-
-/*****************************************************************************/
-/* Helper functions */
-/*****************************************************************************/
-
-
-
-static int IsTypeExpr (void)
-/* Return true if some sort of variable or type is waiting */
-{
- SymEntry* Entry;
-
- return CurTok.Tok == TOK_LPAREN && (
- (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
- (nxttok == TOK_CONST) ||
- (nxttok == TOK_IDENT &&
- (Entry = FindSym (NextTok.Ident)) != 0 &&
- IsTypeDef (Entry))
- );
-}
-
-
-
-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 */
-/*****************************************************************************/
-
-
-
-static ExprNode* GetIntNode (int Value)
-/* Allocate a new expression node from the tree, make it a valid integer
- * node and return it. Often used if an error occurs to get a safe expression
- * tree.
- */
-{
- ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
- N->IVal = Value;
- return N;
-}
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-ExprNode* DoAsm (void)
-/* This function parses ASM statements. The syntax of the ASM directive
- * looks like the one defined for C++ (C has no ASM directive), that is,
- * a string literal in parenthesis.
- */
-{
- ExprNode* N;
-
-
- /* Skip the ASM */
- NextToken ();
-
- /* Need left parenthesis */
- ConsumeLParen ();
-
- /* Create a new expression node and assign a void type */
- N = AllocExprNode (NT_ASM, type_void, RVALUE);
-
- /* String literal */
- if (CurTok.Tok != TOK_SCONST) {
-
- /* Print an error */
- Error ("String literal expected");
-
- /* To be on the safe side later, insert an empty asm string */
- AppendItem (N, xstrdup (""));
-
- } else {
-
- /* Insert a copy of the string into the expression node */
- 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.
- */
- ResetLiteralPoolOffs (CurTok.IVal);
- }
-
- /* Skip the string token */
- NextToken ();
-
- /* Closing paren needed */
- ConsumeRParen ();
-
- /* Return the created node */
- return N;
-}
-
-
-
-static ExprNode* Primary (void)
-/* Evaluate a primary expression */
-{
- ExprNode* N;
-
- /* Process a parenthesized subexpression. In this case we don't need to
- * allocate a new node ourselves.
- */
- if (CurTok.Tok == TOK_LPAREN) {
- NextToken ();
- N = Expression ();
- ConsumeRParen ();
- return N;
- }
-
- /* Check for an integer or character constant */
- if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
-
- /* Create the new node */
- N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
- N->IVal = CurTok.IVal;
-
- /* Skip the token and return the result */
- NextToken ();
- return N;
- }
-
- /* Check for a float constant */
- if (CurTok.Tok == TOK_FCONST) {
-
- /* Create the new node */
- N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
- N->FVal = CurTok.FVal;
-
- /* Skip the token and return the result */
- NextToken ();
- return N;
- }
-
- /* All others may only be used if the expression evaluation is not called
- * recursively by the preprocessor.
- */
- if (Preprocessing) {
- /* Illegal expression in PP mode */
- Error ("Preprocessor expression expected");
-
- /* Skip the token for error recovery */
- NextToken ();
-
- /* Return an integer constant */
- return GetIntNode (0);
- }
-
- /* Identifier? */
- if (CurTok.Tok == TOK_IDENT) {
-
- /* Identifier */
- SymEntry* Sym;
- ident Ident;
-
- /* Get a pointer to the symbol table entry */
- Sym = FindSym (CurTok.Ident);
-
- /* Is the symbol known? */
- if (Sym) {
-
- /* We found the symbol - skip the name token */
- NextToken ();
-
- /* Check for illegal symbol types */
- if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
- /* Cannot use labels in expressions */
- Error ("Cannot use a label in an expression");
- return GetIntNode (0);
- } else if (Sym->Flags & SC_TYPE) {
- /* Cannot use type symbols */
- Error ("Cannot use a type in an expression");
- /* Assume an int type to make lval valid */
- return GetIntNode (0);
- }
-
- /* Handle constants including enum values */
- if ((Sym->Flags & SC_CONST) == SC_CONST) {
-
- N = AllocExprNode (NT_CONST, Sym->Type, RVALUE);
- N->IVal = Sym->V.ConstVal;
-
- } else {
-
- /* All symbols besides functions and arrays are lvalues */
- int LVal = (!IsTypeFunc (Sym->Type) && !IsTypeArray (Sym->Type));
-
- /* Create the node */
- N = AllocExprNode (NT_SYM, Sym->Type, LVal);
-
- /* Set the symbol pointer */
- SetNodeSym (N, Sym);
- }
-
- /* The symbol is referenced now */
- Sym->Flags |= SC_REF;
-
- } else {
-
- /* We did not find the symbol. Remember the name, then skip it */
- strcpy (Ident, CurTok.Ident);
- NextToken ();
-
- /* IDENT is either an auto-declared function or an undefined
- * variable.
- */
- if (CurTok.Tok == TOK_LPAREN) {
-
- /* Warn about the use of a function without prototype */
- 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
- * list and returning int.
- */
- Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
- N = AllocExprNode (NT_SYM, Sym->Type, RVALUE);
- SetNodeSym (N, Sym);
-
- } else {
-
- /* Print an error about an undeclared variable */
- Error ("Undefined symbiol: `%s'", Ident);
-
- /* Undeclared Variable */
- Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
- N = AllocExprNode (NT_SYM, Sym->Type, LVALUE);
- SetNodeSym (N, Sym);
-
- }
-
- }
-
- } else if (CurTok.Tok == TOK_SCONST) {
-
- /* String literal */
- N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (CurTok.IVal))), RVALUE);
- N->IVal = CurTok.IVal;
-
- } else if (CurTok.Tok == TOK_ASM) {
-
- /* ASM statement? */
- N = DoAsm ();
-
- } else if (CurTok.Tok == TOK_A) {
-
- /* A register */
- N = AllocExprNode (NT_REG_A, type_uchar, LVALUE);
-
- } else if (CurTok.Tok == TOK_X) {
-
- /* X register */
- N = AllocExprNode (NT_REG_X, type_uchar, LVALUE);
-
- } else if (CurTok.Tok == TOK_Y) {
-
- /* Y register */
- N = AllocExprNode (NT_REG_Y, type_uchar, LVALUE);
-
- } else if (CurTok.Tok == TOK_AX) {
-
- /* AX pseudo register */
- N = AllocExprNode (NT_REG_AX, type_uint, LVALUE);
-
- } else if (CurTok.Tok == TOK_EAX) {
-
- /* EAX pseudo register */
- N = AllocExprNode (NT_REG_EAX, type_ulong, LVALUE);
-
- } else {
-
- /* Illegal primary. */
- Error ("Expression expected");
- N = GetIntNode (0);
-
- }
-
- /* Return the new node */
- return N;
-}
-
-
-
-static ExprNode* DoArray (ExprNode* Left)
-/* Handle arrays */
-{
- ExprNode* Right;
- ExprNode* Root;
- type* ElementType;
-
-
- /* Skip the bracket */
- NextToken ();
-
- /* Get the index */
- Right = Expression ();
-
- /* Check the types. As special "C" feature, accept a reversal of base and
- * 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 ("Invalid subscript");
- /* To avoid problems later, create a new, legal subscript
- * expression
- */
- Right = GetIntNode (0);
- }
- } else if (IsClassPtr (Right->Type)) {
-
- ExprNode* Tmp;
-
- /* Left side must be some sort of integer */
- if (!IsClassInt (Left->Type)) {
- /* Print an error */
- Error ("Invalid subscript");
- /* To avoid problems later, create a new, legal subscript
- * expression
- */
- Left = GetIntNode (0);
- }
-
- /* Swap the expression to it's normal form */
- Tmp = Right;
- Right = Left;
- Left = Tmp;
-
- } else {
- /* Invalid array expression. Skip the closing bracket, then return
- * an integer instead of the array expression to be safe later.
- */
- Error ("Invalid subscript");
- ConsumeRBrack ();
- return GetIntNode (0);
- }
-
- /* Skip the right bracket */
- ConsumeRBrack ();
-
- /* Get the type of the array elements */
- ElementType = Indirect (Left->Type);
-
- /* Allocate the branch node for the array expression */
- Root = AllocExprNode (NT_ARRAY_SUBSCRIPT,
- ElementType,
- IsTypeArray (ElementType)? RVALUE : LVALUE);
-
- /* Setup the branches */
- SetLeftNode (Root, Left);
- SetRightNode (Root, Right);
-
- /* ...and return it */
- return Root;
-}
-
-
-
-static ExprNode* DoStruct (ExprNode* Left)
-/* Process struct field access */
-{
- nodetype_t NT;
- ident Ident;
- type* StructType;
- ExprNode* Right;
- ExprNode* Root;
- SymEntry* Field;
-
-
- /* Type check */
- StructType = Left->Type;
- if (CurTok.Tok == TOK_PTR_REF) {
- NT = NT_STRUCTPTR_ACCESS;
- if (!IsTypePtr (StructType)) {
- Error ("Struct pointer expected");
- return GetIntNode (0);
- }
- StructType = Indirect (StructType);
- } else {
- NT = NT_STRUCT_ACCESS;
- }
- if (!IsClassStruct (StructType)) {
- Error ("Struct expected");
- return GetIntNode (0);
- }
-
- /* Skip the token and check for an identifier */
- NextToken ();
- if (CurTok.Tok != TOK_IDENT) {
- /* Print an error */
- Error ("Identifier expected");
- /* Return an integer expression instead */
- return GetIntNode (0);
- }
-
- /* Get the symbol table entry and check for a struct field */
- strcpy (Ident, CurTok.Ident);
- NextToken ();
- Field = FindStructField (StructType, Ident);
- if (Field == 0) {
- /* Struct field not found */
- Error ("Struct/union has no field named `%s'", Ident);
- /* Return an integer expression instead */
- return GetIntNode (0);
- }
-
- /* Allocate and set up the right (== field) node */
- Right = AllocExprNode (NT_SYM, Field->Type, RVALUE);
- SetNodeSym (Right, Field);
-
- /* Allocate the branch node for the resulting expression */
- Root = AllocExprNode (NT, Right->Type,
- IsTypeArray (Right->Type)? RVALUE : LVALUE);
-
- /* Setup the branches */
- SetLeftNode (Root, Left);
- SetRightNode (Root, Right);
-
- /* ...and return it */
- return Root;
-}
-
-
-
-static ExprNode* DoFunctionCall (ExprNode* Left)
-/* Process a function call */
-{
- type* ResultType; /* Type of function result */
- FuncDesc* Func; /* Function descriptor */
- ExprNode* Root; /* Function call node */
- int Ellipsis; /* True if we have an open param list */
- SymEntry* Param; /* Current formal parameter */
- unsigned ParamCount; /* Actual parameter count */
- unsigned ParamSize; /* Number of parameter bytes */
-
-
- /* Type check */
- if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
-
- /* Call to non function */
- Error ("Illegal function call");
-
- /* Free the old tree */
- FreeExprTree (Left);
-
- /* Return something safe */
- return GetIntNode (0);
- }
-
- /* Get the type of the function result */
- ResultType = Left->Type;
- if (IsTypeFuncPtr (Left->Type)) {
- ++ResultType;
- }
- ResultType += DECODE_SIZE + 1; /* Set to result type */
-
- /* Skip the opening parenthesis */
- NextToken ();
-
- /* Allocate the function call node */
- Root = AllocExprNode (NT_FUNCTION_CALL, ResultType, RVALUE);
-
- /* Get a pointer to the function descriptor from the type string */
- Func = GetFuncDesc (Left->Type);
-
- /* Initialize vars to keep gcc silent */
- Param = 0;
-
- /* Parse the parameter list */
- ParamSize = 0;
- ParamCount = 0;
- Ellipsis = 0;
- while (CurTok.Tok != TOK_RPAREN) {
-
- /* Count arguments */
- ++ParamCount;
-
- /* Fetch the pointer to the next argument, check for too many args */
- if (ParamCount <= Func->ParamCount) {
- if (ParamCount == 1) {
- /* First argument */
- Param = Func->SymTab->SymHead;
- } else {
- /* Next argument */
- Param = Param->NextSym;
- CHECK ((Param->Flags & SC_PARAM) != 0);
- }
- } else if (!Ellipsis) {
- /* Too many arguments. Do we have an open param list? */
- if ((Func->Flags & FD_VARIADIC) == 0) {
- /* End of param list reached, no ellipsis */
- Error ("Too many function arguments");
- }
- /* Assume an ellipsis even in case of errors to avoid an error
- * message for each other argument.
- */
- Ellipsis = 1;
- }
-
- /* Get the parameter value expression tree and add it to the parameter
- * list.
- */
- AppendItem (Root, AssignExpr ());
-
- /* Check for end of argument list */
- if (CurTok.Tok != TOK_COMMA) {
- break;
- }
- NextToken ();
- }
-
- /* We need the closing bracket here */
- ConsumeRParen ();
-
- /* Check if we had enough parameters */
- if (ParamCount < Func->ParamCount) {
- Error ("Too few function arguments");
- }
-
- /* Return the function call node */
- return Root;
-}
-
-
-
-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)
-/* Handle a postfix expression */
-{
- /* Get the lower level expression */
- ExprNode* Root = Primary ();
-
- /* */
- 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.Tok) {
-
- case TOK_LBRACK:
- Root = DoArray (Root);
- break;
-
- case TOK_LPAREN:
- Root = DoFunctionCall (Root);
- break;
-
- case TOK_DOT:
- case TOK_PTR_REF:
- Root = DoStruct (Root);
- break;
-
- case TOK_INC:
- case TOK_DEC:
- Root = DoPostIncDec (Root);
- break;
-
- default:
- Internal ("Unexpected token");
-
- }
- }
-
- /* Return the result */
- return Root;
-}
-
-
-
-static ExprNode* DoPreIncDec (void)
-/* Handle preincrement and predecrement */
-{
- ExprNode* Op;
- ExprNode* Root;
-
- /* Determine the type of the node */
- nodetype_t NT = (CurTok.Tok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
-
- /* Skip the operator token */
- NextToken ();
-
- /* Get the expression to increment or decrement */
- Op = UnaryExpr ();
-
- /* The operand must be an lvalue */
- if (Op->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 Op;
- }
-
- /* Setup the expression tree */
- Root = AllocExprNode (NT, Op->Type, RVALUE);
- SetLeftNode (Root, Op);
-
- /* Return the new node */
- return Root;
-}
-
-
-
-static ExprNode* DoUnaryPlusMinus (void)
-/* Handle unary +/- */
-{
- ExprNode* Op;
- ExprNode* Root;
-
- /* Remember the current token for later, then skip it */
- token_t Tok = CurTok.Tok;
- NextToken ();
-
- /* Get the operand */
- Op = UnaryExpr ();
-
- /* Type check */
- if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
-
- /* Output diagnostic */
- Error ("Syntax error");
-
- /* Free the errorneous node */
- FreeExprTree (Op);
-
- /* Return something that makes sense later */
- return GetIntNode (0);
- }
-
- /* In case of PLUS, we must do nothing */
- if (Tok == TOK_PLUS) {
-
- /* 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 {
-
- /* Non constant value, setup the expression tree */
- Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
- SetLeftNode (Root, Op);
-
- }
-
- /* Return the new node */
- return Root;
-}
-
-
-
-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 operator * */
-{
- 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_TYPECAST, TargetType, RVALUE);
- SetLeftNode (Root, Op);
- return Root;
-
- }
-}
-
-
-
-static ExprNode* UnaryExpr (void)
-{
- /* */
- 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.Tok) {
-
- case TOK_INC:
- case TOK_DEC:
- return DoPreIncDec ();
-
- case TOK_PLUS:
- case TOK_MINUS:
- return DoUnaryPlusMinus ();
-
- case TOK_COMP:
- return DoComplement ();
-
- case TOK_BOOL_NOT:
- return DoBoolNot ();
-
- case TOK_AND:
- return DoAddress ();
-
- case TOK_STAR:
- return DoIndirect ();
-
- case TOK_SIZEOF:
- return DoSizeOf ();
-
- 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 {
-
- /* Just return the lower level expression */
- return Cond;
-
- }
-}
-
-
-