mirror of https://github.com/mgba-emu/mgba.git
Debugger: Expose parser evaluation
This commit is contained in:
parent
e192973bc5
commit
c692006b9d
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue