2088 lines
40 KiB
C++
2088 lines
40 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
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 <stdio.h>
|
|
|
|
}
|
|
#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__
|