#include "../../Headers/scc_core.h" #include #include #include 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] \n\n"); printf("Options:\n"); printf(" -o Output file\n"); printf(" -l Target language: c, c#, csharp (default: c)\n"); printf(" -h
Output header file (C only)\n"); printf(" -ns Specify namespace (C# only, default: SCCGenerated)\n"); printf(" -class Specify class name (C# only, default: SCC)\n"); printf(" -prefix Specify prefix for functions/types (default: scc_ for C, empty for C#)\n"); printf(" -data_type Specify syntax node data type name\n"); printf(" -slex-ns Specify namespace used in slex (default: SLexGenerated)\n"); printf(" -slex-class Specify class name used in slex (default: SLex)\n"); printf(" -slex-prefix Specify function prefix used in slex (default: slex_)\n"); printf(" -slex-data_type Specify segment data type used in slex (default: Segment)\n"); printf(" -slex-h
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 )\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; }