1
0
Fork 0
lesson-lisp/lexer.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;
}
}