#include #include #include #include "common.h" #include "darray.h" #include "string_view.c" #include "errors.c" #include "lexer.c" #include "nodes.c" #include "parser.c" #include "semantic.c" #include "viz.c" typedef enum ExecMode { RUN_NORMAL, PRINT_LEX, PRINT_PARSE, PRINT_SEMANTIC, PRINT_SYMTABLES, } ExecMode; static ExecMode mode = RUN_NORMAL; void init(void) { // STUB } void halt(void) { // STUB } void process_source(const StringView *source, const char *file_name) { // Read tokens. Token *tokens = tokenize(source); check_errors(file_name); if (mode == PRINT_LEX) { print_tokens(tokens); return; } // Parser. Root *roots = parse(tokens); check_errors(file_name); if (mode == PRINT_PARSE) { viz_ast(roots); return; } // Symbol table generation and type checking. ParseTree *parse_tree = semantic_analysis(roots); check_errors(file_name); if (mode == PRINT_SEMANTIC) { viz_ast(parse_tree->roots); return; } if (mode == PRINT_SYMTABLES) { viz_symtables(parse_tree->scopes); return; } } void run_file(char *file_name) { FILE *file = fopen(file_name, "r"); if (!file) { fprintf(stderr, "error: couldn't open input file: %s\n", file_name); exit(EXIT_FAILURE); } // Read entire file into memory. fseek(file, 0, SEEK_END); size_t file_size = ftell(file); fseek(file, 0, SEEK_SET); char *source = malloc(file_size + 1); fread(source, 1, file_size, file); source[file_size] = 0; StringView sv = (StringView){ .start = source, .n = file_size, }; process_source(&sv, file_name); free(source); fclose(file); } #define STDIN_BUF_CAP 16 void run_stdin(void) { size_t buf_size = 0; char *source = NULL; array_init(source, STDIN_BUF_CAP); char c; while ((c = getchar()) != EOF) { array_push(source, c); buf_size++; } StringView sv = (StringView){ .start = source, .n = buf_size, }; process_source(&sv, "stdin"); array_free(source); } #ifndef BIN_NAME #define BIN_NAME "bdl" #endif void print_usage(void) { printf("Usage: %s [options] \n", BIN_NAME); printf("\n"); printf("\t-h \t\tShow usage.\n"); printf("\t-p [l|p|s|t]\tPrint mode for [l]exing, [p]arsing, [s]emantic analysis, symbol [t]ables\n"); printf("\n"); } int main(int argc, char *argv[]) { init(); int option; while ((option = getopt(argc, argv, "hp:")) != -1) { switch (option) { case 'h': { print_usage(); goto exit_success; } break; case 'p': { if (optarg[0] == 'l' && optarg[1] == '\0') { mode = PRINT_LEX; } else if (optarg[0] == 'p' && optarg[1] == '\0') { mode = PRINT_PARSE; } else if (optarg[0] == 's' && optarg[1] == '\0') { mode = PRINT_SEMANTIC; } else if (optarg[0] == 't' && optarg[1] == '\0') { mode = PRINT_SYMTABLES; } else { print_usage(); return EXIT_FAILURE; } } break; default: { print_usage(); return EXIT_FAILURE; } break; } } // Run from stdin. if (optind == argc) { run_stdin(); goto exit_success; } // Run from file. while (optind < argc) { char *file_name = argv[optind]; run_file(file_name); optind++; } exit_success: halt(); return EXIT_SUCCESS; }