Debugger: Expose parser evaluation
Vicki Pfau vi@endrift.com
Fri, 29 Dec 2017 00:02:20 -0500
3 files changed,
91 insertions(+),
82 deletions(-)
M
include/mgba/internal/debugger/parser.h
→
include/mgba/internal/debugger/parser.h
@@ -10,8 +10,6 @@ #include <mgba-util/common.h>
CXX_GUARD_START -#include <mgba/debugger/debugger.h> - enum Operation { OP_ASSIGN, OP_ADD,@@ -61,6 +59,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
M
src/debugger/cli-debugger.c
→
src/debugger/cli-debugger.c
@@ -538,85 +538,6 @@ UNUSED(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 @@ parseLexedExpression(&tree, &lv);
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);
M
src/debugger/parser.c
→
src/debugger/parser.c
@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* 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 @@ free(tree->token.identifierValue);
} 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; +}