Debugger: Expose parser evaluation

This commit is contained in:
Vicki Pfau 2017-12-29 00:02:20 -05:00
parent e192973bc5
commit c692006b9d
3 changed files with 91 additions and 82 deletions

View File

@ -10,8 +10,6 @@
CXX_GUARD_START
#include <mgba/debugger/debugger.h>
enum Operation {
OP_ASSIGN,
OP_ADD,
@ -62,6 +60,9 @@ void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv);
void lexFree(struct LexVector* lv);
void parseFree(struct ParseTree* tree);
struct mDebugger;
bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment);
CXX_GUARD_END
#endif

View File

@ -538,85 +538,6 @@ static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv
debugger->system->printStatus(debugger->system);
}
static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct CLIDebugVector* dv) {
switch (operation) {
case OP_ASSIGN:
current = next;
break;
case OP_ADD:
current += next;
break;
case OP_SUBTRACT:
current -= next;
break;
case OP_MULTIPLY:
current *= next;
break;
case OP_DIVIDE:
if (next != 0) {
current /= next;
} else {
dv->type = CLIDV_ERROR_TYPE;
return 0;
}
break;
case OP_AND:
current &= next;
break;
case OP_OR:
current |= next;
break;
case OP_XOR:
current ^= next;
break;
case OP_LESS:
current = current < next;
break;
case OP_GREATER:
current = current > next;
break;
case OP_EQUAL:
current = current == next;
break;
case OP_LE:
current = current <= next;
break;
case OP_GE:
current = current >= next;
break;
}
return current;
}
static void _evaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, struct CLIDebugVector* dv) {
int32_t lhs, rhs;
switch (tree->token.type) {
case TOKEN_UINT_TYPE:
dv->intValue = tree->token.uintValue;
break;
case TOKEN_SEGMENT_TYPE:
_evaluateParseTree(debugger, tree->lhs, dv);
dv->segmentValue = dv->intValue;
_evaluateParseTree(debugger, tree->rhs, dv);
break;
case TOKEN_OPERATOR_TYPE:
_evaluateParseTree(debugger, tree->lhs, dv);
lhs = dv->intValue;
_evaluateParseTree(debugger, tree->rhs, dv);
rhs = dv->intValue;
dv->intValue = _performOperation(tree->token.operatorValue, lhs, rhs, dv);
break;
case TOKEN_IDENTIFIER_TYPE:
if (mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, &dv->intValue, &dv->segmentValue)) {
break;
}
// Fall through
case TOKEN_ERROR_TYPE:
default:
dv->type = CLIDV_ERROR_TYPE;
}
}
struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length) {
if (!string || length < 1) {
return 0;
@ -636,7 +557,9 @@ struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* stri
if (tree.token.type == TOKEN_ERROR_TYPE) {
dvTemp.type = CLIDV_ERROR_TYPE;
} else {
_evaluateParseTree(&debugger->d, &tree, &dvTemp);
if (!mDebuggerEvaluateParseTree(&debugger->d, &tree, &dvTemp.intValue, &dvTemp.segmentValue)) {
dvTemp.type = CLIDV_ERROR_TYPE;
}
}
parseFree(tree.lhs);

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba/internal/debugger/parser.h>
#include <mgba/debugger/debugger.h>
#include <mgba-util/string.h>
enum LexState {
@ -509,3 +510,87 @@ void parseFree(struct ParseTree* tree) {
}
free(tree);
}
static bool _performOperation(enum Operation operation, int32_t current, int32_t next, int32_t* value) {
switch (operation) {
case OP_ASSIGN:
current = next;
break;
case OP_ADD:
current += next;
break;
case OP_SUBTRACT:
current -= next;
break;
case OP_MULTIPLY:
current *= next;
break;
case OP_DIVIDE:
if (next != 0) {
current /= next;
} else {
return false;
}
break;
case OP_AND:
current &= next;
break;
case OP_OR:
current |= next;
break;
case OP_XOR:
current ^= next;
break;
case OP_LESS:
current = current < next;
break;
case OP_GREATER:
current = current > next;
break;
case OP_EQUAL:
current = current == next;
break;
case OP_LE:
current = current <= next;
break;
case OP_GE:
current = current >= next;
break;
}
*value = current;
return true;
}
bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment) {
if (!value) {
return false;
}
int32_t lhs, rhs;
switch (tree->token.type) {
case TOKEN_UINT_TYPE:
if (segment) {
*segment = -1;
}
*value = tree->token.uintValue;
return true;
case TOKEN_SEGMENT_TYPE:
if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, value, segment)) {
return false;
}
return mDebuggerEvaluateParseTree(debugger, tree->lhs, segment, NULL);
case TOKEN_OPERATOR_TYPE:
if (!mDebuggerEvaluateParseTree(debugger, tree->lhs, &lhs, segment)) {
return false;
}
if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, &rhs, segment)) {
return false;
}
return _performOperation(tree->token.operatorValue, lhs, rhs, value);
case TOKEN_IDENTIFIER_TYPE:
return mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, value, segment);
case TOKEN_ERROR_TYPE:
default:
break;
}
return false;
}