/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1989-1999 Microsoft Corporation Module Name: expr.hxx Abstract: This file contains the expression class definitions. Notes: Author: VibhasC Jun-06-1993 Created Notes: This expression evaluator is used by the front and the code generator of the midl compiler. It therefore must support the complete gamut of c expressions. ----------------------------------------------------------------------------*/ #ifndef __EXPR_HXX__ #define __EXPR_HXX__ /**************************************************************************** * include files ***************************************************************************/ #include "nulldefs.h" #include "common.hxx" #include "listhndl.hxx" #include "midlnode.hxx" extern "C" { #include } #include "stream.hxx" #include "ndrtypes.h" #define _STRDUP( x, y ) ( (y) ? ((x) = new char[strlen(y)+1] ), strcpy( x, y ) : x = 0) class node_skl; class EXPR_CTXT; typedef char * PNAME; typedef __int64 EXPR_VALUE; /**************************************************************************** * extern references ***************************************************************************/ /**************************************************************************** * the meat of the definitions ***************************************************************************/ #if 0 // // the class heirarchy for the expression evaluator. The class heirarchy for // the expression does not reflect the operator or evaluation precedence. The // class heirarchy instead reflects the organisation based on the structure of // an object of the expression class. It is upto the generator of the expression // to ensure proper precedence. In case the expression is generated by a parser // the precedence is automatically ensured. The back end which generates new // expressions must therefore ensure that the precedence is properly set up. We // will NOT check this. // expr_node expr_variable expr_resource expr_constant expr_operator expr_op_unary expr_u_arithmetic // + - expr_u_not // ! expr_u_complement // ~ expr_deref // * expr_u_address // & expr_cast // (type) expr_sizeof // sizeof( type ) expr_alignof // __alignof( type ) expr_post_incr // foo++ expr_pre_incr // ++foo expr_post_decr // foo-- expr_pre_decr // --foo expr_op_binary expr_b_arith // * / + - % expr_b_logical // || && expr_relational // > >= == != < <= expr_shift // << >> expr_bitwise // |, &, ^ expr_dot // a.b expr_pointsto // a->b expr_index // [] expr_comma // , expr_assign // = expr_proc // () expr_statement // ; expr_ternary // ?: #endif // 0 // // The basic expression class. This class is an abstract base class. It only // provides the interface to a general expression node. // #define _expr_node expr_node #define _expr_variable expr_variable #define _expr_constant expr_constant #define _expr_named_constant expr_named_constant #define _expr_operator expr_operator #define _expr_op_unary expr_op_unary #define _expr_op_binary expr_op_binary #define _expr_u_arithmetic expr_u_arithmetic #define _expr_u_not expr_u_not #define _expr_u_complement expr_u_complement #define _expr_u_deref expr_u_deref #define _expr_u_address expr_u_address #define _expr_cast expr_cast #define _expr_sizeof expr_sizeof #define _expr_alignof expr_alignof #define _expr_pre_incr expr_pre_incr #define _expr_pre_decr expr_pre_decr #define _expr_post_incr expr_post_incr #define _expr_post_decr expr_post_decr #define _expr_b_arithmetic expr_b_arithmetic #define _expr_b_logical expr_b_logical #define _expr_relational expr_relational #define _expr_shift expr_shift #define _expr_bitwise expr_bitwise #define _expr_dot expr_dot #define _expr_pointsto expr_pointsto #define _expr_index expr_index #define _expr_comma expr_comma #define _expr_assign expr_assign #define _expr_proc_call expr_proc_call #define _expr_param expr_param // // This is the constant expression class. For now this only has simple integral // constants. We would need to have this class to be more explicit in that it // needs to know the exact type of the constant according to the language // rules and know the exact format to be able to print this out. This is // necessary so that the generated constant looks the same as the original // for the user's convenience. // typedef enum _pformat { VALUE_TYPE_STRING, VALUE_TYPE_WSTRING, VALUE_TYPE_CHAR, VALUE_TYPE_WCHAR, VALUE_TYPE_NUMERIC, VALUE_TYPE_NUMERIC_U, VALUE_TYPE_NUMERIC_LONG, VALUE_TYPE_NUMERIC_ULONG, VALUE_TYPE_HEX, VALUE_TYPE_HEX_U, VALUE_TYPE_HEX_LONG, VALUE_TYPE_HEX_ULONG, VALUE_TYPE_OCTAL, VALUE_TYPE_OCTAL_U, VALUE_TYPE_OCTAL_LONG, VALUE_TYPE_OCTAL_ULONG, VALUE_TYPE_BOOL, VALUE_TYPE_FLOAT, VALUE_TYPE_DOUBLE, // RKK64 // value types for int64 VALUE_TYPE_UNDEFINED, } PFORMAT; struct SExprValue { PFORMAT format; union { signed char ch; signed short sh; signed int n; signed long l; unsigned char uch; unsigned short ush; unsigned int un; unsigned long ul; __int64 hy; float f; double d; BOOL b; wchar_t wch; } ; }; typedef node_skl * ETYPE; class expr_node { protected: // // the type of the expression. All expression nodes need to have a type // since a variable / constant will have a type and so will an operation // on those variables / constants. node_skl * pType; BOOL fConstant : 1; BOOL fFloatExpr : 1; // // The constructor. Each expression node is instantiated using a type // If the type is unknown at the time of instantiation, then an error type // is the type of the expression. Therefore we provide a overloaded // constructor for both these situations. // public: expr_node() { SetType( (node_skl *)0 ); fConstant = TRUE; fFloatExpr = FALSE; }; expr_node( node_skl * pT ) { SetType( pT ); fConstant = TRUE; fFloatExpr = FALSE; }; virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_node; }; // // set the type of the expression. // void SetType( node_skl * pT ) { pType = pT; } // // get the type of the expression. // virtual node_skl * GetType( void ) { return pType; } // // get the type of the expression. Force it to be determined // if it is unknown // node_skl * AlwaysGetType( void ) { node_skl * pType = GetType(); if ( !pType ) { DetermineType(); pType = GetType(); } return pType; } // // determine the type of the expression // virtual void DetermineType() { } // // set the "constness" of the expression. // void SetConstant( BOOL fCon = TRUE ) { fConstant = fCon; } void SetFloatExpr( BOOL f = TRUE ) { fFloatExpr = f; } // // queries. // virtual BOOL IsAVariable() { return FALSE; } virtual BOOL IsResource() { return FALSE; } virtual BOOL IsConstant() { return fConstant; } virtual BOOL IsOperator() { return FALSE; } virtual BOOL IsUnaryOperator() { return FALSE; } virtual BOOL IsBinaryOperator() { return FALSE; } virtual BOOL IsArithmeticOperator() { return FALSE; } virtual BOOL IsLogicalOperator() { return FALSE; } virtual BOOL IsBitwiseOperator() { return FALSE; } virtual BOOL IsRelationalOperator() { return FALSE; } virtual BOOL IsShiftOperator() { return FALSE; } // // test if the expression is a string constant // virtual BOOL IsStringConstant (void) { return FALSE; } BOOL IsFloatExpr( void ) { return fFloatExpr; } // // others. // virtual expr_node * GetLeft() { return 0; } virtual expr_node * GetRight() { return 0; } virtual OPERATOR GetOperator() { return OP_ILLEGAL; } virtual EXPR_VALUE GetValue() { return 0; } virtual BOOL GetExprValue( SExprValue& v ) { v.format = VALUE_TYPE_UNDEFINED; return TRUE; } // // Make (or add to) a list of var nodes of an expr // virtual short MakeListOfVars( ITERATOR & pList ); virtual short MakeListOfDerefedVars( ITERATOR& ) { return 0; } // gaj - this is a dummy routine virtual EXPR_VALUE Evaluate() { return GetValue(); } // gaj - end of dummy routines // // Given an output steam, output the expression. // virtual void Print( ISTREAM * ) { } void PrintWithPrefix( ISTREAM * pS, char * Prefix ); void DecorateWithPrefix( char * Prefix = NULL ); // // This is an overloaded virtual only for the proc_call node. // virtual void PrintCall( ISTREAM * pS, short , BOOL ) { Print( pS ); } virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); // private allocator void * operator new ( size_t size ) { return AllocateOnceNew( size ); } void operator delete( void * ptr ) { AllocateOnceDelete( ptr ); } }; // // This class represents a variable in an expression. // This expression node is instantiated for variables specified as fields of // a struct/union or as parameters. Contrast this to the resource class which // is VERY similar but only corresponds to the internally generated and used // variables in the stub routines. // class expr_variable : public expr_node { private: // // the name of the variable. // PNAME pIDName; char * pPrefix; public: // // the constructor expects the object to be instantiated using a name. // Sometimes one needs to instantiate a variable using the type too. // expr_variable( PNAME p ) { SetName( p ); SetType( (node_skl *)0 ); SetConstant( FALSE ); SetPrefix( NULL ); } expr_variable( PNAME p, node_skl * pT ); virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_variable(0); }; // get the type virtual node_skl * GetType(); // // set methods. // void SetName( PNAME p ) { pIDName = p; } void SetPrefix( char * p ) { pPrefix = p; } // // get methods // PNAME GetName() { return pIDName; } char * GetPrefix() { return pPrefix; } // // is this a variable expression. // virtual BOOL IsAVariable() { return TRUE; } // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); // // Make (or add to) a list of var nodes of an expr // virtual short MakeListOfVars( ITERATOR & pList ); // // determine the type of the expression // virtual void DetermineType(); // // analyze the expression // virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); }; // // This class represents a variable in an expression. // This expression node is instantiated for variables specified as fields of // a struct/union or as parameters. Contrast this to the resource class which // is VERY similar but only corresponds to the internally generated and used // variables in the stub routines. // class expr_named_constant : public expr_variable { public: // // the constructor expects the object to be instantiated using a name. // Sometimes one needs to instantiate a variable using the type too. // expr_named_constant( PNAME p = 0) : expr_variable( p ) { SetConstant( TRUE ); } expr_named_constant( PNAME p, node_skl * pT ) : expr_variable( p, pT ) { SetConstant( TRUE ); } virtual expr_node* Clone() { return new expr_named_constant; }; BOOL IsAVariable() { return FALSE; } // // if it is a constant id or label, we can return the value // virtual EXPR_VALUE GetValue(); // similarly for expression expr_node * GetExpr(); // // Make (or add to) a list of var nodes of an expr // virtual short MakeListOfVars( ITERATOR & pList ); // // determine the type of the expression // virtual void DetermineType(); // // analyze the expression // virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); }; // // value type masks indicate the value type set by the user / determined from // the value of the constant. // #define VALUE_T_MASK_CLEAR (0x00) #define VALUE_T_MASK_CHAR (0x01) #define VALUE_T_MASK_SHORT (0x02) #define VALUE_T_MASK_LONG (0x04) #define VALUE_T_MASK_UCHAR (0x10) #define VALUE_T_MASK_USHORT (0x20) #define VALUE_T_MASK_ULONG (0x40) class expr_constant : public expr_node { private: // // store the original format. If the original format is a null then // the expression is printed out in the manner suitable for the type of // the expression. If the original format is present, then the user // declared this expression in this format and she wants it back in the // header/stub file also in the same format. PFORMAT Format; union { char C; short S; long L; __int64 I64; float F; double D; unsigned char UC; unsigned short US; unsigned long UL; unsigned __int64 UI64; unsigned char* pC; wchar_t* pWC; } Value; // // get and set the format of the constant. // void SetFormat( PFORMAT p ) { Format = p; } public: virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_constant(this); } PFORMAT GetFormat() const { return Format; } // // Different constructors are available for the different kind of constants // that are possible. // expr_constant( char C, PFORMAT pF = VALUE_TYPE_CHAR ) { SetFormat( pF ); Value.I64 = C; } expr_constant( short S, PFORMAT pF = VALUE_TYPE_NUMERIC ) { SetFormat( pF ); Value.I64 = S; } expr_constant( long L, PFORMAT pF = VALUE_TYPE_NUMERIC ) { SetFormat( pF ); Value.I64 = L; } expr_constant( __int64 I64, PFORMAT pF = VALUE_TYPE_NUMERIC ) { SetFormat( pF ); Value.I64 = I64; } expr_constant( float F, PFORMAT pF = VALUE_TYPE_FLOAT ) { SetFormat( pF ); Value.F = F; } expr_constant( double D, PFORMAT pF = VALUE_TYPE_DOUBLE ) { SetFormat( pF ); Value.D = D; } expr_constant( unsigned char UC, PFORMAT pF = VALUE_TYPE_NUMERIC_U ) { SetFormat( pF ); Value.I64 = UC; } expr_constant( unsigned short US, PFORMAT pF = VALUE_TYPE_NUMERIC_U ) { SetFormat( pF ); Value.I64 = US; } expr_constant( unsigned long UL, PFORMAT pF = VALUE_TYPE_NUMERIC ) { SetFormat( pF ); Value.I64 = UL; } expr_constant( unsigned __int64 UI64, PFORMAT pF = VALUE_TYPE_NUMERIC ) { SetFormat( pF ); Value.I64 = (__int64)UI64; } expr_constant( char *pC, PFORMAT pF = VALUE_TYPE_STRING ) { SetFormat( pF ); Value.UI64 = (unsigned __int64)pC; } expr_constant( wchar_t *pWC, PFORMAT pF = VALUE_TYPE_WSTRING ) { SetFormat( pF ); Value.UI64 = (unsigned __int64)pWC; } expr_constant( const expr_constant *p) { SetFormat( p->GetFormat() ); Value = p->Value; } // // queries. // // gaj - return constant value assuming it is long for now... virtual EXPR_VALUE GetValue(); BOOL GetExprValue( SExprValue& v ) { // currently only floats and double use this code path // fix this when expr evaluator is revamped v.format = VALUE_TYPE_UNDEFINED; if (Format == VALUE_TYPE_FLOAT) { v.format = Format; v.f = Value.F; } else if (Format == VALUE_TYPE_DOUBLE) { v.format = Format; v.d = Value.D; } return TRUE; } // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); // // determine the type of the expression // virtual void DetermineType(); // // analyze the expression // virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); // // test if the expression is a string constant // virtual BOOL IsStringConstant (void) { return (Format == VALUE_TYPE_STRING || Format == VALUE_TYPE_WSTRING); } }; // // some convenient helper functions to get vanilla constant 0 and constant 1 // extern expr_constant * GetConstant0(); extern expr_constant * GetConstant1(); // // the operator classes. These classes are group into unary binary and // ternary expression classes. // class expr_operator : public expr_node { private: OPERATOR Operator; public: // // the constructor of an abstract base class does nothing. // expr_operator( OPERATOR Op ) { SetOperator( Op ); } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_operator( OP_ILLEGAL ); }; // // get and set functions. // void SetOperator( OPERATOR Op ) { Operator = Op; } OPERATOR GetOperator() { return Operator; } // // queries. // virtual BOOL IsOperator() { return TRUE; } void PrintSubExpr( expr_node *, ISTREAM * pS ); }; // // unary operator classes. // class expr_op_unary : public expr_operator { private: expr_node * pLeft; public: // // the constructor. This class is instantiated by supplying operator and // the left had side expression values. // expr_op_unary( OPERATOR Op, expr_node *pL) : expr_operator(Op) { SetLeft( pL ); if ( pL ) SetConstant( pL->IsConstant() ); } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_op_unary( OP_ILLEGAL, 0 ); }; // // get and set routines. // expr_node * SetLeft( expr_node * pL ) { return ( pLeft = pL ); } virtual expr_node * GetLeft() { return pLeft; } // // queries. // virtual BOOL IsUnaryOperator() { return TRUE; } // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); // // Make (or add to) a list of var nodes of an expr // virtual short MakeListOfVars( ITERATOR & pList ); // // determine the type of the expression // virtual void DetermineType(); // // analyze the expression // virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); virtual short MakeListOfDerefedVars( ITERATOR& List ) { if( GetLeft() ) return GetLeft()->MakeListOfDerefedVars( List ); return 0; } }; // // binary operator class. Each binary operator node takes a left and right // expression connected by the binary operator. // class expr_op_binary : public expr_operator { private: expr_node * pLeft; expr_node * pRight; public: // // this class is instantiated by specifying the left/right and the // operator. // expr_op_binary( OPERATOR Op, expr_node * pL, expr_node * pR ) : expr_operator( Op ) { SetLeft( pL ); SetRight( pR ); SetConstant( ( (pL) ? pL->IsConstant() : TRUE ) && ( (pR) ? pR->IsConstant() : TRUE ) ); } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_op_binary( OP_ILLEGAL, 0, 0 ); }; // // get and set. // virtual expr_node * SetLeft( expr_node *p ) { return (pLeft = p); } virtual expr_node * SetRight( expr_node *p ) { return (pRight = p); } virtual expr_node * GetLeft() { return pLeft; } virtual expr_node * GetRight() { return pRight; } // // queries. // virtual BOOL IsBinaryOperator() { return TRUE; } // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); virtual void PrintCall( ISTREAM * pS, short LeftMargin, BOOL fInProc ); // // Make (or add to) a list of var nodes of an expr // virtual short MakeListOfVars( ITERATOR & pList ); virtual short MakeListOfDerefedVars( ITERATOR& List ); // // determine the type of the expression // virtual void DetermineType(); // // analyze the expression // virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); }; // // this is the unary arithmetic class. Corresponding to the unary arithmetic // operators + and -. // class expr_u_arithmetic : public expr_op_unary { public: expr_u_arithmetic( OPERATOR Op, expr_node * pL ) : expr_op_unary(Op, pL) { } virtual expr_node* Clone() { return new expr_u_arithmetic( OP_ILLEGAL, 0 ); }; // // queries. // virtual BOOL IsArithmeticOperator() { return TRUE; } // // test if the expression is a string constant // virtual BOOL IsStringConstant (void) { return GetLeft()->IsStringConstant(); } virtual EXPR_VALUE GetValue(); BOOL GetExprValue( SExprValue& v ); }; // // this is the unary not operator class. // class expr_u_not : public expr_op_unary { public: expr_u_not( expr_node * pL ) : expr_op_unary(OP_UNARY_NOT, pL ) { } virtual expr_node* Clone() { return new expr_u_not( 0 ); }; // // queries. // virtual BOOL IsLogicalOperator() { return TRUE; } virtual EXPR_VALUE GetValue(); }; // // the unary complement class. // class expr_u_complement : public expr_op_unary { public: expr_u_complement( expr_node *pL ) : expr_op_unary(OP_UNARY_COMPLEMENT, pL) { } virtual expr_node* Clone() { return new expr_u_complement( 0 ); }; // // queries. // virtual BOOL IsBitwiseOperator() { return TRUE; } virtual EXPR_VALUE GetValue(); }; // // unary derefence operator // class expr_u_deref : public expr_op_unary { public: expr_u_deref( expr_node *pL ) : expr_op_unary(OP_UNARY_INDIRECTION, pL) { SetConstant( FALSE ); } expr_u_deref( OPERATOR op, expr_node *pL ) : expr_op_unary(op, pL) { SetConstant( FALSE ); } virtual expr_node* Clone() { return new expr_u_deref( 0 ); }; virtual short MakeListOfDerefedVars( ITERATOR& List ); }; // // class expr_u_address : public expr_op_unary { public: expr_u_address( expr_node *pL ) : expr_op_unary(OP_UNARY_AND, pL) { SetConstant( FALSE ); } virtual expr_node* Clone() { return new expr_u_address( 0 ); }; }; // // the unary cast operator // class expr_cast : public expr_op_unary { node_skl* pCastType; bool fEmitModifiers; public: expr_cast( node_skl * pT, expr_node *pL ) : expr_op_unary(OP_UNARY_CAST, pL), fEmitModifiers( true ) { pCastType = pT; } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_cast( 0, 0 ); }; // // Given an output steam, output the expression. // virtual void SetEmitModifiers(bool fModifier = true) { fEmitModifiers = fModifier; } virtual bool GetEmitModifiers() { return fEmitModifiers; } virtual void Print( ISTREAM * pS ); virtual node_skl * GetType() { return pCastType; } virtual EXPR_VALUE GetValue(); }; // // the unary sizeof operator. // class expr_sizeof : public expr_op_unary { node_skl * pType; public: expr_sizeof( node_skl *pT) : expr_op_unary( OP_UNARY_SIZEOF,NULL ) { pType = pT; } expr_sizeof( expr_node *pL ) : expr_op_unary( OP_UNARY_SIZEOF,pL ) { pType = pL->GetType(); } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_sizeof( (node_skl*)0 ); }; // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); virtual short MakeListOfVars( ITERATOR & pList ); virtual EXPR_VALUE GetValue(); }; // // the unary __alignof operator. // class expr_alignof : public expr_op_unary { node_skl * pType; public: expr_alignof( node_skl *pT) : expr_op_unary( OP_UNARY_ALIGNOF, NULL ) { pType = pT; } expr_alignof( expr_node *pL ) : expr_op_unary( OP_UNARY_ALIGNOF, pL ) { pType = pL->GetType(); } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_alignof( (node_skl*)0 ); }; // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); virtual short MakeListOfVars( ITERATOR & pList ); virtual EXPR_VALUE GetValue(); }; // // unary pre-increment operator. // class expr_pre_incr : public expr_op_unary { public: expr_pre_incr( expr_node *pL ) : expr_op_unary(OP_PRE_INCR, pL) { SetType( pL->GetType()); } virtual expr_node* Clone() { return new expr_pre_incr(0); }; // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); }; // // unary pre-decrement operator. // class expr_pre_decr : public expr_op_unary { public: expr_pre_decr( expr_node *pL ): expr_op_unary(OP_PRE_DECR, pL) { SetType( pL->GetType()); } virtual expr_node* Clone() { return new expr_pre_decr(0); }; // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); }; // // unary post-increment operator. // class expr_post_incr : public expr_op_unary { public: expr_post_incr( expr_node *pL ): expr_op_unary(OP_POST_INCR, pL) { SetType( pL->GetType()); } virtual expr_node* Clone() { return new expr_post_incr(0); }; // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); }; // // unary post-decrement operator. // class expr_post_decr : public expr_op_unary { public: expr_post_decr( expr_node *pL ): expr_op_unary(OP_POST_DECR, pL) { SetType( pL->GetType()); } virtual expr_node* Clone() { return new expr_post_decr(0); }; // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); }; // // binary arithmetic operators. // class expr_b_arithmetic : public expr_op_binary { public: expr_b_arithmetic( OPERATOR Op, expr_node *pL, expr_node *pR ): expr_op_binary( Op, pL, pR ) { } virtual expr_node* Clone() { return new expr_b_arithmetic(OP_ILLEGAL,0,0); }; // // queries. // virtual BOOL IsArithmeticOperator() { return TRUE; } virtual EXPR_VALUE GetValue(); BOOL GetExprValue( SExprValue& v ); }; // // binary logical operators. // class expr_b_logical : public expr_op_binary { public: expr_b_logical( OPERATOR Op, expr_node *pL, expr_node *pR ): expr_op_binary( Op, pL, pR ) { } virtual expr_node* Clone() { return new expr_b_logical(OP_ILLEGAL,0,0); }; // // queries. // virtual BOOL IsLogicalOperator() { return TRUE; } virtual EXPR_VALUE GetValue(); }; // // relational operators. // class expr_relational : public expr_op_binary { public: expr_relational( OPERATOR Op, expr_node *pL, expr_node *pR ): expr_op_binary( Op, pL, pR ) { } virtual expr_node* Clone() { return new expr_relational(OP_ILLEGAL,0,0); }; // // queries. // virtual BOOL IsRelationalOperator() { return TRUE; } virtual EXPR_VALUE GetValue(); }; // // shift operators. // class expr_shift : public expr_op_binary { public: expr_shift( OPERATOR Op, expr_node *pL, expr_node *pR ): expr_op_binary( Op, pL, pR ) { } virtual expr_node* Clone() { return new expr_shift(OP_ILLEGAL,0,0); }; // // queries. // virtual BOOL IsShiftOperator() { return TRUE; } virtual EXPR_VALUE GetValue(); }; // // bitwise operators. // class expr_bitwise : public expr_op_binary { public: expr_bitwise( OPERATOR Op, expr_node *pL, expr_node *pR ): expr_op_binary( Op, pL, pR ) { } virtual expr_node* Clone() { return new expr_bitwise(OP_ILLEGAL,0,0); }; // // queries. // virtual BOOL IsBitwiseOperator() { return TRUE; } virtual EXPR_VALUE GetValue(); }; // // dot operator. // class expr_dot : public expr_op_binary { public: expr_dot( expr_node *pL, expr_node *pR ): expr_op_binary( OP_DOT, pL, pR ) { } virtual expr_node* Clone() { return new expr_dot(0,0); }; }; // // pointsto operator. // class expr_pointsto : public expr_op_binary { public: expr_pointsto( expr_node *pL, expr_node *pR ): expr_op_binary( OP_POINTSTO, pL, pR ) { } virtual expr_node* Clone() { return new expr_pointsto(0,0); }; }; // // array element operator. // class expr_index : public expr_op_binary { public: expr_index( expr_node *pL, expr_node *pR ); virtual expr_node* Clone() { return new expr_index(0,0); }; // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); virtual void PrintCall( ISTREAM * pS, short LeftMargin, BOOL fInProc ); }; // // comma operator. // class expr_comma : public expr_op_binary { public: expr_comma( expr_node *pL, expr_node *pR ): expr_op_binary( OP_COMMA, pL, pR ) { } virtual expr_node* Clone() { return new expr_comma(0,0); }; }; // // assign operator. // class expr_assign : public expr_op_binary { public: expr_assign( expr_node *pL, expr_node *pR ): expr_op_binary( OP_ASSIGN, pL, pR ) { } virtual expr_node* Clone() { return new expr_assign(0,0); }; virtual void PrintCall( ISTREAM * pS, short LeftMargin, BOOL fInProc ); }; // // proc operator. // class expr_proc_call : public expr_op_unary { private: PNAME pName; short NoOfParams; // // Set the first parameter of the function. This is a private method // because the world should use the SetParam function which will take care // of inserting the new param expression in the correct (last) place in the // parameter list. // class expr_param * SetFirstParam( class expr_param * p ) { return (class expr_param *)SetLeft( (class expr_node *) p ); } public: expr_proc_call(PNAME pN, expr_node *pParamList): expr_op_unary(OP_FUNCTION,pParamList) { SetName( pN ); SetNoOfParams( 0 ); } expr_proc_call( PNAME pN ) : expr_op_unary(OP_FUNCTION, 0) { SetName( pN ); SetNoOfParams( 0 ); } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_proc_call(0); }; // // get and set functions. // void SetName( PNAME pN ) { pName = pN; } PNAME GetName() { return pName; } unsigned short SetNoOfParams( unsigned short N ) { return (NoOfParams = N); } unsigned short GetNoOfParams() { return NoOfParams; } unsigned short IncrNoOfParams() { return (++NoOfParams); } // // This method is used to get at the first param of a function. After // that GetNextParam calls are made on the param node itself. This will // be our most frequent usage, eg in the printing of the expression. // class expr_param * GetFirstParam() { return (class expr_param *)GetLeft(); } // // This method will insert the parameter expression at the end of the // parameter list. This is done so that an procedure call expression // can be created in the natural (left to right) order. // class expr_param * SetParam( class expr_param * pParam ); class expr_param * SetParam( expr_node * pExpr ); // // Given an output steam, output the expression. This does not // generate a semi-colon. // virtual void Print( ISTREAM * pS ); // // This call generates a call with a semi-colon // virtual void PrintCall( ISTREAM * pS, short InitMargin, BOOL fInProc ); }; class expr_param : public expr_op_binary { private: PNAME pName; public: expr_param(expr_node *pParamExpr ): expr_op_binary(OP_PARAM,pParamExpr, 0) { pName = NULL; } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_param(0); }; // // queries. // // // This method gets the next parameter in the parameter list. To emit the // parameter expressions for a procedure, get the first parameter on the // expr_proc_call node and then make GetNextParam calls on the parameter // till the call returns a null. // expr_param * GetNextParam() { return (expr_param *)GetRight(); } // // This method sets the next param expression to be the one specified. This // method does not traverse the list of params and insert at the end !!. // expr_param * SetNextParam( expr_param * p ) { return (expr_param *)SetRight( p ); } // // This method traverses to the end of the parameter list and inserts a new // param expression at the end .Use this method when a procedure call // expression is being generated. The way to do this is to create a // expr_proc_call node and make as many SetParam calls to it as there are // parameter expressions. They will all get inserted into the parameter list // in the left to right (natural) order, with each new param expression // going to the end of the list. // expr_param * SetLastPeerParam( expr_param * pN ); // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ); virtual void PrintCall( ISTREAM * pS, short LeftMargin, BOOL fInProc ); }; // // ternary operator class. Each ternary operator node takes a relational, left and right // expression connected by the ternary operator. // class expr_ternary : public expr_operator { private: expr_node * pLeft; expr_node * pRight; expr_node * pRelational; public: // // this class is instantiated by specifying the left/right and the // operator. // expr_ternary( OPERATOR Op, expr_node * pRel, expr_node * pL, expr_node * pR ) : expr_operator( Op ) { SetRelational( pRel ); SetLeft( pL ); SetRight( pR ); SetConstant( ( (pL) ? pL->IsConstant() : TRUE ) && ( (pR) ? pR->IsConstant() : TRUE ) && ( (pRel) ? pRel->IsConstant() : TRUE ) ); } virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone(); // // get and set. // virtual expr_node * SetRelational( expr_node *p ) { return (pRelational = p); } virtual expr_node * SetLeft( expr_node *p ) { return (pLeft = p); } virtual expr_node * SetRight( expr_node *p ) { return (pRight = p); } virtual expr_node * GetRelational() { return pRelational; } virtual expr_node * GetLeft() { return pLeft; } virtual expr_node * GetRight() { return pRight; } // // queries. // virtual BOOL IsBinaryOperator() { return TRUE; } // // Given an output steam, output the expression. // void Print( ISTREAM * pS ); virtual EXPR_VALUE GetValue(); // // determine the type of the expression // virtual void DetermineType(); // // analyze the expression // virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); virtual short MakeListOfVars( ITERATOR & pList ); }; // gaj - these are added for now to satisfy the grammar class expr_init_list: public expr_node { private: class expr_init_list * pSibling; class expr_node * pExpr; public: expr_init_list( expr_node * pE ) { pExpr = pE; SetConstant( pE->IsConstant() ); }; virtual void CopyTo( expr_node* lhs ); virtual expr_node* Clone() { return new expr_init_list(0); }; virtual void LinkSibling( class expr_init_list * pIL ) { pSibling = pIL; } // assume only the first value here... virtual EXPR_VALUE GetValue() { return pExpr->GetValue(); } // // Given an output steam, output the expression. // virtual void Print( ISTREAM * pS ) { pExpr->Print( pS ); } // // determine the type of the expression // virtual void DetermineType(); // // analyze the expression // virtual void ExprAnalyze( EXPR_CTXT * pExprCtxt ); }; class expr_error: public expr_node { public: virtual expr_node* Clone() { return new expr_error; }; }; #endif // __EXPR_HXX__