196 lines
5.1 KiB
C
196 lines
5.1 KiB
C
#include "lexer.h"
|
|
|
|
#include "enums.h"
|
|
#include "tokens.h"
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
static char buffer[1024];
|
|
static size_t buffer_index = 0;
|
|
static enum State state = STATE_INIT;
|
|
|
|
static void buffer_add(char chr);
|
|
static void buffer_clean();
|
|
static void token_add(enum State state, char *val);
|
|
|
|
void buffer_add(char chr)
|
|
{
|
|
assert(buffer_index < 1000);
|
|
buffer[buffer_index++] = chr;
|
|
buffer[buffer_index] = 0;
|
|
}
|
|
|
|
void buffer_clean()
|
|
{
|
|
buffer_index = 0;
|
|
}
|
|
|
|
void token_add(enum State state, char *val)
|
|
{
|
|
if (state == STATE_WHITESPACE) return;
|
|
|
|
enum TokenType token_type;
|
|
assert(State_to_token_type(state, &token_type));
|
|
|
|
tokens_push(token_type, val);
|
|
}
|
|
|
|
void lex(const char chr)
|
|
{
|
|
switch (state) {
|
|
case STATE_INIT:
|
|
if (chr == '(') {
|
|
state = STATE_OPEN;
|
|
buffer_add(chr);
|
|
} else if (chr == ')') {
|
|
state = STATE_CLOSE;
|
|
buffer_add(chr);
|
|
} else if (isspace(chr)) {
|
|
state = STATE_WHITESPACE;
|
|
buffer_add(chr);
|
|
} else if (isalpha(chr)) {
|
|
state = STATE_ATOM;
|
|
buffer_add(chr);
|
|
} else if (isdigit(chr)) {
|
|
state = STATE_NUM;
|
|
buffer_add(chr);
|
|
} else {
|
|
abort();
|
|
}
|
|
break;
|
|
case STATE_WHITESPACE:
|
|
if (chr == '(') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_OPEN;
|
|
buffer_add(chr);
|
|
} else if (chr == ')') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_CLOSE;
|
|
buffer_add(chr);
|
|
} else if (isspace(chr)) {
|
|
buffer_add(chr);
|
|
} else if (isalpha(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_ATOM;
|
|
buffer[buffer_index++] = chr;
|
|
} else if (isdigit(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_NUM;
|
|
buffer[buffer_index++] = chr;
|
|
} else {
|
|
abort();
|
|
}
|
|
break;
|
|
case STATE_OPEN:
|
|
if (chr == '(') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_OPEN;
|
|
buffer_add(chr);
|
|
} else if (chr == ')') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_CLOSE;
|
|
buffer_add(chr);
|
|
} else if (isspace(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_WHITESPACE;
|
|
buffer_add(chr);
|
|
} else if (isalpha(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_ATOM;
|
|
buffer_add(chr);
|
|
} else if (isdigit(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_NUM;
|
|
buffer_add(chr);
|
|
} else {
|
|
abort();
|
|
}
|
|
break;
|
|
case STATE_CLOSE:
|
|
if (chr == '(') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_OPEN;
|
|
buffer_add(chr);
|
|
} else if (chr == ')') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_CLOSE;
|
|
buffer_add(chr);
|
|
} else if (isspace(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_WHITESPACE;
|
|
buffer_add(chr);
|
|
} else if (isalpha(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_ATOM;
|
|
buffer_add(chr);
|
|
} else if (isdigit(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_NUM;
|
|
buffer_add(chr);
|
|
} else {
|
|
abort();
|
|
}
|
|
break;
|
|
case STATE_ATOM:
|
|
if (chr == '(') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_OPEN;
|
|
buffer_add(chr);
|
|
} else if (chr == ')') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_CLOSE;
|
|
buffer_add(chr);
|
|
} else if (isspace(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_WHITESPACE;
|
|
buffer_add(chr);
|
|
} else if (isalnum(chr)) {
|
|
buffer_add(chr);
|
|
} else {
|
|
abort();
|
|
}
|
|
break;
|
|
case STATE_NUM:
|
|
if (chr == '(') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_OPEN;
|
|
buffer_add(chr);
|
|
} else if (chr == ')') {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_CLOSE;
|
|
buffer_add(chr);
|
|
} else if (isspace(chr)) {
|
|
token_add(state, buffer);
|
|
buffer_clean();
|
|
state = STATE_WHITESPACE;
|
|
buffer_add(chr);
|
|
} else if (isdigit(chr)) {
|
|
buffer_add(chr);
|
|
} else {
|
|
abort();
|
|
}
|
|
break;
|
|
}
|
|
}
|