lexer.h
This commit is contained in:
parent
bff63075d0
commit
f7b2817f55
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ all: lisp
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wextra
|
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
|
run: lisp
|
||||||
./lisp
|
./lisp
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 "enums.h"
|
||||||
|
#include "lexer.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "tokens.h"
|
#include "tokens.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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);
|
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 *
|
* Parser *
|
||||||
**********/
|
**********/
|
||||||
|
@ -84,189 +70,6 @@ void error(const char *msg)
|
||||||
exit(EXIT_FAILURE);
|
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 *
|
* Parser *
|
||||||
**********/
|
**********/
|
||||||
|
|
Loading…
Reference in New Issue