Debugger: Rework expression evaluator.
CLanguageExpressionEvaluator: - Revise to make use of Number class rather than MAPM. In the process, implement support for bitwise operators. SourceLanguage/CLanguageFamily/CLanguageExpressionEvaluator: - Adjust interface for expression evaluation to allow specifying the type to evaluate the expression as. Adjust implementing classes accordingly. ExpressionEvaluationWindow: - Adjust to new expression interface. For now defaults to 64-bit integer type, UI for type selection to be added.
This commit is contained in:
parent
1c6c5f3b57
commit
fc8713b02e
@ -11,7 +11,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "CLanguageExpressionEvaluator.h"
|
#include "CLanguageExpressionEvaluator.h"
|
||||||
|
#include "FloatValue.h"
|
||||||
#include "IntegerValue.h"
|
#include "IntegerValue.h"
|
||||||
|
#include "Number.h"
|
||||||
#include "StringValue.h"
|
#include "StringValue.h"
|
||||||
#include "TeamTypeInformation.h"
|
#include "TeamTypeInformation.h"
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
@ -165,16 +167,36 @@ CLanguageFamily::ParseTypeExpression(const BString& expression,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
CLanguageFamily::EvaluateExpression(const BString& expression, Value*& _output)
|
CLanguageFamily::EvaluateExpression(const BString& expression,
|
||||||
|
type_code type, Value*& _output)
|
||||||
{
|
{
|
||||||
_output = NULL;
|
_output = NULL;
|
||||||
CLanguageExpressionEvaluator evaluator;
|
CLanguageExpressionEvaluator evaluator;
|
||||||
evaluator.SetSupportHexInput(true);
|
Number result;
|
||||||
int64 resultValue;
|
|
||||||
try {
|
try {
|
||||||
resultValue = evaluator.EvaluateToInt64(expression);
|
result = evaluator.Evaluate(expression, type);
|
||||||
BVariant variantValue(resultValue);
|
BVariant resultValue = result.GetValue();
|
||||||
_output = new(std::nothrow) IntegerValue(variantValue);
|
switch (type) {
|
||||||
|
case B_INT8_TYPE:
|
||||||
|
case B_UINT8_TYPE:
|
||||||
|
case B_INT16_TYPE:
|
||||||
|
case B_UINT16_TYPE:
|
||||||
|
case B_INT32_TYPE:
|
||||||
|
case B_UINT32_TYPE:
|
||||||
|
case B_INT64_TYPE:
|
||||||
|
case B_UINT64_TYPE:
|
||||||
|
_output = new(std::nothrow) IntegerValue(resultValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_FLOAT_TYPE:
|
||||||
|
_output = new(std::nothrow) FloatValue(resultValue.ToFloat());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_DOUBLE_TYPE:
|
||||||
|
_output = new(std::nothrow) FloatValue(resultValue.ToDouble());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (_output == NULL)
|
if (_output == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public:
|
|||||||
Type*& _resultType) const;
|
Type*& _resultType) const;
|
||||||
|
|
||||||
virtual status_t EvaluateExpression(const BString& expression,
|
virtual status_t EvaluateExpression(const BString& expression,
|
||||||
Value*& _output);
|
type_code type, Value*& _output);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool IsModifierValid(char modifier) const = 0;
|
virtual bool IsModifierValid(char modifier) const = 0;
|
||||||
|
@ -30,7 +30,7 @@ SourceLanguage::ParseTypeExpression(const BString& expression,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
SourceLanguage::EvaluateExpression(const BString& expression,
|
SourceLanguage::EvaluateExpression(const BString& expression,
|
||||||
Value*& _resultValue)
|
type_code type, Value*& _resultValue)
|
||||||
{
|
{
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ public:
|
|||||||
Type*& _resultType) const;
|
Type*& _resultType) const;
|
||||||
|
|
||||||
virtual status_t EvaluateExpression(const BString& expression,
|
virtual status_t EvaluateExpression(const BString& expression,
|
||||||
Value*& _output);
|
type_code type, Value*& _output);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,17 +11,13 @@
|
|||||||
|
|
||||||
#include "CLanguageExpressionEvaluator.h"
|
#include "CLanguageExpressionEvaluator.h"
|
||||||
|
|
||||||
|
#include "Number.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
#include <m_apm.h>
|
|
||||||
|
|
||||||
|
|
||||||
static const int32 kMaxDecimalPlaces = 32;
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TOKEN_NONE = 0,
|
TOKEN_NONE = 0,
|
||||||
@ -47,6 +43,7 @@ enum {
|
|||||||
TOKEN_BITWISE_AND,
|
TOKEN_BITWISE_AND,
|
||||||
TOKEN_BITWISE_OR,
|
TOKEN_BITWISE_OR,
|
||||||
TOKEN_BITWISE_NOT,
|
TOKEN_BITWISE_NOT,
|
||||||
|
TOKEN_BITWISE_XOR,
|
||||||
TOKEN_EQ,
|
TOKEN_EQ,
|
||||||
TOKEN_NE,
|
TOKEN_NE,
|
||||||
TOKEN_GT,
|
TOKEN_GT,
|
||||||
@ -81,7 +78,7 @@ static BString TokenTypeToString(int32 type)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_POWER:
|
case TOKEN_POWER:
|
||||||
token = "^";
|
token = "**";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_OPENING_BRACKET:
|
case TOKEN_OPENING_BRACKET:
|
||||||
@ -116,6 +113,10 @@ static BString TokenTypeToString(int32 type)
|
|||||||
token = "~";
|
token = "~";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOKEN_BITWISE_XOR:
|
||||||
|
token = "^";
|
||||||
|
break;
|
||||||
|
|
||||||
case TOKEN_EQ:
|
case TOKEN_EQ:
|
||||||
token = "==";
|
token = "==";
|
||||||
break;
|
break;
|
||||||
@ -153,7 +154,7 @@ struct CLanguageExpressionEvaluator::Token {
|
|||||||
Token()
|
Token()
|
||||||
: string(""),
|
: string(""),
|
||||||
type(TOKEN_NONE),
|
type(TOKEN_NONE),
|
||||||
value(0),
|
value(0L),
|
||||||
position(0)
|
position(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -169,7 +170,7 @@ struct CLanguageExpressionEvaluator::Token {
|
|||||||
Token(const char* string, int32 length, int32 position, int32 type)
|
Token(const char* string, int32 length, int32 position, int32 type)
|
||||||
: string(string, length),
|
: string(string, length),
|
||||||
type(type),
|
type(type),
|
||||||
value(0),
|
value(),
|
||||||
position(position)
|
position(position)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -185,7 +186,7 @@ struct CLanguageExpressionEvaluator::Token {
|
|||||||
|
|
||||||
BString string;
|
BString string;
|
||||||
int32 type;
|
int32 type;
|
||||||
MAPM value;
|
Number value;
|
||||||
|
|
||||||
int32 position;
|
int32 position;
|
||||||
};
|
};
|
||||||
@ -198,15 +199,10 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
fCurrentChar(NULL),
|
fCurrentChar(NULL),
|
||||||
fCurrentToken(),
|
fCurrentToken(),
|
||||||
fReuseToken(false),
|
fReuseToken(false),
|
||||||
fHexSupport(false)
|
fType(B_INT32_TYPE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSupportHexInput(bool enabled)
|
|
||||||
{
|
|
||||||
fHexSupport = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTo(const char* string)
|
void SetTo(const char* string)
|
||||||
{
|
{
|
||||||
fString = string;
|
fString = string;
|
||||||
@ -215,6 +211,11 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
fReuseToken = false;
|
fReuseToken = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetType(type_code type)
|
||||||
|
{
|
||||||
|
fType = type;
|
||||||
|
}
|
||||||
|
|
||||||
const Token& NextToken()
|
const Token& NextToken()
|
||||||
{
|
{
|
||||||
if (fCurrentToken.type == TOKEN_END_OF_LINE)
|
if (fCurrentToken.type == TOKEN_END_OF_LINE)
|
||||||
@ -235,7 +236,7 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
bool decimal = *fCurrentChar == '.' || *fCurrentChar == ',';
|
bool decimal = *fCurrentChar == '.' || *fCurrentChar == ',';
|
||||||
|
|
||||||
if (decimal || isdigit(*fCurrentChar)) {
|
if (decimal || isdigit(*fCurrentChar)) {
|
||||||
if (fHexSupport && *fCurrentChar == '0' && fCurrentChar[1] == 'x')
|
if (*fCurrentChar == '0' && fCurrentChar[1] == 'x')
|
||||||
return _ParseHexNumber();
|
return _ParseHexNumber();
|
||||||
|
|
||||||
BString temp;
|
BString temp;
|
||||||
@ -297,7 +298,7 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
|
|
||||||
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
||||||
TOKEN_CONSTANT);
|
TOKEN_CONSTANT);
|
||||||
fCurrentToken.value = temp.String();
|
fCurrentToken.value.SetTo(fType, temp.String());
|
||||||
} else if (isalpha(*fCurrentChar) && *fCurrentChar != 'x') {
|
} else if (isalpha(*fCurrentChar) && *fCurrentChar != 'x') {
|
||||||
const char* begin = fCurrentChar;
|
const char* begin = fCurrentChar;
|
||||||
while (*fCurrentChar != 0 && (isalpha(*fCurrentChar)
|
while (*fCurrentChar != 0 && (isalpha(*fCurrentChar)
|
||||||
@ -331,13 +332,6 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
type = TOKEN_SLASH;
|
type = TOKEN_SLASH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
|
||||||
if (!fHexSupport) {
|
|
||||||
type = TOKEN_STAR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw ParseException("unexpected character",
|
throw ParseException("unexpected character",
|
||||||
_CurrentPos());
|
_CurrentPos());
|
||||||
@ -367,8 +361,14 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
type = TOKEN_STAR;
|
if (Peek() == '*') {
|
||||||
length = 1;
|
type = TOKEN_POWER;
|
||||||
|
length = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
type = TOKEN_STAR;
|
||||||
|
length = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
@ -382,7 +382,7 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '^':
|
case '^':
|
||||||
type = TOKEN_POWER;
|
type = TOKEN_BITWISE_XOR;
|
||||||
length = 1;
|
length = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -497,18 +497,7 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
fCurrentToken = Token(begin, length, _CurrentPos() - length,
|
||||||
TOKEN_CONSTANT);
|
TOKEN_CONSTANT);
|
||||||
|
|
||||||
// MAPM has no conversion from long long, so we need to improvise.
|
fCurrentToken.value.SetTo(fType, fCurrentToken.string.String(), 16);
|
||||||
uint64 value = strtoll(fCurrentToken.string.String(), NULL, 0);
|
|
||||||
if (value <= 0x7fffffff) {
|
|
||||||
fCurrentToken.value = (long)value;
|
|
||||||
} else {
|
|
||||||
fCurrentToken.value = (int)(value >> 60);
|
|
||||||
fCurrentToken.value *= 1 << 30;
|
|
||||||
fCurrentToken.value += (int)((value >> 30) & 0x3fffffff);
|
|
||||||
fCurrentToken.value *= 1 << 30;
|
|
||||||
fCurrentToken.value += (int)(value& 0x3fffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fCurrentToken;
|
return fCurrentToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +510,7 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
|||||||
const char* fCurrentChar;
|
const char* fCurrentChar;
|
||||||
Token fCurrentToken;
|
Token fCurrentToken;
|
||||||
bool fReuseToken;
|
bool fReuseToken;
|
||||||
bool fHexSupport;
|
type_code fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -537,80 +526,22 @@ CLanguageExpressionEvaluator::~CLanguageExpressionEvaluator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
Number
|
||||||
CLanguageExpressionEvaluator::SetSupportHexInput(bool enabled)
|
CLanguageExpressionEvaluator::Evaluate(const char* expressionString, type_code type)
|
||||||
{
|
|
||||||
fTokenizer->SetSupportHexInput(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BString
|
|
||||||
CLanguageExpressionEvaluator::Evaluate(const char* expressionString)
|
|
||||||
{
|
{
|
||||||
|
fTokenizer->SetType(type);
|
||||||
fTokenizer->SetTo(expressionString);
|
fTokenizer->SetTo(expressionString);
|
||||||
|
|
||||||
MAPM value = _ParseBinary();
|
Number value = _ParseBinary();
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
if (token.type != TOKEN_END_OF_LINE)
|
if (token.type != TOKEN_END_OF_LINE)
|
||||||
throw ParseException("parse error", token.position);
|
throw ParseException("parse error", token.position);
|
||||||
|
|
||||||
if (value == 0)
|
return value;
|
||||||
return BString("0");
|
|
||||||
|
|
||||||
char* buffer = value.toFixPtStringExp(kMaxDecimalPlaces, '.', 0, 0);
|
|
||||||
if (buffer == NULL)
|
|
||||||
throw ParseException("out of memory", 0);
|
|
||||||
|
|
||||||
// remove surplus zeros
|
|
||||||
int32 lastChar = strlen(buffer) - 1;
|
|
||||||
if (strchr(buffer, '.')) {
|
|
||||||
while (buffer[lastChar] == '0')
|
|
||||||
lastChar--;
|
|
||||||
if (buffer[lastChar] == '.')
|
|
||||||
lastChar--;
|
|
||||||
}
|
|
||||||
|
|
||||||
BString result(buffer, lastChar + 1);
|
|
||||||
free(buffer);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int64
|
Number
|
||||||
CLanguageExpressionEvaluator::EvaluateToInt64(const char* expressionString)
|
|
||||||
{
|
|
||||||
fTokenizer->SetTo(expressionString);
|
|
||||||
|
|
||||||
MAPM value = _ParseBinary();
|
|
||||||
Token token = fTokenizer->NextToken();
|
|
||||||
if (token.type != TOKEN_END_OF_LINE)
|
|
||||||
throw ParseException("parse error", token.position);
|
|
||||||
|
|
||||||
char buffer[128];
|
|
||||||
value.toIntegerString(buffer);
|
|
||||||
|
|
||||||
return strtoll(buffer, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
double
|
|
||||||
CLanguageExpressionEvaluator::EvaluateToDouble(const char* expressionString)
|
|
||||||
{
|
|
||||||
fTokenizer->SetTo(expressionString);
|
|
||||||
|
|
||||||
MAPM value = _ParseBinary();
|
|
||||||
Token token = fTokenizer->NextToken();
|
|
||||||
if (token.type != TOKEN_END_OF_LINE)
|
|
||||||
throw ParseException("parse error", token.position);
|
|
||||||
|
|
||||||
char buffer[1024];
|
|
||||||
value.toString(buffer, sizeof(buffer) - 4);
|
|
||||||
|
|
||||||
return strtod(buffer, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MAPM
|
|
||||||
CLanguageExpressionEvaluator::_ParseBinary()
|
CLanguageExpressionEvaluator::_ParseBinary()
|
||||||
{
|
{
|
||||||
return _ParseSum();
|
return _ParseSum();
|
||||||
@ -637,20 +568,20 @@ CLanguageExpressionEvaluator::_ParseBinary()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAPM
|
Number
|
||||||
CLanguageExpressionEvaluator::_ParseSum()
|
CLanguageExpressionEvaluator::_ParseSum()
|
||||||
{
|
{
|
||||||
// TODO: check isnan()...
|
// TODO: check isnan()...
|
||||||
MAPM value = _ParseProduct();
|
Number value = _ParseProduct();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
case TOKEN_PLUS:
|
case TOKEN_PLUS:
|
||||||
value = value + _ParseProduct();
|
value += _ParseProduct();
|
||||||
break;
|
break;
|
||||||
case TOKEN_MINUS:
|
case TOKEN_MINUS:
|
||||||
value = value - _ParseProduct();
|
value -= _ParseProduct();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -661,66 +592,86 @@ CLanguageExpressionEvaluator::_ParseSum()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAPM
|
Number
|
||||||
CLanguageExpressionEvaluator::_ParseProduct()
|
CLanguageExpressionEvaluator::_ParseProduct()
|
||||||
{
|
{
|
||||||
// TODO: check isnan()...
|
Number value = _ParsePower();
|
||||||
MAPM value = _ParsePower();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
case TOKEN_STAR:
|
case TOKEN_STAR:
|
||||||
value = value * _ParsePower();
|
value *= _ParsePower();
|
||||||
break;
|
break;
|
||||||
case TOKEN_SLASH:
|
case TOKEN_SLASH:
|
||||||
{
|
{
|
||||||
MAPM rhs = _ParsePower();
|
Number rhs = _ParsePower();
|
||||||
if (rhs == MAPM(0))
|
if (rhs == Number(fCurrentType, 0))
|
||||||
throw ParseException("division by zero", token.position);
|
throw ParseException("division by zero", token.position);
|
||||||
value = value / rhs;
|
value /= rhs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOKEN_MODULO:
|
case TOKEN_MODULO:
|
||||||
{
|
{
|
||||||
MAPM rhs = _ParsePower();
|
Number rhs = _ParsePower();
|
||||||
if (rhs == MAPM(0))
|
if (rhs == Number())
|
||||||
throw ParseException("modulo by zero", token.position);
|
throw ParseException("modulo by zero", token.position);
|
||||||
value = value % rhs;
|
value %= rhs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TOKEN_LOGICAL_AND:
|
case TOKEN_LOGICAL_AND:
|
||||||
value = (value != MAPM(0) && _ParsePower() != MAPM(0));
|
{
|
||||||
|
Number zero(BVariant(0L));
|
||||||
|
value.SetTo(BVariant((int32)((value != zero)
|
||||||
|
&& (_ParsePower() != zero))));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case TOKEN_LOGICAL_OR:
|
case TOKEN_LOGICAL_OR:
|
||||||
value = (value != MAPM(0) || _ParsePower() != MAPM(0));
|
{
|
||||||
|
Number zero(BVariant(0L));
|
||||||
|
value.SetTo(BVariant((int32)((value != zero)
|
||||||
|
|| (_ParsePower() != zero))));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TOKEN_BITWISE_AND:
|
||||||
|
value &= _ParsePower();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOKEN_BITWISE_OR:
|
||||||
|
value |= _ParsePower();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOKEN_BITWISE_XOR:
|
||||||
|
value ^= _ParsePower();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_EQ:
|
case TOKEN_EQ:
|
||||||
value = (value == _ParsePower());
|
value.SetTo(BVariant((int32)(value == _ParsePower())));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_NE:
|
case TOKEN_NE:
|
||||||
value = (value != _ParsePower());
|
value.SetTo(BVariant((int32)(value != _ParsePower())));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_GT:
|
case TOKEN_GT:
|
||||||
value = (value > _ParsePower());
|
value.SetTo(BVariant((int32)(value > _ParsePower())));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_GE:
|
case TOKEN_GE:
|
||||||
value = (value >= _ParsePower());
|
value.SetTo(BVariant((int32)(value >= _ParsePower())));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_LT:
|
case TOKEN_LT:
|
||||||
value = (value < _ParsePower());
|
value.SetTo(BVariant((int32)(value < _ParsePower())));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_LE:
|
case TOKEN_LE:
|
||||||
value = (value <= _ParsePower());
|
value.SetTo(BVariant((int32)(value <= _ParsePower())));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -731,10 +682,10 @@ CLanguageExpressionEvaluator::_ParseProduct()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAPM
|
Number
|
||||||
CLanguageExpressionEvaluator::_ParsePower()
|
CLanguageExpressionEvaluator::_ParsePower()
|
||||||
{
|
{
|
||||||
MAPM value = _ParseUnary();
|
Number value = _ParseUnary();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
@ -742,12 +693,16 @@ CLanguageExpressionEvaluator::_ParsePower()
|
|||||||
fTokenizer->RewindToken();
|
fTokenizer->RewindToken();
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
value = value.pow(_ParseUnary());
|
|
||||||
|
Number power = _ParseUnary();
|
||||||
|
Number temp = value;
|
||||||
|
for (int32 powerValue = power.GetValue().ToInt32(); powerValue > 1; powerValue--)
|
||||||
|
value *= temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAPM
|
Number
|
||||||
CLanguageExpressionEvaluator::_ParseUnary()
|
CLanguageExpressionEvaluator::_ParseUnary()
|
||||||
{
|
{
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
@ -761,13 +716,11 @@ CLanguageExpressionEvaluator::_ParseUnary()
|
|||||||
case TOKEN_MINUS:
|
case TOKEN_MINUS:
|
||||||
return -_ParseUnary();
|
return -_ParseUnary();
|
||||||
|
|
||||||
case TOKEN_BITWISE_AND:
|
|
||||||
case TOKEN_BITWISE_OR:
|
|
||||||
case TOKEN_BITWISE_NOT:
|
case TOKEN_BITWISE_NOT:
|
||||||
throw ParseException("Unimplemented bitwise operator", token.position);
|
return ~_ParseUnary();
|
||||||
|
|
||||||
case TOKEN_LOGICAL_NOT:
|
case TOKEN_LOGICAL_NOT:
|
||||||
return MAPM(_ParseUnary() == 0);
|
return Number((int32)(_ParseUnary() == Number(BVariant(0L))));
|
||||||
|
|
||||||
case TOKEN_IDENTIFIER:
|
case TOKEN_IDENTIFIER:
|
||||||
return _ParseIdentifier();
|
return _ParseIdentifier();
|
||||||
@ -777,7 +730,7 @@ CLanguageExpressionEvaluator::_ParseUnary()
|
|||||||
return _ParseAtom();
|
return _ParseAtom();
|
||||||
}
|
}
|
||||||
|
|
||||||
return MAPM(0);
|
return Number();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -785,21 +738,21 @@ struct Function {
|
|||||||
const char* name;
|
const char* name;
|
||||||
int argumentCount;
|
int argumentCount;
|
||||||
void* function;
|
void* function;
|
||||||
MAPM value;
|
Number value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MAPM
|
Number
|
||||||
CLanguageExpressionEvaluator::_ParseIdentifier()
|
CLanguageExpressionEvaluator::_ParseIdentifier()
|
||||||
{
|
{
|
||||||
throw ParseException("Identifiers not implemented", 0);
|
throw ParseException("Identifiers not implemented", 0);
|
||||||
|
|
||||||
return MAPM(0);
|
return Number();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CLanguageExpressionEvaluator::_InitArguments(MAPM values[], int32 argumentCount)
|
CLanguageExpressionEvaluator::_InitArguments(Number values[], int32 argumentCount)
|
||||||
{
|
{
|
||||||
_EatToken(TOKEN_OPENING_BRACKET);
|
_EatToken(TOKEN_OPENING_BRACKET);
|
||||||
|
|
||||||
@ -810,7 +763,7 @@ CLanguageExpressionEvaluator::_InitArguments(MAPM values[], int32 argumentCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MAPM
|
Number
|
||||||
CLanguageExpressionEvaluator::_ParseAtom()
|
CLanguageExpressionEvaluator::_ParseAtom()
|
||||||
{
|
{
|
||||||
Token token = fTokenizer->NextToken();
|
Token token = fTokenizer->NextToken();
|
||||||
@ -824,7 +777,7 @@ CLanguageExpressionEvaluator::_ParseAtom()
|
|||||||
|
|
||||||
_EatToken(TOKEN_OPENING_BRACKET);
|
_EatToken(TOKEN_OPENING_BRACKET);
|
||||||
|
|
||||||
MAPM value = _ParseBinary();
|
Number value = _ParseBinary();
|
||||||
|
|
||||||
_EatToken(TOKEN_CLOSING_BRACKET);
|
_EatToken(TOKEN_CLOSING_BRACKET);
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class ParseException {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Function;
|
struct Function;
|
||||||
class MAPM;
|
class Number;
|
||||||
|
|
||||||
class CLanguageExpressionEvaluator {
|
class CLanguageExpressionEvaluator {
|
||||||
|
|
||||||
@ -42,30 +42,28 @@ class CLanguageExpressionEvaluator {
|
|||||||
CLanguageExpressionEvaluator();
|
CLanguageExpressionEvaluator();
|
||||||
~CLanguageExpressionEvaluator();
|
~CLanguageExpressionEvaluator();
|
||||||
|
|
||||||
void SetSupportHexInput(bool enabled);
|
Number Evaluate(const char* expressionString,
|
||||||
|
type_code type);
|
||||||
BString Evaluate(const char* expressionString);
|
|
||||||
int64 EvaluateToInt64(const char* expressionString);
|
|
||||||
double EvaluateToDouble(const char* expressionString);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Token;
|
struct Token;
|
||||||
class Tokenizer;
|
class Tokenizer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MAPM _ParseBinary();
|
Number _ParseBinary();
|
||||||
MAPM _ParseSum();
|
Number _ParseSum();
|
||||||
MAPM _ParseProduct();
|
Number _ParseProduct();
|
||||||
MAPM _ParsePower();
|
Number _ParsePower();
|
||||||
MAPM _ParseUnary();
|
Number _ParseUnary();
|
||||||
MAPM _ParseIdentifier();
|
Number _ParseIdentifier();
|
||||||
void _InitArguments(MAPM values[],
|
void _InitArguments(Number values[],
|
||||||
int32 argumentCount);
|
int32 argumentCount);
|
||||||
MAPM _ParseAtom();
|
Number _ParseAtom();
|
||||||
|
|
||||||
void _EatToken(int32 type);
|
void _EatToken(int32 type);
|
||||||
|
|
||||||
Tokenizer* fTokenizer;
|
Tokenizer* fTokenizer;
|
||||||
|
type_code fCurrentType;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // C_LANGUAGE_EXPRESSION_EVALUATOR_H
|
#endif // C_LANGUAGE_EXPRESSION_EVALUATOR_H
|
||||||
|
@ -124,7 +124,7 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
|
|||||||
Value* value = NULL;
|
Value* value = NULL;
|
||||||
BString outputText;
|
BString outputText;
|
||||||
status_t error = fLanguage->EvaluateExpression(
|
status_t error = fLanguage->EvaluateExpression(
|
||||||
fExpressionInput->TextView()->Text(), value);
|
fExpressionInput->TextView()->Text(), B_INT64_TYPE, value);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
value->ToString(outputText);
|
value->ToString(outputText);
|
||||||
|
Loading…
Reference in New Issue
Block a user