windows-nt/Source/XPSP1/NT/com/rpc/midl/expr/expr.hxx
2020-09-26 16:20:57 +08:00

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__