in cores/gba/src/debugger/parser.c [182:477]
size_t lexExpression(struct LexVector* lv, const char* string, size_t length, const char* eol) {
if (!string || length < 1) {
return 0;
}
uint32_t next = 0;
size_t adjusted = 0;
enum LexState state = LEX_ROOT;
const char* tokenStart = 0;
struct Token* lvNext;
if (!eol) {
eol = " \r\n";
}
while (length > 0 && string[0] && !strchr(eol, string[0]) && state != LEX_ERROR) {
char token = string[0];
++string;
++adjusted;
--length;
switch (state) {
case LEX_EXPECT_OPERATOR2:
switch (token) {
case '&':
case '|':
case '=':
case '<':
case '>':
_lexOperator(lv, token, &state);
break;
}
if (state != LEX_EXPECT_OPERATOR2) {
break;
}
// Fall through
case LEX_ROOT:
tokenStart = string - 1;
switch (token) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
state = LEX_EXPECT_DECIMAL;
next = token - '0';
break;
case '0':
state = LEX_EXPECT_PREFIX;
next = 0;
break;
case '$':
state = LEX_EXPECT_HEX_FIRST;
next = 0;
break;
case '%':
state = LEX_EXPECT_BINARY_FIRST;
next = 0;
break;
case '(':
state = LEX_ROOT;
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_OPEN_PAREN_TYPE;
break;
case ' ':
case '\t':
break;
default:
if (tolower(token) >= 'a' && tolower(token <= 'z')) {
state = LEX_EXPECT_IDENTIFIER;
} else {
state = LEX_ERROR;
}
break;
};
break;
case LEX_EXPECT_IDENTIFIER:
switch (token) {
case '=':
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case '<':
case '>':
case '!':
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_IDENTIFIER_TYPE;
lvNext->identifierValue = strndup(tokenStart, string - tokenStart - 1);
_lexOperator(lv, token, &state);
break;
case ')':
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_IDENTIFIER_TYPE;
lvNext->identifierValue = strndup(tokenStart, string - tokenStart - 1);
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_CLOSE_PAREN_TYPE;
state = LEX_EXPECT_OPERATOR;
break;
case ' ':
case '\t':
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_IDENTIFIER_TYPE;
lvNext->identifierValue = strndup(tokenStart, string - tokenStart - 1);
state = LEX_EXPECT_OPERATOR;
break;
default:
break;
}
break;
case LEX_EXPECT_BINARY_FIRST:
state = LEX_EXPECT_BINARY;
// Fall through
case LEX_EXPECT_BINARY:
switch (token) {
case '0':
case '1':
// TODO: handle overflow
next <<= 1;
next += token - '0';
break;
default:
_lexValue(lv, token, next, &state);
break;
}
break;
case LEX_EXPECT_DECIMAL:
switch (token) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// TODO: handle overflow
next *= 10;
next += token - '0';
break;
default:
_lexValue(lv, token, next, &state);
break;
}
break;
case LEX_EXPECT_HEX_FIRST:
state = LEX_EXPECT_HEX;
// Fall through
case LEX_EXPECT_HEX:
switch (token) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// TODO: handle overflow
next *= 16;
next += token - '0';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
// TODO: handle overflow
next *= 16;
next += token - 'A' + 10;
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
// TODO: handle overflow
next *= 16;
next += token - 'a' + 10;
break;
case ':':
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_SEGMENT_TYPE;
lvNext->uintValue = next;
next = 0;
break;
default:
_lexValue(lv, token, next, &state);
break;
}
break;
case LEX_EXPECT_PREFIX:
switch (token) {
case 'X':
case 'x':
next = 0;
state = LEX_EXPECT_HEX_FIRST;
break;
case 'B':
case 'b':
next = 0;
state = LEX_EXPECT_BINARY_FIRST;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
next = token - '0';
state = LEX_EXPECT_DECIMAL;
break;
default:
_lexValue(lv, token, next, &state);
break;
}
break;
case LEX_EXPECT_OPERATOR:
switch (token) {
case '=':
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case '<':
case '>':
case '!':
_lexOperator(lv, token, &state);
break;
case ')':
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_CLOSE_PAREN_TYPE;
break;
case ' ':
case '\t':
break;
default:
state = LEX_ERROR;
}
break;
case LEX_ERROR:
// This shouldn't be reached
break;
}
}
switch (state) {
case LEX_EXPECT_BINARY:
case LEX_EXPECT_DECIMAL:
case LEX_EXPECT_HEX:
case LEX_EXPECT_PREFIX:
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_UINT_TYPE;
lvNext->uintValue = next;
break;
case LEX_EXPECT_IDENTIFIER:
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_IDENTIFIER_TYPE;
lvNext->identifierValue = strndup(tokenStart, string - tokenStart);
break;
case LEX_ROOT:
case LEX_EXPECT_OPERATOR:
case LEX_EXPECT_OPERATOR2:
break;
case LEX_EXPECT_BINARY_FIRST:
case LEX_EXPECT_HEX_FIRST:
case LEX_ERROR:
default:
lvNext = LexVectorAppend(lv);
lvNext->type = TOKEN_ERROR_TYPE;
break;
}
return adjusted;
}