Files
2026-05-26 19:21:36 +10:00

210 lines
7.9 KiB
C

#include "../../Headers/scc_core.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void print_usage() {
printf("SCC (Simple Compiler-Compiler) - Version 1.0\n");
printf("Translates grammar rule files to target language parser source code.\n\n");
printf("Usage: scc [options] <input_file>\n\n");
printf("Options:\n");
printf(" -o <output> Output file\n");
printf(" -l <language> Target language: c, c#, csharp (default: c)\n");
printf(" -h <header> Output header file (C only)\n");
printf(" -ns <namespace> Specify namespace (C# only, default: SCCGenerated)\n");
printf(" -class <class_name> Specify class name (C# only, default: SCC)\n");
printf(" -prefix <prefix> Specify prefix for functions/types (default: scc_ for C, empty for C#)\n");
printf(" -data_type <name> Specify syntax node data type name\n");
printf(" -slex-ns <ns> Specify namespace used in slex (default: SLexGenerated)\n");
printf(" -slex-class <class> Specify class name used in slex (default: SLex)\n");
printf(" -slex-prefix <prefix> Specify function prefix used in slex (default: slex_)\n");
printf(" -slex-data_type <type> Specify segment data type used in slex (default: Segment)\n");
printf(" -slex-h <header> Specify header file slex generated (C only, default: slex_generated.h)\n");
}
int main(int ac, char **av)
{
char* input_file = NULL;
char* output_file = NULL;
scc_options options;
options.target_language = c_language;
options.header_output = NULL;
options.namespace_name = NULL;
options.class_name = NULL;
options.prefix = NULL;
options.data_type_name = NULL;
options.slex_namespace_name = NULL;
options.slex_class_name = NULL;
options.slex_prefix = NULL;
options.slex_data_type_name = NULL;
options.slex_header = NULL;
for (int i = 1; i < ac; i++) {
if (strcmp(av[i], "-o") == 0) {
if (i + 1 < ac) {
output_file = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -o option\n");
return 1;
}
} else if (strcmp(av[i], "-l") == 0) {
if (i + 1 < ac) {
char* lang = av[++i];
if (strcmp(lang, "c") == 0) {
options.target_language = c_language;
} else if (strcmp(lang, "c#") == 0 || strcmp(lang, "csharp") == 0) {
options.target_language = csharp;
} else {
fprintf(stderr, "Error: Unsupported language '%s'\n", lang);
return 1;
}
} else {
fprintf(stderr, "Error: Missing value for -l option\n");
return 1;
}
} else if (strcmp(av[i], "-h") == 0) {
if (i + 1 < ac) {
options.header_output = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -h option\n");
return 1;
}
} else if (strcmp(av[i], "-ns") == 0) {
if (i + 1 < ac) {
options.namespace_name = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -ns option\n");
return 1;
}
} else if (strcmp(av[i], "-class") == 0) {
if (i + 1 < ac) {
options.class_name = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -class option\n");
return 1;
}
} else if (strcmp(av[i], "-prefix") == 0) {
if (i + 1 < ac) {
options.prefix = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -prefix option\n");
return 1;
}
} else if (strcmp(av[i], "-data_type") == 0) {
if (i + 1 < ac) {
options.data_type_name = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -data_type option\n");
return 1;
}
} else if (strcmp(av[i], "-slex-ns") == 0) {
if (i + 1 < ac) {
options.slex_namespace_name = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -slex-ns option\n");
return 1;
}
} else if (strcmp(av[i], "-slex-class") == 0) {
if (i + 1 < ac) {
options.slex_class_name = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -slex-class option\n");
return 1;
}
} else if (strcmp(av[i], "-slex-prefix") == 0) {
if (i + 1 < ac) {
options.slex_prefix = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -slex-prefix option\n");
return 1;
}
} else if (strcmp(av[i], "-slex-data_type") == 0) {
if (i + 1 < ac) {
options.slex_data_type_name = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -slex-data_type option\n");
return 1;
}
} else if (strcmp(av[i], "-slex-h") == 0) {
if (i + 1 < ac) {
options.slex_header = av[++i];
} else {
fprintf(stderr, "Error: Missing value for -slex-h option\n");
return 1;
}
} else if (av[i][0] == '-') {
fprintf(stderr, "Error: Unknown option '%s'\n", av[i]);
print_usage();
return 1;
} else {
if (input_file == NULL) {
input_file = av[i];
} else {
fprintf(stderr, "Error: Multiple input files specified ('%s' and '%s')\n", input_file, av[i]);
return 1;
}
}
}
if (!input_file) {
fprintf(stderr, "Error: Missing input file\n");
print_usage();
return 1;
}
if (!output_file) {
fprintf(stderr, "Error: Missing output file (-o <output>)\n");
print_usage();
return 1;
}
// Set C/C# defaults if not provided
if (options.target_language == c_language) {
if (!options.prefix) options.prefix = "scc_";
if (!options.data_type_name) options.data_type_name = "scc_syntax_node";
if (!options.slex_prefix) options.slex_prefix = "slex_";
if (!options.slex_data_type_name) options.slex_data_type_name = "slex_segment";
if (!options.slex_header) options.slex_header = "slex_generated.h";
} else {
if (!options.namespace_name) options.namespace_name = "SCCGenerated";
if (!options.class_name) options.class_name = "SCC";
if (!options.data_type_name) options.data_type_name = "SyntaxNode";
if (!options.slex_namespace_name) options.slex_namespace_name = "SLexGenerated";
if (!options.slex_class_name) options.slex_class_name = "SLex";
if (!options.slex_data_type_name) options.slex_data_type_name = "Segment";
if (!options.prefix) options.prefix = "";
}
FILE* f = fopen(input_file, "r");
if (!f) {
fprintf(stderr, "Error: Could not open input file '%s'\n", input_file);
return 1;
}
scc_rules rules;
if (!scc_read_rule_from_file(f, &rules)) {
fprintf(stderr, "Error: Failed to parse rules from input file '%s'\n", input_file);
fclose(f);
return 1;
}
fclose(f);
FILE* out = fopen(output_file, "w");
if (!out) {
fprintf(stderr, "Error: Could not open output file '%s'\n", output_file);
return 1;
}
bool success = scc_translate_to_file(&options, &rules, out);
fclose(out);
if (!success) {
fprintf(stderr, "Error: Parser translation failed\n");
remove(output_file);
return 1;
}
printf("Success: Generated parser written to '%s'\n", output_file);
return 0;
}