265 lines
7.0 KiB
C
265 lines
7.0 KiB
C
#include <stdio.h> // for now
|
|
#include "helper.h"
|
|
#include "error.h"
|
|
#include "types.h"
|
|
|
|
void tab(noom_uint_t amount) {
|
|
amount *= 2;
|
|
for (noom_uint_t i = 0; i < amount; i++) {
|
|
putchar(' ');
|
|
}
|
|
}
|
|
|
|
void print_node(const noomP_Node *node, noom_uint_t depth) {
|
|
tab(depth);
|
|
printf("{\n");
|
|
|
|
tab(depth + 1);
|
|
printf("type: %s\n", noomP_formatNodeType(node->type));
|
|
|
|
tab(depth + 1);
|
|
printf("location: %lld\n", node->source_offset);
|
|
|
|
tab(depth + 1);
|
|
printf("subnodes:\n");
|
|
|
|
for (noom_uint_t i = 0; i < node->subnodec; i++) {
|
|
print_node(node->subnodes[i], depth + 1);
|
|
}
|
|
|
|
tab(depth);
|
|
printf("}\n");
|
|
}
|
|
|
|
int the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(const char *code, const char *filename) {
|
|
noomP_Parser parser;
|
|
noomP_Node *program;
|
|
|
|
// goodbye "shitass" you will be missed
|
|
int success = noomP_parse(code, filename, NOOM_VERSION_54, &program, &parser);
|
|
if (success == 0) {
|
|
puts("LEX OUTPUT:");
|
|
fputs("\x1b[48;2;10;10;10m", stdout);
|
|
noom_uint_t pos = 0;
|
|
while (1) {
|
|
noomL_Token token;
|
|
|
|
noomL_ErrorType err = noomL_lex(code, pos, &token, NOOM_VERSION_54);
|
|
if (err) break;
|
|
|
|
if (token.type == NOOML_TOKEN_KEYWORD) {
|
|
fputs("\x1b[38;2;207;142;109m", stdout);
|
|
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
|
} else if (token.type == NOOML_TOKEN_WHITESPACE) {
|
|
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
|
} else if (token.type == NOOML_TOKEN_IDENTIFIER) {
|
|
fputs("\x1b[38;2;255;255;255m", stdout);
|
|
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
|
} else if (token.type == NOOML_TOKEN_SYMBOL) {
|
|
fputs("\x1b[38;2;0;255;255m", stdout);
|
|
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
|
} else if (token.type == NOOML_TOKEN_STRING) {
|
|
fputs("\x1b[38;2;255;0;0m", stdout);
|
|
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
|
} else if (token.type == NOOML_TOKEN_NUMBER) {
|
|
fputs("\x1b[38;2;0;255;0m", stdout);
|
|
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
|
} else {
|
|
fputs("\x1b[0m\n", stdout);
|
|
printf("%s ", noomL_formatTokenType(token.type));
|
|
for (noom_uint_t i = 0; i < token.length; i++) putchar((code + token.offset)[i]);
|
|
fputs("\x1b[48;2;10;10;10m", stdout);
|
|
putchar('\n');
|
|
}
|
|
|
|
pos += token.length;
|
|
|
|
if (token.type == NOOML_TOKEN_EOF) break;
|
|
}
|
|
puts("\x1b[0m");
|
|
puts("PARSE OUTPUT:");
|
|
print_node(program, 0);
|
|
}
|
|
else {
|
|
noom_uint_t bleh = noom_format_error(&parser, NULL, 0);
|
|
char* buf = noom_alloc(bleh);
|
|
noom_format_error(&parser, buf, bleh);
|
|
fputs(buf, stdout);
|
|
noom_free(buf);
|
|
}
|
|
|
|
// freeing time
|
|
noomP_Node *last_node = parser.last_node;
|
|
while (last_node) {
|
|
noomP_Node *next = last_node->previous_node;
|
|
// subnodes could be null if we OOM'd during a realloc of it
|
|
if (last_node->subnodes) noom_free(last_node->subnodes);
|
|
noom_free(last_node);
|
|
last_node = next;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
static char* read_file(const char* filename) {
|
|
FILE* file = fopen(filename, "r");
|
|
if (file == 0) {
|
|
fprintf(stderr, "Failed to open '%s'.\n", filename);
|
|
return 0;
|
|
}
|
|
|
|
fseek(file, 0, SEEK_END);
|
|
const unsigned long filesize = ftell(file);
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
char* buffer = noom_alloc(filesize + 1);
|
|
|
|
if (fread(buffer, 1, filesize, file) != filesize) {
|
|
fprintf(stderr, "Reached the end of the file\n");
|
|
return 0;
|
|
}
|
|
buffer[filesize] = '\0';
|
|
|
|
fclose(file);
|
|
return buffer;
|
|
}
|
|
|
|
static char* read_stdin() {
|
|
noom_uint_t capacity = 4096;
|
|
noom_uint_t size = 0;
|
|
char* buffer = noom_alloc(capacity);
|
|
|
|
size_t n;
|
|
while ((n = fread(buffer + size, 1, capacity - size, stdin)) > 0) {
|
|
size += n;
|
|
if (size == capacity) {
|
|
capacity *= 2;
|
|
buffer = noom_realloc(buffer, capacity);
|
|
}
|
|
}
|
|
|
|
buffer[size] = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
// code stolen from my different project
|
|
static int read_prompt(char* buf, int buf_size, char* prompt, const int required) {
|
|
do {
|
|
printf("%s", prompt);
|
|
if (!fgets(buf, buf_size, stdin)) return 1;
|
|
const size_t len = noom_strlen(buf);
|
|
if (len > 0 && buf[len - 1] != '\n') {
|
|
while (getchar() != '\n' && !feof(stdin)) ;
|
|
}
|
|
else if (len > 0) {
|
|
buf[len - 1] = '\0';
|
|
}
|
|
} while (buf[0] == '\0' && required);
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
const char *err = 0;
|
|
struct {
|
|
noom_bool_t enter_repl;
|
|
noom_bool_t use_stdin;
|
|
const char* script_exec;
|
|
const char* script_path;
|
|
noom_bool_t do_i_already_know_what_to_do;
|
|
} params = {0};
|
|
|
|
if (argc < 2) {
|
|
params.enter_repl = 1;
|
|
params.do_i_already_know_what_to_do = 1;
|
|
}
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
if (noom_strcmp(argv[i], "-") == 0) {
|
|
params.use_stdin = 1;
|
|
params.do_i_already_know_what_to_do = 1;
|
|
continue;
|
|
}
|
|
|
|
if (noom_strcmp(argv[i], "--") == 0) {
|
|
if (++i >= argc) break;
|
|
if (params.do_i_already_know_what_to_do) {
|
|
err = "too many arguments";
|
|
goto die;
|
|
}
|
|
params.script_exec = argv[i];
|
|
params.do_i_already_know_what_to_do = 1;
|
|
continue;
|
|
}
|
|
|
|
if (argv[i][0] != '-') {
|
|
if (params.do_i_already_know_what_to_do) {
|
|
err = "too many arguments";
|
|
goto die;
|
|
}
|
|
params.script_path = argv[i];
|
|
params.do_i_already_know_what_to_do = 1;
|
|
continue;
|
|
}
|
|
|
|
if (argv[i][1] == 'e') {
|
|
if (params.do_i_already_know_what_to_do) {
|
|
goto die;
|
|
}
|
|
/* "-estat" or "-e stat" */
|
|
if (argv[i][2] != '\0') {
|
|
params.script_exec = argv[i] + 2;
|
|
params.do_i_already_know_what_to_do = 1;
|
|
continue;
|
|
}
|
|
|
|
if (++i >= argc) {
|
|
err = "-e needs an argument";
|
|
goto die;
|
|
}
|
|
params.script_exec = argv[i];
|
|
params.do_i_already_know_what_to_do = 1;
|
|
}
|
|
|
|
if (argv[i][1] == 'v') {
|
|
puts(NOOM_VERSION_TEXT);
|
|
return 0;
|
|
}
|
|
|
|
err = "unknown option";
|
|
goto die;
|
|
}
|
|
if (!params.do_i_already_know_what_to_do) {
|
|
err = "script not set";
|
|
goto die;
|
|
}
|
|
if (params.script_exec || params.script_path) {
|
|
if (params.script_exec) {
|
|
return the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(params.script_exec, "(command line)");
|
|
}
|
|
char* code = read_file(params.script_path);
|
|
if (code == 0) return 1;
|
|
return the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(code, params.script_path);
|
|
}
|
|
if (params.use_stdin) {
|
|
char* code = read_stdin();
|
|
if (code == 0) return 1;
|
|
return the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(code, "stdin");
|
|
}
|
|
if (params.enter_repl) {
|
|
puts(NOOM_VERSION_TEXT);
|
|
for (;;) {
|
|
char code[4096];
|
|
if (read_prompt(code, sizeof(code), "> ", 1)) return 0;
|
|
the_theoretical_function_to_execute_your_code_that_should_be_replaced_later(code, "(noom input)");
|
|
}
|
|
}
|
|
die:
|
|
fprintf(stderr, "%s: %s\n"
|
|
"usage: %s [options] [script [args]]\n"
|
|
"Available options are:\n"
|
|
" - execute stdin\n"
|
|
" -e stat execute string 'stat'\n"
|
|
" -v show version\n",
|
|
argv[0], err, argv[0]);
|
|
return 1;
|
|
}
|