You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/languages/cpp/cppevaluation.h

367 lines
11 KiB

/***************************************************************************
begin : Sat Jul 21 2001
copyright : (C) 2001 by Victor R<EFBFBD>er
email : victor_roeder@gmx.de
copyright : (C) 2002,2003 by Roberto Raggi
email : roberto@kdevelop.org
copyright : (C) 2005 by Adam Treat
email : manyoso@yahoo.com
copyright : (C) 2006 by David Nolden
email : david.nolden.kdevelop@art-master.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef CPPEVALUATION_H
#define CPPEVALUATION_H
#include <tqvaluelist.h>
#include "expressioninfo.h"
#include "simpletype.h"
#include "declarationinfo.h"
#include <hashedstring.h>
class SimpleContext;
void statusBarText( const TQString& str, int time = 1000 );
namespace CppEvaluation {
template <class To, class From>
extern TQValueList<To> convertList( const TQValueList<From>& from );
extern TQString nameFromType( SimpleType t );
class Operator;
struct OperatorIdentification {
TQValueList<TQString> innerParams; /** Inner parameters of the operator( for the vec["hello"] the "hello" ) */
int start, end; /** Range the operator occupies */
bool found;
Operator* op; ///Can be 0 !
OperatorIdentification() : start( 0 ), end( 0 ), found( false ), op( 0 ) {}
operator bool() {
return found;
}
};
class EvaluationResult {
public:
EvaluationResult& operator = ( const EvaluationResult& rhs ) {
resultType = rhs.resultType;
sourceVariable = rhs.sourceVariable;
expr = rhs.expr;
isMacro = rhs.isMacro;
macro = rhs.macro;
return *this;
}
EvaluationResult( const EvaluationResult& rhs ) : resultType( rhs.resultType ), expr( rhs.expr ), sourceVariable( rhs.sourceVariable ), isMacro( rhs.isMacro ), macro( rhs.macro ) {}
LocateResult resultType; ///The resulting type
ExpressionInfo expr; ///Information about the expression that was processed
DeclarationInfo sourceVariable; ///If the type comes from a variable, this stores Information about it
bool isMacro;
Macro macro;
///should be removed
EvaluationResult( SimpleType rhs ) : isMacro( false ) {
if ( rhs.get() != 0 )
resultType = rhs->desc();
}
EvaluationResult( LocateResult tp = TypeDesc(), DeclarationInfo var = DeclarationInfo() ) : resultType( tp ), sourceVariable( var ), isMacro( false ) {}
/*operator TypeDesc () const {
return (TypeDesc)resultType;
}*/
///This must be removed
operator SimpleType() const {
if ( resultType->resolved() ) {
return SimpleType( resultType->resolved() );
} else {
return SimpleType( new SimpleTypeImpl( ( TypeDesc ) resultType ) );
}
}
TypeDesc* operator -> () {
return & resultType.desc();
}
operator LocateResult () const {
return resultType;
}
operator bool() const {
return ( bool ) resultType;
}
};
class Operator {
public:
enum BindingSide {
Neutral = 0,
Left = 1,
Right = 2
};
enum Type {
Unary = 1,
Binary = 2,
Ternary = 3
};
virtual ~Operator() {}
virtual int priority() = 0;
virtual Type type() = 0;
virtual int paramCount() = 0;
///"binding" means that the operator needs the evaluated type of the expression on that side
///The types of all bound sides will later be sent in the "params"-list of the apply-function
virtual BindingSide binding() = 0; ///The side to which the operator binds
///When this returns true, the ident-structure must be filled correctly
virtual OperatorIdentification identify( TQString& str ) = 0;
///params
virtual EvaluationResult apply( TQValueList<EvaluationResult> params, TQValueList<EvaluationResult> innerParams ) = 0;
virtual TQString name() = 0;
///Should return whether the item it the given side can be a type(Neutral stands for the inner paremeters)
virtual bool canBeType( BindingSide side ) {
return true;
}
protected:
void log( const TQString& msg );
TQString printTypeList( TQValueList<EvaluationResult>& lst );
};
class OperatorSet {
private:
typedef TQValueList< Operator* > OperatorList;
OperatorList m_operators;
public:
OperatorSet() {}
~OperatorSet();
void registerOperator( Operator* op ) {
m_operators << op;
}
OperatorIdentification identifyOperator( const TQString& str_ , Operator::BindingSide allowedBindings = ( Operator::BindingSide ) ( Operator::Left | Operator::Right | Operator::Neutral ) );
};
extern OperatorSet AllOperators;
template <class OperatorType>
class RegisterOperator {
public:
RegisterOperator( OperatorSet& set
) {
set.registerOperator( new OperatorType() );
}
~RegisterOperator() {}
}
;
class UnaryOperator : public Operator {
public:
UnaryOperator( int priority , TQString identString, TQString description, Operator::BindingSide binding ) : Operator(), m_priority( priority ), m_identString( identString ), m_name( description ), m_binding( binding ) {}
virtual int priority() {
return m_priority;
}
virtual Operator::Type type() {
return Operator::Unary;
}
virtual Operator::BindingSide binding() {
return m_binding;
}
virtual int paramCount() {
return 1;
}
virtual OperatorIdentification identify( TQString& str );
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& innerParams ) = 0;
virtual bool checkParams( const TQValueList<EvaluationResult>& params ) {
return !params.isEmpty() && params[ 0 ];
}
virtual EvaluationResult apply( TQValueList<EvaluationResult> params, TQValueList<EvaluationResult> innerParams );
virtual TQString name() {
return m_name;
}
private:
int m_priority;
TQString m_identString;
TQString m_name;
Operator::BindingSide m_binding;
protected:
TQString identString() const {
return m_identString;
}
};
class NestedTypeOperator : public UnaryOperator {
public:
NestedTypeOperator() : UnaryOperator( 18, "::", "nested-type-operator", Operator::Left ) {}
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& /*innerParams*/ );
};
//RegisterOperator< NestedTypeOperator > NestedTypeReg( AllOperators ); ///This registers the operator to the list of all operators
class DotOperator : public UnaryOperator {
public:
DotOperator() : UnaryOperator( 17, ".", "dot-operator", Operator::Left ) {}
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& /*innerParams*/ );
virtual bool canBeType( BindingSide side ) {
return false;
}
};
class ArrowOperator : public UnaryOperator {
public:
ArrowOperator() : UnaryOperator( 17, "->", "arrow-operator", Operator::Left ) {}
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& innerParams );
virtual bool canBeType( BindingSide side ) {
return false;
}
};
class StarOperator : public UnaryOperator {
public:
StarOperator() : UnaryOperator( 15, "*", "star-operator", Operator::Right ) { ///Normally this should have a priority of 16, but that would need changes to the expression-parsin g-loop
}
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& /*innerParams*/ );
virtual bool canBeType( BindingSide side ) {
return false;
}
};
class AddressOperator : public UnaryOperator {
public:
AddressOperator() : UnaryOperator( 16, "&", "address-operator", Operator::Right ) {}
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& /*innerParams*/ );
virtual bool canBeType( BindingSide side ) {
return false;
}
};
class UnaryParenOperator : public UnaryOperator {
public:
///Identstring should be both parens, for Example "[]" or "()"
UnaryParenOperator( int priority , TQString identString, TQString description, Operator::BindingSide binding ) : UnaryOperator( priority, identString, description, binding ) {}
virtual OperatorIdentification identify( TQString& str );
virtual bool canBeType( BindingSide side ) {
return false;
}
};
class IndexOperator : public UnaryParenOperator {
public:
IndexOperator() : UnaryParenOperator( 17, "[]", "index-operator", Operator::Left ) {}
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& innerParams );
virtual bool canBeType( BindingSide side ) {
return false;
}
};
class ParenOperator : public UnaryParenOperator {
public:
ParenOperator() : UnaryParenOperator( 16, "()", "paren-operator", Operator::Left ) {}
virtual bool checkParams( const TQValueList<EvaluationResult>& params ) {
return !params.isEmpty();
}
virtual EvaluationResult unaryApply( EvaluationResult param, const TQValueList<EvaluationResult>& innerParams );
virtual bool canBeType( BindingSide side ) {
return false;
}
};
//This is used in CppCodeCompletion::evaluateExpression(..)
class ExpressionEvaluation {
private:
CppCodeCompletion* m_data;
SimpleContext* m_ctx;
ExpressionInfo m_expr;
bool m_global;
OperatorSet& m_operators;
HashedStringSet m_includeFiles;
public:
ExpressionEvaluation( CppCodeCompletion* data, ExpressionInfo expr, OperatorSet& operators, const HashedStringSet& includeFiles, SimpleContext* ctx = 0 );
EvaluationResult evaluate();
private:
/**
recursion-method:
1. Find the rightmost operator with the lowest priority, split the expression
vector[ (*it)->position ]().
*/
virtual EvaluationResult evaluateExpressionInternal( TQString expr, EvaluationResult scope, SimpleContext * ctx, SimpleContext* innerCtx , bool canBeTypeExpression = true );
///Locates types or members
EvaluationResult evaluateAtomicExpression( TypeDesc expr, EvaluationResult scope, SimpleContext * ctx = 0, bool canBeTypeExpression = true );
};
}
#endif