141 lines
3.2 KiB
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);
|
|
}
|