lexer.h
This commit is contained in:
parent
bff63075d0
commit
f7b2817f55
4 changed files with 203 additions and 199 deletions
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ all: lisp
|
|||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra
|
||||
|
||||
OBJS = enums.c.o main.c.o object.c.o tokens.c.o
|
||||
OBJS = enums.c.o lexer.c.o main.c.o object.c.o tokens.c.o
|
||||
|
||||
run: lisp
|
||||
./lisp
|
||||
|
|
195
lexer.c
Normal file
195
lexer.c
Normal file
|
@ -0,0 +1,195 @@
|
|||
#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;
|
||||
}
|
||||
}
|
6
lexer.h
Normal file
6
lexer.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef __LEXER_H__
|
||||
#define __LEXER_H__
|
||||
|
||||
void lex(char chr);
|
||||
|
||||
#endif
|
199
main.c
199
main.c
|
@ -1,30 +1,16 @@
|
|||
#include "enums.h"
|
||||
#include "lexer.h"
|
||||
#include "object.h"
|
||||
#include "tokens.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char buffer[1024];
|
||||
static size_t buffer_index = 0;
|
||||
|
||||
static enum State state = STATE_INIT;
|
||||
|
||||
static void error(const char *msg);
|
||||
|
||||
/*********
|
||||
* Lexer *
|
||||
*********/
|
||||
|
||||
static void buffer_add(char chr);
|
||||
static void buffer_clean();
|
||||
static void token_add(enum State state, char *val);
|
||||
static void lex(char chr);
|
||||
|
||||
/**********
|
||||
* Parser *
|
||||
**********/
|
||||
|
@ -84,189 +70,6 @@ void error(const char *msg)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*********
|
||||
* Lexer *
|
||||
*********/
|
||||
|
||||
void buffer_add(char chr)
|
||||
{
|
||||
if (buffer_index >= 1000) error("token too long");
|
||||
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;
|
||||
if (!State_to_token_type(state, &token_type)) error("invalid state");
|
||||
|
||||
tokens_push(token_type, val);
|
||||
}
|
||||
|
||||
void lex(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 {
|
||||
error("invalid char (STATE_INIT)");
|
||||
}
|
||||
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 {
|
||||
error("invalid char (STATE_WHITESPACE)");
|
||||
}
|
||||
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 {
|
||||
error("invalid char (STATE_OPEN)");
|
||||
}
|
||||
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 {
|
||||
error("invalid char (STATE_CLOSE)");
|
||||
}
|
||||
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 {
|
||||
error("invalid char (STATE_ATOM)");
|
||||
}
|
||||
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 {
|
||||
error("invalid char (STATE_NUM)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**********
|
||||
* Parser *
|
||||
**********/
|
||||
|
|
Loading…
Reference in a new issue