1
0
Fork 0
lesson-lisp/src/main.c

141 lines
3.2 KiB
C

#include "lexer.h"
#include "object.h"
#include "parser.h"
#include "syntax.h"
#include "tokens.h"
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void repl(struct Object *environment);
static void script(FILE *file, struct Object *environment);
int main(int argc, char **argv)
{
struct Object *const environment = Object_new_pair(NULL, NULL);
int index = 1;
for (; index < argc; ++index) {
if (strcmp(argv[index], "-r") == 0) {
++index;
assert(index < argc);
FILE *const file = fopen(argv[index], "r");
assert(file);
script(file, environment);
fclose(file);
} else {
break;
}
}
if (index < argc) {
for (; index < argc; ++index) {
FILE *const file = fopen(argv[index], "r");
assert(file);
script(file, environment);
fclose(file);
}
} else {
const bool is_tty = isatty(fileno(stdin));
if (is_tty) {
repl(environment);
} else {
script(stdin, environment);
}
}
exit(EXIT_SUCCESS);
}
void repl(struct Object *const environment)
{
printf("Lisp by Causa Arcana\n\n");
while (true) {
Tokens tokens = Tokens_new();
assert(tokens);
Lexer lexer = Lexer_new(tokens);
assert(lexer);
printf(">> ");
while (true) {
const char chr = getchar();
if (chr == EOF) {
putchar('\n');
exit(EXIT_SUCCESS);
}
if (chr == '\n') break;
Lexer_lex(lexer, chr);
}
Lexer_lex(lexer, '\n');
LEXER_DELETE(lexer);
if (Tokens_top(tokens) == NULL) continue;
struct Object *const program = parse(tokens);
TOKENS_DELETE(tokens);
struct Object *const result = syntax_repl(program, environment);
printf("=> ");
syntax_repl(
Object_build_list(
3,
Object_new_symbol("begin"),
Object_build_list(
2,
Object_new_symbol("display"),
Object_build_list(
2,
Object_new_symbol("quote"),
result
)
),
Object_build_list(
1,
Object_new_symbol("newline")
)
),
environment
);
}
}
void script(FILE *const file, struct Object *const environment)
{
Tokens tokens = Tokens_new();
assert(tokens);
Lexer lexer = Lexer_new(tokens);
assert(lexer);
while (true) {
const char chr = getc(file);
if (chr == EOF) break;
Lexer_lex(lexer, chr);
}
Lexer_lex(lexer, '\n');
LEXER_DELETE(lexer);
struct Object *program = NULL;
while (Tokens_top(tokens)) {
program = Object_new_pair(parse(tokens), program);
}
TOKENS_DELETE(tokens);
if (program == NULL) return;
syntax_script(program, environment);
}