1
0
Fork 0

DBG: formatted ExpressionParser

This commit is contained in:
mrexodia 2016-05-22 15:50:40 +02:00
parent c4777b2984
commit 07f18d442e
4 changed files with 98 additions and 78 deletions

View File

@ -3,23 +3,23 @@
ExpressionParser::Token::Token(const String & data, const Type type) ExpressionParser::Token::Token(const String & data, const Type type)
{ {
_data = data; mData = data;
_type = type; mType = type;
} }
const String & ExpressionParser::Token::data() const const String & ExpressionParser::Token::data() const
{ {
return _data; return mData;
} }
ExpressionParser::Token::Type ExpressionParser::Token::type() const ExpressionParser::Token::Type ExpressionParser::Token::type() const
{ {
return _type; return mType;
} }
ExpressionParser::Token::Associativity ExpressionParser::Token::associativity() const ExpressionParser::Token::Associativity ExpressionParser::Token::associativity() const
{ {
switch(_type) switch(mType)
{ {
case Type::OperatorUnarySub: case Type::OperatorUnarySub:
case Type::OperatorNot: case Type::OperatorNot:
@ -52,7 +52,7 @@ ExpressionParser::Token::Associativity ExpressionParser::Token::associativity()
int ExpressionParser::Token::precedence() const int ExpressionParser::Token::precedence() const
{ {
switch(_type) switch(mType)
{ {
case Type::OperatorUnarySub: case Type::OperatorUnarySub:
case Type::OperatorNot: case Type::OperatorNot:
@ -93,22 +93,22 @@ int ExpressionParser::Token::precedence() const
bool ExpressionParser::Token::isOperator() const bool ExpressionParser::Token::isOperator() const
{ {
return _type != Type::Data && _type != Type::OpenBracket && _type != Type::CloseBracket; return mType != Type::Data && mType != Type::OpenBracket && mType != Type::CloseBracket;
} }
ExpressionParser::ExpressionParser(const String & expression) ExpressionParser::ExpressionParser(const String & expression)
: mExpression(fixClosingBrackets(expression)),
mIsValidExpression(true)
{ {
_tokens.clear(); tokenize();
_prefixTokens.clear();
tokenize(fixClosingBrackets(expression));
shuntingYard(); shuntingYard();
} }
String ExpressionParser::fixClosingBrackets(const String & expression) String ExpressionParser::fixClosingBrackets(const String & expression)
{ {
int open = 0; size_t open = 0;
int close = 0; size_t close = 0;
size_t len = expression.length(); auto len = expression.length();
for(size_t i = 0; i < len; i++) for(size_t i = 0; i < len; i++)
{ {
if(expression[i] == '(') if(expression[i] == '(')
@ -116,28 +116,28 @@ String ExpressionParser::fixClosingBrackets(const String & expression)
else if(expression[i] == ')') else if(expression[i] == ')')
close++; close++;
} }
String result = expression; auto result = expression;
if(close < open) if(close < open)
{ {
for(int i = 0; i < open - close; i++) for(size_t i = 0; i < open - close; i++)
result += ")"; result += ")";
} }
return result; return result;
} }
void ExpressionParser::tokenize(const String & expression) void ExpressionParser::tokenize()
{ {
auto stateMemory = 0; size_t stateMemory = 0;
size_t len = expression.length(); auto len = mExpression.length();
for(size_t i = 0; i < len; i++) for(size_t i = 0; i < len; i++)
{ {
char ch = expression[i]; auto ch = mExpression[i];
switch(ch) switch(ch)
{ {
case '[': case '[':
{ {
stateMemory++; stateMemory++;
_curToken += ch; mCurToken += ch;
} }
break; break;
@ -145,14 +145,14 @@ void ExpressionParser::tokenize(const String & expression)
{ {
if(stateMemory) if(stateMemory)
stateMemory--; stateMemory--;
_curToken += ch; mCurToken += ch;
} }
break; break;
default: default:
{ {
if(stateMemory) if(stateMemory)
_curToken += ch; mCurToken += ch;
else else
{ {
switch(ch) switch(ch)
@ -189,21 +189,24 @@ void ExpressionParser::tokenize(const String & expression)
addOperatorToken(ch, Token::Type::OperatorSub); addOperatorToken(ch, Token::Type::OperatorSub);
break; break;
case '=': case '=':
if(i + 1 < len && expression[i + 1] == '=') if(i + 1 < len && mExpression[i + 1] == '=')
{ {
addOperatorToken(ch, Token::Type::OperatorEqual); addOperatorToken(ch, Token::Type::OperatorEqual);
i++; i++;
} }
else else
{
addOperatorToken(ch, Token::Type::Error); addOperatorToken(ch, Token::Type::Error);
mIsValidExpression = false;
}
break; break;
case '<': case '<':
if(i + 1 < len && expression[i + 1] == '=') if(i + 1 < len && mExpression[i + 1] == '=')
{ {
addOperatorToken(ch, Token::Type::OperatorSmallerEqual); addOperatorToken(ch, Token::Type::OperatorSmallerEqual);
i++; i++;
} }
else if(i + 1 < len && expression[i + 1] == '<') else if(i + 1 < len && mExpression[i + 1] == '<')
{ {
addOperatorToken(ch, Token::Type::OperatorShl); addOperatorToken(ch, Token::Type::OperatorShl);
i++; i++;
@ -212,12 +215,12 @@ void ExpressionParser::tokenize(const String & expression)
addOperatorToken(ch, Token::Type::OperatorSmaller); addOperatorToken(ch, Token::Type::OperatorSmaller);
break; break;
case '>': case '>':
if(i + 1 < len && expression[i + 1] == '=') if(i + 1 < len && mExpression[i + 1] == '=')
{ {
addOperatorToken(ch, Token::Type::OperatorBiggerEqual); addOperatorToken(ch, Token::Type::OperatorBiggerEqual);
i++; i++;
} }
else if(i + 1 < len && expression[i + 1] == '>') else if(i + 1 < len && mExpression[i + 1] == '>')
{ {
addOperatorToken(ch, Token::Type::OperatorShr); addOperatorToken(ch, Token::Type::OperatorShr);
i++; i++;
@ -226,7 +229,7 @@ void ExpressionParser::tokenize(const String & expression)
addOperatorToken(ch, Token::Type::OperatorBigger); addOperatorToken(ch, Token::Type::OperatorBigger);
break; break;
case '&': case '&':
if(i + 1 < len && expression[i + 1] == '&') if(i + 1 < len && mExpression[i + 1] == '&')
{ {
addOperatorToken(ch, Token::Type::OperatorLogicalAnd); addOperatorToken(ch, Token::Type::OperatorLogicalAnd);
i++; i++;
@ -238,7 +241,7 @@ void ExpressionParser::tokenize(const String & expression)
addOperatorToken(ch, Token::Type::OperatorXor); addOperatorToken(ch, Token::Type::OperatorXor);
break; break;
case '|': case '|':
if(i + 1 < len && expression[i + 1] == '|') if(i + 1 < len && mExpression[i + 1] == '|')
{ {
addOperatorToken(ch, Token::Type::OperatorLogicalOr); addOperatorToken(ch, Token::Type::OperatorLogicalOr);
i++; i++;
@ -247,7 +250,7 @@ void ExpressionParser::tokenize(const String & expression)
addOperatorToken(ch, Token::Type::OperatorOr); addOperatorToken(ch, Token::Type::OperatorOr);
break; break;
case '!': case '!':
if(i + 1 < len && expression[i + 1] == '=') if(i + 1 < len && mExpression[i + 1] == '=')
{ {
addOperatorToken(ch, Token::Type::OperatorNotEqual); addOperatorToken(ch, Token::Type::OperatorNotEqual);
i++; i++;
@ -259,7 +262,7 @@ void ExpressionParser::tokenize(const String & expression)
case '\t': //ignore tabs case '\t': //ignore tabs
break; break;
default: default:
_curToken += ch; mCurToken += ch;
break; break;
} }
} }
@ -267,29 +270,29 @@ void ExpressionParser::tokenize(const String & expression)
break; break;
} }
} }
if(_curToken.length() != 0) //make sure the last token is added if(mCurToken.length() != 0) //make sure the last token is added
_tokens.push_back(Token(_curToken, Token::Type::Data)); mTokens.push_back(Token(mCurToken, Token::Type::Data));
} }
void ExpressionParser::addOperatorToken(const char ch, const Token::Type type) void ExpressionParser::addOperatorToken(const char ch, const Token::Type type)
{ {
if(_curToken.length()) //add a new data token when there is data in the buffer if(mCurToken.length()) //add a new data token when there is data in the buffer
{ {
_tokens.push_back(Token(_curToken, Token::Type::Data)); mTokens.push_back(Token(mCurToken, Token::Type::Data));
_curToken.clear(); mCurToken.clear();
} }
String data; String data;
data += ch; data += ch;
_tokens.push_back(Token(data, type)); //add the operator token mTokens.push_back(Token(data, type)); //add the operator token
} }
bool ExpressionParser::isUnaryOperator() bool ExpressionParser::isUnaryOperator() const
{ {
if(_curToken.length()) //data before the operator means it is no unary operator if(mCurToken.length()) //data before the operator means it is no unary operator
return false; return false;
if(!_tokens.size()) //no tokens before the operator means it is an unary operator if(!mTokens.size()) //no tokens before the operator means it is an unary operator
return true; return true;
Token lastToken = _tokens[_tokens.size() - 1]; auto lastToken = mTokens[mTokens.size() - 1];
return lastToken.isOperator(); //if the previous operator is a token, the operator is an unary operator return lastToken.isOperator(); //if the previous operator is a token, the operator is an unary operator
} }
@ -298,11 +301,11 @@ void ExpressionParser::shuntingYard()
//Implementation of Dijkstra's Shunting-yard algorithm //Implementation of Dijkstra's Shunting-yard algorithm
std::vector<Token> queue; std::vector<Token> queue;
std::stack<Token> stack; std::stack<Token> stack;
size_t len = _tokens.size(); auto len = mTokens.size();
//process the tokens //process the tokens
for(size_t i = 0; i < len; i++) for(size_t i = 0; i < len; i++)
{ {
Token & token = _tokens[i]; auto & token = mTokens[i];
switch(token.type()) switch(token.type())
{ {
case Token::Type::Data: case Token::Type::Data:
@ -314,9 +317,12 @@ void ExpressionParser::shuntingYard()
case Token::Type::CloseBracket: case Token::Type::CloseBracket:
while(true) while(true)
{ {
if(stack.empty()) //empty stack = bracket mismatch if(stack.empty()) //empty stack = bracket mismatch
{
mIsValidExpression = false;
return; return;
Token curToken = stack.top(); }
auto curToken = stack.top();
stack.pop(); stack.pop();
if(curToken.type() == Token::Type::OpenBracket) if(curToken.type() == Token::Type::OpenBracket)
break; break;
@ -324,10 +330,10 @@ void ExpressionParser::shuntingYard()
} }
break; break;
default: //operator default: //operator
Token & o1 = token; auto & o1 = token;
while(!stack.empty()) while(!stack.empty())
{ {
Token o2 = stack.top(); auto o2 = stack.top();
if(o2.isOperator() && if(o2.isOperator() &&
(o1.associativity() == Token::Associativity::LeftToRight && o1.precedence() >= o2.precedence()) || (o1.associativity() == Token::Associativity::LeftToRight && o1.precedence() >= o2.precedence()) ||
(o1.associativity() == Token::Associativity::RightToLeft && o1.precedence() > o2.precedence())) (o1.associativity() == Token::Associativity::RightToLeft && o1.precedence() > o2.precedence()))
@ -345,38 +351,41 @@ void ExpressionParser::shuntingYard()
//pop the remaining operators //pop the remaining operators
while(!stack.empty()) while(!stack.empty())
{ {
Token curToken = stack.top(); auto curToken = stack.top();
stack.pop(); stack.pop();
if(curToken.type() == Token::Type::OpenBracket || curToken.type() == Token::Type::CloseBracket) //brackets on the stack means invalid expression if(curToken.type() == Token::Type::OpenBracket || curToken.type() == Token::Type::CloseBracket) //brackets on the stack means invalid expression
{
mIsValidExpression = false;
return; return;
}
queue.push_back(curToken); queue.push_back(curToken);
} }
_prefixTokens = queue; mPrefixTokens = queue;
} }
#ifdef _WIN64 #ifdef _WIN64
#include <intrin.h> #include <intrin.h>
static inline unsigned long long umulhi(unsigned long long x, unsigned long long y) static unsigned long long umulhi(unsigned long long x, unsigned long long y)
{ {
unsigned __int64 res; unsigned __int64 res;
_umul128(x, y, &res); _umul128(x, y, &res);
return res; return res;
} }
static inline long long mulhi(long long x, long long y) static long long mulhi(long long x, long long y)
{ {
__int64 res; __int64 res;
_mul128(x, y, &res); _mul128(x, y, &res);
return res; return res;
} }
#else #else
static inline unsigned int umulhi(unsigned int x, unsigned int y) static unsigned int umulhi(unsigned int x, unsigned int y)
{ {
return (unsigned int)(((unsigned long long)x * y) >> 32); return (unsigned int)(((unsigned long long)x * y) >> 32);
} }
static inline int mulhi(int x, int y) static int mulhi(int x, int y)
{ {
return (int)(((long long)x * y) >> 32); return (int)(((long long)x * y) >> 32);
} }
@ -467,28 +476,28 @@ static bool operation(const ExpressionParser::Token::Type type, const T op1, con
return true; return true;
} }
bool ExpressionParser::unsignedoperation(const Token::Type type, const duint op1, const duint op2, duint & result) bool ExpressionParser::unsignedOperation(const Token::Type type, const duint op1, const duint op2, duint & result) const
{ {
return operation<duint>(type, op1, op2, result, false); return operation<duint>(type, op1, op2, result, false);
} }
bool ExpressionParser::signedoperation(const Token::Type type, const dsint op1, const dsint op2, duint & result) bool ExpressionParser::signedOperation(const Token::Type type, const dsint op1, const dsint op2, duint & result) const
{ {
dsint signedResult; dsint signedResult;
if(!operation<dsint>(type, op1, op2, signedResult, true)) if(!operation<dsint>(type, op1, op2, signedResult, true))
return false; return false;
result = (duint)signedResult; result = duint(signedResult);
return true; return true;
} }
bool ExpressionParser::calculate(duint & value, bool signedcalc, bool silent, bool baseonly, int* value_size, bool* isvar, bool* hexonly) bool ExpressionParser::Calculate(duint & value, bool signedcalc, bool silent, bool baseonly, int* value_size, bool* isvar, bool* hexonly) const
{ {
value = 0; value = 0;
if(!_prefixTokens.size()) if(!mPrefixTokens.size() || !mIsValidExpression)
return false; return false;
std::stack<duint> stack; std::stack<duint> stack;
//calculate the result from the RPN queue //calculate the result from the RPN queue
for(const auto & token : _prefixTokens) for(const auto & token : mPrefixTokens)
{ {
if(token.isOperator()) if(token.isOperator())
{ {
@ -505,9 +514,9 @@ bool ExpressionParser::calculate(duint & value, bool signedcalc, bool silent, bo
op1 = stack.top(); op1 = stack.top();
stack.pop(); stack.pop();
if(signedcalc) if(signedcalc)
signedoperation(token.type(), op1, op2, result); signedOperation(token.type(), op1, op2, result);
else else
unsignedoperation(token.type(), op1, op2, result); unsignedOperation(token.type(), op1, op2, result);
stack.push(result); stack.push(result);
break; break;
case Token::Type::OperatorMul: case Token::Type::OperatorMul:
@ -536,9 +545,9 @@ bool ExpressionParser::calculate(duint & value, bool signedcalc, bool silent, bo
op1 = stack.top(); op1 = stack.top();
stack.pop(); stack.pop();
if(signedcalc) if(signedcalc)
signedoperation(token.type(), op1, op2, result); signedOperation(token.type(), op1, op2, result);
else else
unsignedoperation(token.type(), op1, op2, result); unsignedOperation(token.type(), op1, op2, result);
stack.push(result); stack.push(result);
break; break;
case Token::Type::Error: case Token::Type::Error:
@ -554,7 +563,6 @@ bool ExpressionParser::calculate(duint & value, bool signedcalc, bool silent, bo
return false; return false;
stack.push(result); stack.push(result);
} }
} }
if(stack.empty()) //empty result stack means error if(stack.empty()) //empty result stack means error
return false; return false;

View File

@ -6,8 +6,18 @@
class ExpressionParser class ExpressionParser
{ {
public: public:
ExpressionParser(const String & expression); explicit ExpressionParser(const String & expression);
bool calculate(duint & value, bool signedcalc, bool silent, bool baseonly, int* value_size, bool* isvar, bool* hexonly); bool Calculate(duint & value, bool signedcalc, bool silent = true, bool baseonly = false, int* value_size = nullptr, bool* isvar = nullptr, bool* hexonly = nullptr) const;
const String & GetExpression() const
{
return mExpression;
}
bool IsValidExpression() const
{
return mIsValidExpression;
}
class Token class Token
{ {
@ -57,22 +67,24 @@ public:
bool isOperator() const; bool isOperator() const;
private: private:
String _data; String mData;
Type _type; Type mType;
}; };
private: private:
static String fixClosingBrackets(const String & expression); static String fixClosingBrackets(const String & expression);
bool isUnaryOperator(); bool isUnaryOperator() const;
void tokenize(const String & expression); void tokenize();
void shuntingYard(); void shuntingYard();
void addOperatorToken(const char ch, const Token::Type type); void addOperatorToken(const char ch, const Token::Type type);
bool unsignedoperation(const Token::Type type, const duint op1, const duint op2, duint & result); bool unsignedOperation(const Token::Type type, const duint op1, const duint op2, duint & result) const;
bool signedoperation(const Token::Type type, const dsint op1, const dsint op2, duint & result); bool signedOperation(const Token::Type type, const dsint op1, const dsint op2, duint & result) const;
std::vector<Token> _tokens; String mExpression;
std::vector<Token> _prefixTokens; bool mIsValidExpression;
String _curToken; std::vector<Token> mTokens;
std::vector<Token> mPrefixTokens;
String mCurToken;
}; };
#endif //_EXPRESSION_PARSER_H #endif //_EXPRESSION_PARSER_H

View File

@ -1702,7 +1702,7 @@ bool valfromstring(const char* string, duint* value, bool silent, bool baseonly,
} }
ExpressionParser parser(string); ExpressionParser parser(string);
duint result; duint result;
if(!parser.calculate(result, valuesignedcalc(), silent, baseonly, value_size, isvar, hexonly)) if(!parser.Calculate(result, valuesignedcalc(), silent, baseonly, value_size, isvar, hexonly))
return false; return false;
*value = result; *value = result;
return true; return true;

View File

@ -7,8 +7,8 @@
bool valuesignedcalc(); bool valuesignedcalc();
void valuesetsignedcalc(bool a); void valuesetsignedcalc(bool a);
bool valapifromstring(const char* name, duint* value, int* value_size, bool printall, bool silent, bool* hexonly); bool valapifromstring(const char* name, duint* value, int* value_size, bool printall, bool silent, bool* hexonly);
bool valfromstring_noexpr(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = 0, bool* isvar = 0, bool* hexonly = 0); bool valfromstring_noexpr(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = nullptr, bool* isvar = nullptr, bool* hexonly = nullptr);
bool valfromstring(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = 0, bool* isvar = 0, bool* hexonly = 0); bool valfromstring(const char* string, duint* value, bool silent = true, bool baseonly = false, int* value_size = nullptr, bool* isvar = nullptr, bool* hexonly = nullptr);
bool valflagfromstring(duint eflags, const char* string); bool valflagfromstring(duint eflags, const char* string);
bool valtostring(const char* string, duint value, bool silent); bool valtostring(const char* string, duint value, bool silent);
bool valmxcsrflagfromstring(duint mxcsrflags, const char* string); bool valmxcsrflagfromstring(duint mxcsrflags, const char* string);