Debugger: Add basic support for types in expressions.
SourceLanguage/CLanguageFamily/ExpressionEvaluationJob: - Add TeamTypeInformation parameter to EvaluateExpression() hook. Adjust implementing subclasses and callers accordingly. CLanguageExpressionEvaluator: - Add class InternalVariableID for representing intermediate variables generated while parsing an expression. - When parsing an identifier, if we were passed in a type information object, then first attempt to resolve the name as a type. If not matched, then fall through to attempting to match it to a value node as before. - When parsing an atom, check if it resulted in a type. If it did, and there still remains more of the expression to parse, then parse the result to see what value/variable to try to apply the typecast to. If the result is a primitive, generate an appropriate internal variable + value node child for it, otherwise use the target variable's child. Then, attempt to typecast it as requested. - Simplify _EatToken(). - If the final result of an expression is a type, configure the result object accordingly. As a result of all the above, an expression can now resolve to a type, allowing the evaluator to take over the duties of parsing the desired type for a typecast request in the variables view, and in addition, expressions themselves can now contain typecasts, which opens up quite a few new possibilities.
This commit is contained in:
parent
9d6cd8b210
commit
af76b51633
@ -91,7 +91,7 @@ ExpressionEvaluationJob::Do()
|
|||||||
|
|
||||||
ValueNode* neededNode = NULL;
|
ValueNode* neededNode = NULL;
|
||||||
result = fLanguage->EvaluateExpression(fExpressionInfo->Expression(),
|
result = fLanguage->EvaluateExpression(fExpressionInfo->Expression(),
|
||||||
fManager, fResultValue, neededNode);
|
fManager, fTeam->GetTeamTypeInformation(), fResultValue, neededNode);
|
||||||
if (neededNode != NULL) {
|
if (neededNode != NULL) {
|
||||||
result = ResolveNodeValue(neededNode);
|
result = ResolveNodeValue(neededNode);
|
||||||
if (State() == JOB_STATE_WAITING)
|
if (State() == JOB_STATE_WAITING)
|
||||||
|
@ -30,8 +30,8 @@ SourceLanguage::ParseTypeExpression(const BString& expression,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
SourceLanguage::EvaluateExpression(const BString& expression,
|
SourceLanguage::EvaluateExpression(const BString& expression,
|
||||||
ValueNodeManager* manager, ExpressionResult*& _resultValue,
|
ValueNodeManager* manager, TeamTypeInformation* info,
|
||||||
ValueNode*& _neededNode)
|
ExpressionResult*& _resultValue, ValueNode*& _neededNode)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
|
|
||||||
virtual status_t EvaluateExpression(const BString& expression,
|
virtual status_t EvaluateExpression(const BString& expression,
|
||||||
ValueNodeManager* manager,
|
ValueNodeManager* manager,
|
||||||
|
TeamTypeInformation* info,
|
||||||
ExpressionResult*& _output,
|
ExpressionResult*& _output,
|
||||||
ValueNode*& _neededNode);
|
ValueNode*& _neededNode);
|
||||||
};
|
};
|
||||||
|
@ -18,11 +18,18 @@
|
|||||||
#include "CLanguageTokenizer.h"
|
#include "CLanguageTokenizer.h"
|
||||||
#include "ExpressionInfo.h"
|
#include "ExpressionInfo.h"
|
||||||
#include "FloatValue.h"
|
#include "FloatValue.h"
|
||||||
|
#include "IntegerFormatter.h"
|
||||||
#include "IntegerValue.h"
|
#include "IntegerValue.h"
|
||||||
|
#include "ObjectID.h"
|
||||||
#include "StackFrame.h"
|
#include "StackFrame.h"
|
||||||
|
#include "SyntheticPrimitiveType.h"
|
||||||
|
#include "TeamTypeInformation.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
|
#include "TypeHandlerRoster.h"
|
||||||
|
#include "TypeLookupConstraints.h"
|
||||||
#include "Value.h"
|
#include "Value.h"
|
||||||
|
#include "ValueLocation.h"
|
||||||
#include "ValueNode.h"
|
#include "ValueNode.h"
|
||||||
#include "ValueNodeManager.h"
|
#include "ValueNodeManager.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
@ -142,6 +149,42 @@ static BString TokenTypeToString(int32 type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - CLanguageExpressionEvaluator::InternalVariableID
|
||||||
|
|
||||||
|
|
||||||
|
class CLanguageExpressionEvaluator::InternalVariableID : public ObjectID {
|
||||||
|
public:
|
||||||
|
InternalVariableID(const BVariant& value)
|
||||||
|
:
|
||||||
|
fValue(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~InternalVariableID()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool operator==(const ObjectID& other) const
|
||||||
|
{
|
||||||
|
const InternalVariableID* otherID
|
||||||
|
= dynamic_cast<const InternalVariableID*>(&other);
|
||||||
|
if (otherID == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return fValue == otherID->fValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual uint32 ComputeHashValue() const
|
||||||
|
{
|
||||||
|
return *(uint32*)(&fValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BVariant fValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - CLanguageExpressionEvaluator::Operand
|
// #pragma mark - CLanguageExpressionEvaluator::Operand
|
||||||
|
|
||||||
|
|
||||||
@ -1394,6 +1437,7 @@ private:
|
|||||||
CLanguageExpressionEvaluator::CLanguageExpressionEvaluator()
|
CLanguageExpressionEvaluator::CLanguageExpressionEvaluator()
|
||||||
:
|
:
|
||||||
fTokenizer(new Tokenizer()),
|
fTokenizer(new Tokenizer()),
|
||||||
|
fTypeInfo(NULL),
|
||||||
fNodeManager(NULL)
|
fNodeManager(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -1407,9 +1451,10 @@ CLanguageExpressionEvaluator::~CLanguageExpressionEvaluator()
|
|||||||
|
|
||||||
ExpressionResult*
|
ExpressionResult*
|
||||||
CLanguageExpressionEvaluator::Evaluate(const char* expressionString,
|
CLanguageExpressionEvaluator::Evaluate(const char* expressionString,
|
||||||
ValueNodeManager* manager)
|
ValueNodeManager* manager, TeamTypeInformation* info)
|
||||||
{
|
{
|
||||||
fNodeManager = manager;
|
fNodeManager = manager;
|
||||||
|
fTypeInfo = info;
|
||||||
fTokenizer->SetTo(expressionString);
|
fTokenizer->SetTo(expressionString);
|
||||||
|
|
||||||
Operand value = _ParseSum();
|
Operand value = _ParseSum();
|
||||||
@ -1420,26 +1465,26 @@ CLanguageExpressionEvaluator::Evaluate(const char* expressionString,
|
|||||||
ExpressionResult* result = new(std::nothrow)ExpressionResult;
|
ExpressionResult* result = new(std::nothrow)ExpressionResult;
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
BReference<ExpressionResult> resultReference(result, true);
|
BReference<ExpressionResult> resultReference(result, true);
|
||||||
Value* outputValue = NULL;
|
|
||||||
BVariant primitive = value.PrimitiveValue();
|
|
||||||
if (primitive.IsInteger())
|
|
||||||
outputValue = new(std::nothrow) IntegerValue(primitive);
|
|
||||||
else if (primitive.IsFloat()) {
|
|
||||||
outputValue = new(std::nothrow) FloatValue(
|
|
||||||
primitive.ToDouble());
|
|
||||||
}
|
|
||||||
|
|
||||||
BReference<Value> valueReference;
|
|
||||||
if (outputValue != NULL)
|
|
||||||
valueReference.SetTo(outputValue, true);
|
|
||||||
|
|
||||||
if (value.Kind() == OPERAND_KIND_PRIMITIVE) {
|
if (value.Kind() == OPERAND_KIND_PRIMITIVE) {
|
||||||
if (outputValue == NULL)
|
Value* outputValue = NULL;
|
||||||
return NULL;
|
BVariant primitive = value.PrimitiveValue();
|
||||||
|
if (primitive.IsInteger())
|
||||||
|
outputValue = new(std::nothrow) IntegerValue(primitive);
|
||||||
|
else if (primitive.IsFloat()) {
|
||||||
|
outputValue = new(std::nothrow) FloatValue(
|
||||||
|
primitive.ToDouble());
|
||||||
|
}
|
||||||
|
|
||||||
result->SetToPrimitive(outputValue);
|
BReference<Value> valueReference;
|
||||||
|
if (outputValue != NULL) {
|
||||||
|
valueReference.SetTo(outputValue, true);
|
||||||
|
result->SetToPrimitive(outputValue);
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
} else if (value.Kind() == OPERAND_KIND_VALUE_NODE)
|
} else if (value.Kind() == OPERAND_KIND_VALUE_NODE)
|
||||||
result->SetToValueNode(value.GetValueNode()->NodeChild());
|
result->SetToValueNode(value.GetValueNode()->NodeChild());
|
||||||
|
else if (value.Kind() == OPERAND_KIND_TYPE)
|
||||||
|
result->SetToType(value.GetType());
|
||||||
|
|
||||||
resultReference.Detach();
|
resultReference.Detach();
|
||||||
}
|
}
|
||||||
@ -1638,14 +1683,31 @@ CLanguageExpressionEvaluator::Operand
|
|||||||
CLanguageExpressionEvaluator::_ParseIdentifier(ValueNode* parentNode)
|
CLanguageExpressionEvaluator::_ParseIdentifier(ValueNode* parentNode)
|
||||||
{
|
{
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
|
const BString& identifierName = token.string;
|
||||||
|
|
||||||
|
if (fTypeInfo != NULL) {
|
||||||
|
Type* resultType = NULL;
|
||||||
|
status_t error = fTypeInfo->LookupTypeByName(identifierName,
|
||||||
|
TypeLookupConstraints(), resultType);
|
||||||
|
if (error == B_OK) {
|
||||||
|
BReference<Type> typeReference(resultType, true);
|
||||||
|
return _ParseType(resultType);
|
||||||
|
} else if (error != B_ENTRY_NOT_FOUND) {
|
||||||
|
BString errorMessage;
|
||||||
|
errorMessage.SetToFormat("Failed to look up type name '%s': %"
|
||||||
|
B_PRId32 ".", identifierName.String(), error);
|
||||||
|
throw ParseException(errorMessage.String(), token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we didn't recognize the identifier as a type name, fall through
|
||||||
|
// and see if it's possibly a value
|
||||||
|
}
|
||||||
|
|
||||||
if (fNodeManager == NULL) {
|
if (fNodeManager == NULL) {
|
||||||
throw ParseException("Identifiers not resolvable without manager.",
|
throw ParseException("Identifiers not resolvable without manager.",
|
||||||
token.position);
|
token.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
const BString& identifierName = token.string;
|
|
||||||
|
|
||||||
ValueNodeContainer* container = fNodeManager->GetContainer();
|
ValueNodeContainer* container = fNodeManager->GetContainer();
|
||||||
AutoLocker<ValueNodeContainer> containerLocker(container);
|
AutoLocker<ValueNodeContainer> containerLocker(container);
|
||||||
|
|
||||||
@ -1725,7 +1787,7 @@ CLanguageExpressionEvaluator::_ParseAtom()
|
|||||||
{
|
{
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
if (token.type == TOKEN_END_OF_LINE)
|
if (token.type == TOKEN_END_OF_LINE)
|
||||||
throw ParseException("unexpected end of expression", token.position);
|
throw ParseException("Unexpected end of expression", token.position);
|
||||||
|
|
||||||
Operand value;
|
Operand value;
|
||||||
|
|
||||||
@ -1741,6 +1803,41 @@ CLanguageExpressionEvaluator::_ParseAtom()
|
|||||||
_EatToken(TOKEN_CLOSING_PAREN);
|
_EatToken(TOKEN_CLOSING_PAREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value.Kind() == OPERAND_KIND_TYPE) {
|
||||||
|
token = fTokenizer->NextToken();
|
||||||
|
if (token.type == TOKEN_END_OF_LINE)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
Type* castType = value.GetType();
|
||||||
|
// if our evaluated result was a type, and there still remain
|
||||||
|
// further tokens to evaluate, then this is a typecast for
|
||||||
|
// a subsequent expression. Attempt to evaluate it, and then
|
||||||
|
// apply the cast to the result.
|
||||||
|
fTokenizer->RewindToken();
|
||||||
|
value = _ParseSum();
|
||||||
|
ValueNodeChild* child = NULL;
|
||||||
|
if (value.Kind() != OPERAND_KIND_PRIMITIVE
|
||||||
|
&& value.Kind() != OPERAND_KIND_VALUE_NODE) {
|
||||||
|
throw ParseException("Expected value or variable expression after"
|
||||||
|
" typecast.", token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Kind() == OPERAND_KIND_VALUE_NODE)
|
||||||
|
child = value.GetValueNode()->NodeChild();
|
||||||
|
else if (value.Kind() == OPERAND_KIND_PRIMITIVE)
|
||||||
|
_GetNodeChildForPrimitive(token, value.PrimitiveValue(), child);
|
||||||
|
|
||||||
|
ValueNode* newNode = NULL;
|
||||||
|
status_t error = TypeHandlerRoster::Default()->CreateValueNode(child,
|
||||||
|
castType, newNode);
|
||||||
|
if (error != B_OK) {
|
||||||
|
throw ParseException("Unable to create value node for typecast"
|
||||||
|
" operation.", token.position);
|
||||||
|
}
|
||||||
|
child->SetNode(newNode);
|
||||||
|
value.SetTo(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1760,28 +1857,6 @@ CLanguageExpressionEvaluator::_EatToken(int32 type)
|
|||||||
expected = "a constant";
|
expected = "a constant";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_PLUS:
|
|
||||||
case TOKEN_MINUS:
|
|
||||||
case TOKEN_STAR:
|
|
||||||
case TOKEN_MODULO:
|
|
||||||
case TOKEN_POWER:
|
|
||||||
case TOKEN_OPENING_PAREN:
|
|
||||||
case TOKEN_CLOSING_PAREN:
|
|
||||||
case TOKEN_LOGICAL_AND:
|
|
||||||
case TOKEN_BITWISE_AND:
|
|
||||||
case TOKEN_LOGICAL_OR:
|
|
||||||
case TOKEN_BITWISE_OR:
|
|
||||||
case TOKEN_LOGICAL_NOT:
|
|
||||||
case TOKEN_BITWISE_NOT:
|
|
||||||
case TOKEN_EQ:
|
|
||||||
case TOKEN_NE:
|
|
||||||
case TOKEN_GT:
|
|
||||||
case TOKEN_GE:
|
|
||||||
case TOKEN_LT:
|
|
||||||
case TOKEN_LE:
|
|
||||||
expected << "'" << TokenTypeToString(type) << "'";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TOKEN_SLASH:
|
case TOKEN_SLASH:
|
||||||
expected = "'/', '\\', or ':'";
|
expected = "'/', '\\', or ':'";
|
||||||
break;
|
break;
|
||||||
@ -1789,7 +1864,12 @@ CLanguageExpressionEvaluator::_EatToken(int32 type)
|
|||||||
case TOKEN_END_OF_LINE:
|
case TOKEN_END_OF_LINE:
|
||||||
expected = "'\\n'";
|
expected = "'\\n'";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
expected << "'" << TokenTypeToString(type) << "'";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BString temp;
|
BString temp;
|
||||||
temp << "Expected " << expected.String() << " got '" << token.string
|
temp << "Expected " << expected.String() << " got '" << token.string
|
||||||
<< "'";
|
<< "'";
|
||||||
@ -1798,6 +1878,76 @@ CLanguageExpressionEvaluator::_EatToken(int32 type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLanguageExpressionEvaluator::Operand
|
||||||
|
CLanguageExpressionEvaluator::_ParseType(Type* baseType)
|
||||||
|
{
|
||||||
|
BReference<Type> typeReference;
|
||||||
|
Type* finalType = baseType;
|
||||||
|
|
||||||
|
bool arraySpecifierEncountered = false;
|
||||||
|
status_t error;
|
||||||
|
for (;;) {
|
||||||
|
Token token = fTokenizer->NextToken();
|
||||||
|
if (token.type == TOKEN_STAR || token.type == TOKEN_BITWISE_AND) {
|
||||||
|
if (arraySpecifierEncountered)
|
||||||
|
break;
|
||||||
|
|
||||||
|
address_type_kind addressKind = (token.type == TOKEN_STAR)
|
||||||
|
? DERIVED_TYPE_POINTER : DERIVED_TYPE_REFERENCE;
|
||||||
|
AddressType* derivedType = NULL;
|
||||||
|
error = finalType->CreateDerivedAddressType(addressKind,
|
||||||
|
derivedType);
|
||||||
|
if (error != B_OK) {
|
||||||
|
BString errorMessage;
|
||||||
|
errorMessage.SetToFormat("Failed to create derived address"
|
||||||
|
" type %d for base type %s: %s (%" B_PRId32 ")",
|
||||||
|
addressKind, finalType->Name().String(), strerror(error),
|
||||||
|
error);
|
||||||
|
throw ParseException(errorMessage, token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
finalType = derivedType;
|
||||||
|
typeReference.SetTo(finalType, true);
|
||||||
|
} else if (token.type == TOKEN_OPENING_SQUARE_BRACKET) {
|
||||||
|
Operand indexSize = _ParseSum();
|
||||||
|
if (indexSize.Kind() == OPERAND_KIND_TYPE) {
|
||||||
|
throw ParseException("Cannot specify type name as array"
|
||||||
|
" subscript.", token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
_EatToken(TOKEN_CLOSING_SQUARE_BRACKET);
|
||||||
|
|
||||||
|
uint32 resolvedSize = indexSize.PrimitiveValue().ToUInt32();
|
||||||
|
if (resolvedSize == 0) {
|
||||||
|
throw ParseException("Non-zero array size required in type"
|
||||||
|
" specifier.", token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayType* derivedType = NULL;
|
||||||
|
error = finalType->CreateDerivedArrayType(0, resolvedSize, true,
|
||||||
|
derivedType);
|
||||||
|
if (error != B_OK) {
|
||||||
|
BString errorMessage;
|
||||||
|
errorMessage.SetToFormat("Failed to create derived array type"
|
||||||
|
" of size %" B_PRIu32 " for base type %s: %s (%"
|
||||||
|
B_PRId32 ")", resolvedSize, finalType->Name().String(),
|
||||||
|
strerror(error), error);
|
||||||
|
throw ParseException(errorMessage, token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
arraySpecifierEncountered = true;
|
||||||
|
finalType = derivedType;
|
||||||
|
typeReference.SetTo(finalType, true);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
typeReference.Detach();
|
||||||
|
fTokenizer->RewindToken();
|
||||||
|
return Operand(finalType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CLanguageExpressionEvaluator::_RequestValueIfNeeded(
|
CLanguageExpressionEvaluator::_RequestValueIfNeeded(
|
||||||
const Token& token, ValueNodeChild* child)
|
const Token& token, ValueNodeChild* child)
|
||||||
@ -1832,3 +1982,59 @@ CLanguageExpressionEvaluator::_RequestValueIfNeeded(
|
|||||||
throw ParseException(errorMessage, token.position);
|
throw ParseException(errorMessage, token.position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CLanguageExpressionEvaluator::_GetNodeChildForPrimitive(const Token& token,
|
||||||
|
const BVariant& value, ValueNodeChild*& _output) const
|
||||||
|
{
|
||||||
|
Type* type = new(std::nothrow) SyntheticPrimitiveType(value.Type());
|
||||||
|
if (type == NULL) {
|
||||||
|
throw ParseException("Out of memory while creating type object.",
|
||||||
|
token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
BReference<Type> typeReference(type, true);
|
||||||
|
ValueLocation* location = new(std::nothrow) ValueLocation();
|
||||||
|
if (location == NULL) {
|
||||||
|
throw ParseException("Out of memory while creating location object.",
|
||||||
|
token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
BReference<ValueLocation> locationReference(location, true);
|
||||||
|
ValuePieceLocation piece;
|
||||||
|
if (!piece.SetToValue(value.Bytes(), value.Size())
|
||||||
|
|| !location->AddPiece(piece)) {
|
||||||
|
throw ParseException("Out of memory populating location"
|
||||||
|
" object.", token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
char variableName[32];
|
||||||
|
if (!IntegerFormatter::FormatValue(value, INTEGER_FORMAT_HEX_DEFAULT,
|
||||||
|
variableName, sizeof(variableName))) {
|
||||||
|
throw ParseException("Failed to generate internal variable name.",
|
||||||
|
token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalVariableID* id = new(std::nothrow) InternalVariableID(value);
|
||||||
|
if (id == NULL) {
|
||||||
|
throw ParseException("Out of memory while creating ID object.",
|
||||||
|
token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
BReference<ObjectID> idReference(id, true);
|
||||||
|
Variable* variable = new(std::nothrow) Variable(id, variableName, type,
|
||||||
|
location);
|
||||||
|
if (variable == NULL) {
|
||||||
|
throw ParseException("Out of memory while creating variable object.",
|
||||||
|
token.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
BReference<Variable> variableReference(variable, true);
|
||||||
|
_output = new(std::nothrow) VariableValueNodeChild(
|
||||||
|
variable);
|
||||||
|
if (_output == NULL) {
|
||||||
|
throw ParseException("Out of memory while creating node child object.",
|
||||||
|
token.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,7 +20,9 @@ namespace CLanguage {
|
|||||||
class Tokenizer;
|
class Tokenizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BVariant;
|
||||||
|
class TeamTypeInformation;
|
||||||
|
class Type;
|
||||||
class ValueNode;
|
class ValueNode;
|
||||||
class ValueNodeChild;
|
class ValueNodeChild;
|
||||||
class ValueNodeManager;
|
class ValueNodeManager;
|
||||||
@ -45,17 +47,19 @@ class Number;
|
|||||||
|
|
||||||
class CLanguageExpressionEvaluator {
|
class CLanguageExpressionEvaluator {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CLanguageExpressionEvaluator();
|
CLanguageExpressionEvaluator();
|
||||||
~CLanguageExpressionEvaluator();
|
~CLanguageExpressionEvaluator();
|
||||||
|
|
||||||
ExpressionResult* Evaluate(const char* expressionString,
|
ExpressionResult* Evaluate(const char* expressionString,
|
||||||
ValueNodeManager* manager);
|
ValueNodeManager* manager,
|
||||||
|
TeamTypeInformation* info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class InternalVariableID;
|
||||||
class Operand;
|
class Operand;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Operand _ParseSum();
|
Operand _ParseSum();
|
||||||
Operand _ParseProduct();
|
Operand _ParseProduct();
|
||||||
Operand _ParsePower();
|
Operand _ParsePower();
|
||||||
@ -65,11 +69,27 @@ class CLanguageExpressionEvaluator {
|
|||||||
|
|
||||||
void _EatToken(int32 type);
|
void _EatToken(int32 type);
|
||||||
|
|
||||||
|
Operand _ParseType(Type* baseType);
|
||||||
|
// the passed in Type object
|
||||||
|
// is expected to be the initial
|
||||||
|
// base type that was recognized by
|
||||||
|
// e.g. ParseIdentifier. This function then
|
||||||
|
// takes care of handling any modifiers
|
||||||
|
// that go with it, and returns a
|
||||||
|
// corresponding final type.
|
||||||
|
|
||||||
void _RequestValueIfNeeded(
|
void _RequestValueIfNeeded(
|
||||||
const CLanguage::Token& token,
|
const CLanguage::Token& token,
|
||||||
ValueNodeChild* child);
|
ValueNodeChild* child);
|
||||||
|
|
||||||
|
void _GetNodeChildForPrimitive(
|
||||||
|
const CLanguage::Token& token,
|
||||||
|
const BVariant& value,
|
||||||
|
ValueNodeChild*& _output) const;
|
||||||
|
|
||||||
|
private:
|
||||||
CLanguage::Tokenizer* fTokenizer;
|
CLanguage::Tokenizer* fTokenizer;
|
||||||
|
TeamTypeInformation* fTypeInfo;
|
||||||
ValueNodeManager* fNodeManager;
|
ValueNodeManager* fNodeManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,14 +169,14 @@ CLanguageFamily::ParseTypeExpression(const BString& expression,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
CLanguageFamily::EvaluateExpression(const BString& expression,
|
CLanguageFamily::EvaluateExpression(const BString& expression,
|
||||||
ValueNodeManager* manager, ExpressionResult*& _output,
|
ValueNodeManager* manager, TeamTypeInformation* info,
|
||||||
ValueNode*& _neededNode)
|
ExpressionResult*& _output, ValueNode*& _neededNode)
|
||||||
{
|
{
|
||||||
_output = NULL;
|
_output = NULL;
|
||||||
_neededNode = NULL;
|
_neededNode = NULL;
|
||||||
CLanguageExpressionEvaluator evaluator;
|
CLanguageExpressionEvaluator evaluator;
|
||||||
try {
|
try {
|
||||||
_output = evaluator.Evaluate(expression, manager);
|
_output = evaluator.Evaluate(expression, manager, info);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} catch (ParseException ex) {
|
} catch (ParseException ex) {
|
||||||
BString error;
|
BString error;
|
||||||
|
@ -23,6 +23,7 @@ public:
|
|||||||
|
|
||||||
virtual status_t EvaluateExpression(const BString& expression,
|
virtual status_t EvaluateExpression(const BString& expression,
|
||||||
ValueNodeManager* manager,
|
ValueNodeManager* manager,
|
||||||
|
TeamTypeInformation* info,
|
||||||
ExpressionResult*& _output,
|
ExpressionResult*& _output,
|
||||||
ValueNode*& _neededNode);
|
ValueNode*& _neededNode);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user