size_t lexExpression()

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;
}