mirror of https://github.com/mgba-emu/mgba.git
Add parenthesis support
This commit is contained in:
parent
a58f8f8675
commit
4638e4a017
|
@ -336,6 +336,7 @@ static uint32_t _evaluateParseTree(struct ARMDebugger* debugger, struct ParseTre
|
|||
case TOKEN_IDENTIFIER_TYPE:
|
||||
return _lookupIdentifier(debugger, tree->token.identifierValue, dv);
|
||||
case TOKEN_ERROR_TYPE:
|
||||
default:
|
||||
dv->type = DV_ERROR_TYPE;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -25,6 +25,7 @@ static struct LexVector* _lexOperator(struct LexVector* lv, char operator) {
|
|||
lv = lvNext;
|
||||
lvNext = malloc(sizeof(struct LexVector));
|
||||
lvNext->next = lv->next;
|
||||
lvNext->token.type = TOKEN_ERROR_TYPE;
|
||||
lv->next = lvNext;
|
||||
return lvNext;
|
||||
}
|
||||
|
@ -39,6 +40,7 @@ size_t lexExpression(struct LexVector* lv, const char* string, size_t length) {
|
|||
|
||||
enum LexState state = LEX_ROOT;
|
||||
const char* tokenStart = 0;
|
||||
struct LexVector* lvNext;
|
||||
|
||||
while (length > 0 && string[0] && string[0] != ' ' && state != LEX_ERROR) {
|
||||
char token = string[0];
|
||||
|
@ -68,6 +70,15 @@ size_t lexExpression(struct LexVector* lv, const char* string, size_t length) {
|
|||
state = LEX_EXPECT_HEX;
|
||||
next = 0;
|
||||
break;
|
||||
case '(':
|
||||
state = LEX_ROOT;
|
||||
lv->token.type = TOKEN_OPEN_PAREN_TYPE;
|
||||
lvNext = malloc(sizeof(struct LexVector));
|
||||
lvNext->next = lv->next;
|
||||
lvNext->token.type = TOKEN_ERROR_TYPE;
|
||||
lv->next = lvNext;
|
||||
lv = lvNext;
|
||||
break;
|
||||
default:
|
||||
if (tolower(token) >= 'a' && tolower(token <= 'z')) {
|
||||
state = LEX_EXPECT_IDENTIFIER;
|
||||
|
@ -88,6 +99,11 @@ size_t lexExpression(struct LexVector* lv, const char* string, size_t length) {
|
|||
lv = _lexOperator(lv, token);
|
||||
state = LEX_ROOT;
|
||||
break;
|
||||
case ')':
|
||||
lv->token.type = TOKEN_IDENTIFIER_TYPE;
|
||||
lv->token.identifierValue = strndup(tokenStart, string - tokenStart - 1);
|
||||
state = LEX_EXPECT_OPERATOR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -117,6 +133,11 @@ size_t lexExpression(struct LexVector* lv, const char* string, size_t length) {
|
|||
lv = _lexOperator(lv, token);
|
||||
state = LEX_ROOT;
|
||||
break;
|
||||
case ')':
|
||||
lv->token.type = TOKEN_UINT_TYPE;
|
||||
lv->token.uintValue = next;
|
||||
state = LEX_EXPECT_OPERATOR;
|
||||
break;
|
||||
default:
|
||||
state = LEX_ERROR;
|
||||
}
|
||||
|
@ -166,6 +187,11 @@ size_t lexExpression(struct LexVector* lv, const char* string, size_t length) {
|
|||
lv = _lexOperator(lv, token);
|
||||
state = LEX_ROOT;
|
||||
break;
|
||||
case ')':
|
||||
lv->token.type = TOKEN_UINT_TYPE;
|
||||
lv->token.uintValue = next;
|
||||
state = LEX_EXPECT_OPERATOR;
|
||||
break;
|
||||
default:
|
||||
state = LEX_ERROR;
|
||||
break;
|
||||
|
@ -183,6 +209,23 @@ size_t lexExpression(struct LexVector* lv, const char* string, size_t length) {
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case LEX_EXPECT_OPERATOR:
|
||||
switch (token) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '*':
|
||||
case '/':
|
||||
lvNext = malloc(sizeof(struct LexVector));
|
||||
lvNext->next = lv->next;
|
||||
lvNext->token.type = TOKEN_CLOSE_PAREN_TYPE;
|
||||
lv->next = lvNext;
|
||||
lv = _lexOperator(lv->next, token);
|
||||
state = LEX_ROOT;
|
||||
break;
|
||||
default:
|
||||
state = LEX_ERROR;
|
||||
}
|
||||
break;
|
||||
case LEX_ERROR:
|
||||
// This shouldn't be reached
|
||||
break;
|
||||
|
@ -199,6 +242,12 @@ size_t lexExpression(struct LexVector* lv, const char* string, size_t length) {
|
|||
lv->token.type = TOKEN_IDENTIFIER_TYPE;
|
||||
lv->token.identifierValue = strndup(tokenStart, string - tokenStart);
|
||||
break;
|
||||
case LEX_EXPECT_OPERATOR:
|
||||
lvNext = malloc(sizeof(struct LexVector));
|
||||
lvNext->next = lv->next;
|
||||
lvNext->token.type = TOKEN_CLOSE_PAREN_TYPE;
|
||||
lv->next = lvNext;
|
||||
break;
|
||||
case LEX_ERROR:
|
||||
default:
|
||||
lv->token.type = TOKEN_ERROR_TYPE;
|
||||
|
@ -222,7 +271,7 @@ static struct ParseTree* _parseTreeCreate() {
|
|||
return tree;
|
||||
}
|
||||
|
||||
static struct LexVector* _parseExpression(struct ParseTree* tree, struct LexVector* lv, int precedence) {
|
||||
static struct LexVector* _parseExpression(struct ParseTree* tree, struct LexVector* lv, int precedence, int openParens) {
|
||||
struct ParseTree* newTree = 0;
|
||||
while (lv) {
|
||||
int newPrecedence;
|
||||
|
@ -237,6 +286,16 @@ static struct LexVector* _parseExpression(struct ParseTree* tree, struct LexVect
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
case TOKEN_OPEN_PAREN_TYPE:
|
||||
lv = _parseExpression(tree, lv->next, INT_MAX, openParens + 1);
|
||||
break;
|
||||
case TOKEN_CLOSE_PAREN_TYPE:
|
||||
if (openParens <= 0) {
|
||||
tree->token.type = TOKEN_ERROR_TYPE;
|
||||
return 0;
|
||||
}
|
||||
return lv->next;
|
||||
break;
|
||||
case TOKEN_OPERATOR_TYPE:
|
||||
newPrecedence = _operatorPrecedence[lv->token.operatorValue];
|
||||
if (newPrecedence < precedence) {
|
||||
|
@ -245,7 +304,7 @@ static struct LexVector* _parseExpression(struct ParseTree* tree, struct LexVect
|
|||
tree->lhs = newTree;
|
||||
tree->rhs = _parseTreeCreate();
|
||||
tree->token = lv->token;
|
||||
lv = _parseExpression(tree->rhs, lv->next, newPrecedence);
|
||||
lv = _parseExpression(tree->rhs, lv->next, newPrecedence, openParens);
|
||||
if (tree->token.type == TOKEN_ERROR_TYPE) {
|
||||
tree->token.type = TOKEN_ERROR_TYPE;
|
||||
}
|
||||
|
@ -271,7 +330,7 @@ void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv) {
|
|||
tree->lhs = 0;
|
||||
tree->rhs = 0;
|
||||
|
||||
_parseExpression(tree, lv, _operatorPrecedence[OP_ASSIGN]);
|
||||
_parseExpression(tree, lv, _operatorPrecedence[OP_ASSIGN], 0);
|
||||
}
|
||||
|
||||
void lexFree(struct LexVector* lv) {
|
||||
|
|
|
@ -11,6 +11,7 @@ enum LexState {
|
|||
LEX_EXPECT_DECIMAL,
|
||||
LEX_EXPECT_HEX,
|
||||
LEX_EXPECT_PREFIX,
|
||||
LEX_EXPECT_OPERATOR
|
||||
};
|
||||
|
||||
enum Operation {
|
||||
|
@ -27,6 +28,8 @@ struct Token {
|
|||
TOKEN_UINT_TYPE,
|
||||
TOKEN_IDENTIFIER_TYPE,
|
||||
TOKEN_OPERATOR_TYPE,
|
||||
TOKEN_OPEN_PAREN_TYPE,
|
||||
TOKEN_CLOSE_PAREN_TYPE,
|
||||
} type;
|
||||
union {
|
||||
uint32_t uintValue;
|
||||
|
|
Loading…
Reference in New Issue