Files
fz-lang/src/compiler/main.c
T
2026-10-10 02:40:53 +03:00

192 lines
3.8 KiB
C

#include <compiler/fzl_debug.h>
#include <compiler/fzl_parser.h>
#include <compiler/fzl_reader.h>
#include <compiler/fzl_walker.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Build arguments setup descriptor
typedef struct
{
char *filepath;
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->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
{
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)
return -1;
else if (args->help)
return 0;
if (args->verbose)
printf("> analyze\n-> reading file...");
char source[8192];
FILE *fd = fopen(args->filepath, "r");
if (!fd)
{
printf("Error: failed to open file '%s'\n", args->filepath);
return -1;
}
fseek(fd, 0L, SEEK_END);
size_t fsz = ftell(fd);
rewind(fd);
fread(source, fsz, 1, fd);
fclose(fd);
if (args->verbose)
{
printf("ok!\n");
printf("-> tokenizing...");
}
fzl_reader_t *rd = fzl_mkreader(source);
int result = fzl_read(rd);
if (result != 0)
{
printf("error: %s\n", fzl_reader_geterror());
return -1;
}
if (args->verbose)
printf("ok!\n");
fzl_reader_ll_t *entry = rd->first;
if (args->verbose)
{
printf("--> structure: ");
while (entry)
{
if (entry->token)
{
if (entry->token->store_value)
printf("<TOK:%d:%s>", entry->token->type,
(char *)entry->token->value);
else
printf("<TOK:%d>", entry->token->type);
}
entry = entry->next;
}
printf("\n");
printf("-> parsing...");
}
fzl_parser_t *parser = fzl_mkparser(rd->first);
result = fzl_parse(parser);
if (result != 0)
{
printf("Error: %s\n", fzl_parser_geterror());
return -1;
}
if (args->verbose)
{
printf("ok!\n");
fzl_debug_print_ast(parser->root);
printf("-> walking AST...");
}
fzl_walker_t *walker = fzl_mkwalker(parser->root);
result = fzl_walk(walker);
if (result != 0)
{
printf("Error: %s\n", fzl_walker_geterror());
return -1;
}
if (args->verbose)
{
printf("ok!\n");
printf("--> Constants table:\n");
for (size_t i = 0; i < walker->consts->size; i++)
printf("---> %s\n", walker->consts->array[i].as.string.chars);
printf("--> Ops:\n");
for (size_t i = 0; i < walker->op_count; i++)
printf("---> %lu\n", walker->ops[i]);
}
free(args);
fzl_freereader(rd);
fzl_freeparser(parser);
fzl_freeast(parser->root);
fzl_freewalker(walker);
printf("done.\n");
return 0;
}