feat: enhance compiler
- Add comments and test for it - Add semicolon as required end of some expressions - Add new arguments parser - Add multi-file compilation - Add colors in output
This commit is contained in:
+60
-138
@@ -1,147 +1,69 @@
|
||||
#include <common/fzl_colors.h>
|
||||
#include <compiler/fzl_debug.h>
|
||||
#include <compiler/fzl_parser.h>
|
||||
#include <compiler/fzl_reader.h>
|
||||
#include <compiler/fzl_walker.h>
|
||||
#include <compiler/fzl_writer.h>
|
||||
#include <compiler/utils/fzl_linked.h>
|
||||
#include <compiler/utils/fzl_options.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Build arguments setup descriptor
|
||||
typedef struct
|
||||
{
|
||||
char *filepath;
|
||||
char *outpath;
|
||||
bool verbose;
|
||||
bool help;
|
||||
} build_args_t;
|
||||
|
||||
// Print command usage hint
|
||||
void print_usage()
|
||||
{
|
||||
printf("Usage: fzc [flags] <file path>\n");
|
||||
printf("Flags:\n");
|
||||
printf("\t-v\t--verbose\tdisplay debug information\n");
|
||||
printf("\t-h\t--help\t\tprint usage hint (which you're looking at)\n");
|
||||
}
|
||||
|
||||
// Read the arguments and build `build_args_t` struct
|
||||
build_args_t *getargs(int argc, char **argv)
|
||||
{
|
||||
build_args_t *args = malloc(sizeof(build_args_t));
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
args->filepath = NULL;
|
||||
args->outpath = NULL;
|
||||
args->verbose = false;
|
||||
args->help = false;
|
||||
|
||||
size_t args_total = 0;
|
||||
if (argc > 2)
|
||||
{
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] != '-')
|
||||
continue;
|
||||
|
||||
args_total++;
|
||||
|
||||
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
|
||||
{
|
||||
args->help = true;
|
||||
}
|
||||
else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
|
||||
{
|
||||
args->verbose = true;
|
||||
}
|
||||
else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--out") == 0)
|
||||
{
|
||||
if (!argv[i + 1] || argv[i + 1][0] == '-')
|
||||
{
|
||||
printf("Error: file path is not specified.\n");
|
||||
return NULL;
|
||||
}
|
||||
args->outpath = argv[++i];
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: unknown argument '%s'\n", argv[i]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - 1 - args_total < 1)
|
||||
{
|
||||
printf("Error: source code file is not specified.\n");
|
||||
print_usage();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (argv[argc - 1][0] == '-')
|
||||
{
|
||||
printf("Error: last argument MUST be a path to file.\n");
|
||||
printf("Write 'fzc --help' to read help\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
args->filepath = argv[argc - 1];
|
||||
return args;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
build_args_t *args = getargs(argc, argv);
|
||||
if (args == NULL)
|
||||
fzl_options_t *opts = fzl_mkoptions(argc, argv);
|
||||
if (!opts)
|
||||
return -1;
|
||||
else if (args->help)
|
||||
else if (!opts->should_continue)
|
||||
return 0;
|
||||
|
||||
if (args->verbose)
|
||||
printf("> analyze\n-> reading file...");
|
||||
if (opts->verbose)
|
||||
printf("%s> analyze\n-> reading file...%s", FZL_CDEBUG, FZL_CRST);
|
||||
|
||||
char *source;
|
||||
FILE *fd = fopen(args->filepath, "r");
|
||||
if (!fd)
|
||||
fzl_linked_t *linked = fzl_mklinked();
|
||||
if (!linked)
|
||||
{
|
||||
printf("Error: failed to open file '%s'\n", args->filepath);
|
||||
char *lasterr = fzl_linked_geterror();
|
||||
if (lasterr[0])
|
||||
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, lasterr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(fd, 0L, SEEK_END);
|
||||
size_t fsz = ftell(fd);
|
||||
rewind(fd);
|
||||
|
||||
source = malloc(fsz + 1);
|
||||
fread(source, fsz, 1, fd);
|
||||
fclose(fd);
|
||||
source[fsz] = '\0';
|
||||
|
||||
if (args->verbose)
|
||||
bool read_result =
|
||||
fzl_linked_add_files(linked, opts->files, opts->files_count);
|
||||
if (!read_result)
|
||||
{
|
||||
printf("ok!\n");
|
||||
printf("--> Red %ld bytes\n", fsz);
|
||||
printf("-> tokenizing...");
|
||||
char *lasterr = fzl_linked_geterror();
|
||||
if (lasterr[0])
|
||||
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, lasterr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fzl_reader_t *rd = fzl_mkreader(source);
|
||||
int result = fzl_read(rd);
|
||||
if (opts->verbose)
|
||||
{
|
||||
printf("%sok%s!\n", FZL_COK, FZL_CRST);
|
||||
printf("%s--> Red %ld bytes%s\n", FZL_CDEBUG, linked->total_sz, FZL_CRST);
|
||||
printf("%s-> tokenizing...%s", FZL_CDEBUG, FZL_CRST);
|
||||
}
|
||||
|
||||
fzl_reader_t *rd = fzl_mkreader(linked);
|
||||
int result = fzl_read(rd);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("error: %s\n", fzl_reader_geterror());
|
||||
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_reader_geterror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args->verbose)
|
||||
printf("ok!\n");
|
||||
if (opts->verbose)
|
||||
printf("%sok%s!\n", FZL_COK, FZL_CRST);
|
||||
|
||||
fzl_reader_ll_t *entry = rd->first;
|
||||
|
||||
if (args->verbose)
|
||||
if (opts->verbose)
|
||||
{
|
||||
printf("--> structure: ");
|
||||
printf("%s--> structure: %s", FZL_CDEBUG, FZL_CRST);
|
||||
while (entry)
|
||||
{
|
||||
if (entry->token)
|
||||
@@ -157,42 +79,42 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("-> parsing...");
|
||||
printf("%s-> parsing...%s", FZL_CDEBUG, FZL_CRST);
|
||||
}
|
||||
|
||||
fzl_parser_t *parser = fzl_mkparser(rd->first);
|
||||
result = fzl_parse(parser);
|
||||
result = fzl_parse(parser);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("Error: %s\n", fzl_parser_geterror());
|
||||
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_parser_geterror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args->verbose)
|
||||
if (opts->verbose)
|
||||
{
|
||||
printf("ok!\n");
|
||||
printf("%sok%s!\n", FZL_COK, FZL_CRST);
|
||||
fzl_debug_print_ast(parser->root);
|
||||
printf("> building\n");
|
||||
printf("-> walking AST...\n");
|
||||
printf("%s> building%s\n", FZL_CDEBUG, FZL_CRST);
|
||||
printf("%s-> walking AST...%s\n", FZL_CDEBUG, FZL_CRST);
|
||||
}
|
||||
|
||||
fzl_walker_t *walker = fzl_mkwalker(parser->root);
|
||||
result = fzl_walk(walker);
|
||||
result = fzl_walk(walker);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("Error: %s\n", fzl_walker_geterror());
|
||||
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_walker_geterror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args->verbose)
|
||||
if (opts->verbose)
|
||||
{
|
||||
printf("ok!\n");
|
||||
printf("%sok%s!\n", FZL_COK, FZL_CRST);
|
||||
|
||||
printf("--> Constants table:\n");
|
||||
printf("%s--> Constants table%s:\n", FZL_CDEBUG, FZL_CRST);
|
||||
for (size_t i = 0; i < walker->consts->size; i++)
|
||||
printf("---> %s\n", walker->consts->array[i].as.string.chars);
|
||||
|
||||
printf("--> Ops:\n");
|
||||
printf("%s--> Ops%s:\n", FZL_CDEBUG, FZL_CRST);
|
||||
printf("---> ");
|
||||
for (size_t i = 0; i < walker->op_count; i++)
|
||||
{
|
||||
@@ -202,40 +124,40 @@ int main(int argc, char **argv)
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("-> preparing final write\n");
|
||||
printf("%s-> preparing final write%s\n", FZL_CDEBUG, FZL_CRST);
|
||||
}
|
||||
|
||||
char outpath[256];
|
||||
if (args->outpath)
|
||||
strcpy(outpath, args->outpath);
|
||||
if (opts->outname)
|
||||
strcpy(outpath, opts->outname);
|
||||
else
|
||||
strcpy(outpath, "a.fzb");
|
||||
|
||||
if (args->verbose)
|
||||
if (opts->verbose)
|
||||
{
|
||||
printf("-> output file path is: %s\n", outpath);
|
||||
printf("-> writing file...");
|
||||
printf("%s-> output file path is%s: %s\n", FZL_CDEBUG, FZL_CRST, outpath);
|
||||
printf("%s-> writing file...%s", FZL_CDEBUG, FZL_CRST);
|
||||
}
|
||||
|
||||
fzl_writer_t *writer = fzl_mkwriter(outpath);
|
||||
result = fzl_write(writer, walker);
|
||||
result = fzl_write(writer, walker);
|
||||
if (result != 0)
|
||||
{
|
||||
printf("Error: %s\n", fzl_writer_geterror());
|
||||
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_writer_geterror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (args->verbose)
|
||||
printf("ok!\n");
|
||||
if (opts->verbose)
|
||||
printf("%sok%s!\n", FZL_COK, FZL_CRST);
|
||||
|
||||
free(source);
|
||||
free(args);
|
||||
fzl_freeoptions(opts);
|
||||
fzl_freelinked(linked);
|
||||
fzl_freereader(rd);
|
||||
fzl_freeast(parser->root);
|
||||
fzl_freeparser(parser);
|
||||
fzl_freewalker(walker);
|
||||
fzl_freewriter(writer);
|
||||
|
||||
printf("done.\n");
|
||||
printf("%sCompiled successfully%s.\n", FZL_COK, FZL_CRST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user