#include "../../Headers/slex_core.h" #include #include #include #include static void print_usage(const char* prog_name) { printf("Usage: %s [options] [options]\n\n", prog_name); printf("Options:\n"); printf(" -o Output file/output folder\n"); printf(" -l Specify target language: c, c#, csharp (default: detected or c)\n"); printf(" -h
Output header file (separates declarations and implementation for C)\n"); printf(" -ns Specify namespace (C# only. Default: SLexGenerated)\n"); printf(" -class Specify class name (C# only. Default: SLexer)\n"); printf(" -prefix Specify prefix for functions/methods\n"); printf(" -data_type Specify data type name of the segment\n"); } int main(int ac, char **av) { char* input_path = NULL; char* output_path = NULL; char* header_path = NULL; char* lang_str = NULL; char* ns_name = NULL; char* class_name = NULL; char* prefix = NULL; char* data_type_name = NULL; for (int i = 1; i < ac; i++) { if (av[i][0] == '-') { if (strcmp(av[i], "-o") == 0) { if (i + 1 < ac) output_path = av[++i]; else { fprintf(stderr, "Error: -o option requires an argument\n"); return 1; } } else if (strcmp(av[i], "-l") == 0) { if (i + 1 < ac) lang_str = av[++i]; else { fprintf(stderr, "Error: -l option requires an argument\n"); return 1; } } else if (strcmp(av[i], "-h") == 0) { if (i + 1 < ac) header_path = av[++i]; else { fprintf(stderr, "Error: -h option requires an argument\n"); return 1; } } else if (strcmp(av[i], "-ns") == 0) { if (i + 1 < ac) ns_name = av[++i]; else { fprintf(stderr, "Error: -ns option requires an argument\n"); return 1; } } else if (strcmp(av[i], "-class") == 0) { if (i + 1 < ac) class_name = av[++i]; else { fprintf(stderr, "Error: -class option requires an argument\n"); return 1; } } else if (strcmp(av[i], "-prefix") == 0) { if (i + 1 < ac) prefix = av[++i]; else { fprintf(stderr, "Error: -prefix option requires an argument\n"); return 1; } } else if (strcmp(av[i], "-data_type") == 0) { if (i + 1 < ac) data_type_name = av[++i]; else { fprintf(stderr, "Error: -data_type option requires an argument\n"); return 1; } } else { fprintf(stderr, "Error: Unknown option %s\n", av[i]); print_usage(av[0]); return 1; } } else { if (!input_path) { input_path = av[i]; } else { fprintf(stderr, "Error: Multiple input files are not supported: %s\n", av[i]); return 1; } } } if (!input_path) { fprintf(stderr, "Error: No input file specified\n"); print_usage(av[0]); return 1; } // Determine target language slex_target_language target_lang = c_language; bool lang_detected = false; if (lang_str) { char temp_lang[256]; int l_len = (int)strlen(lang_str); for (int k = 0; k < l_len && k < 255; k++) { temp_lang[k] = (char)tolower((unsigned char)lang_str[k]); } temp_lang[l_len] = '\0'; if (strcmp(temp_lang, "c") == 0) { target_lang = c_language; lang_detected = true; } else if (strcmp(temp_lang, "c#") == 0 || strcmp(temp_lang, "csharp") == 0) { target_lang = csharp; lang_detected = true; } else { fprintf(stderr, "Error: Unsupported language %s\n", lang_str); return 1; } } else if (output_path) { // Guess language from output path extension char* ext = strrchr(output_path, '.'); if (ext) { if (strcmp(ext, ".cs") == 0) { target_lang = csharp; lang_detected = true; } else if (strcmp(ext, ".c") == 0) { target_lang = c_language; lang_detected = true; } } } if (!lang_detected) { // Default to C if not specified and not detected target_lang = c_language; } // Initialize options with defaults slex_options options; memset(&options, 0, sizeof(options)); options.target_language = target_lang; options.header_output = header_path; if (target_lang == c_language) { options.prefix = prefix ? prefix : "slex_"; options.data_type_name = data_type_name ? data_type_name : "slex_segment"; } else { options.namespace_name = ns_name ? ns_name : "SLexGenerated"; options.class_name = class_name ? class_name : "SLexer"; options.prefix = prefix ? prefix : ""; options.data_type_name = data_type_name ? data_type_name : "Segment"; } // Load input rule file FILE* in_f = fopen(input_path, "r"); if (!in_f) { fprintf(stderr, "Error: Failed to open input file %s\n", input_path); return 1; } slex_rules rules; memset(&rules, 0, sizeof(rules)); if (!slex_read_rule_from_file(in_f, &rules)) { fprintf(stderr, "Error: Failed to parse rule file %s\n", input_path); fclose(in_f); return 1; } fclose(in_f); // Open output file FILE* out_f = stdout; if (output_path && strlen(output_path) > 0) { out_f = fopen(output_path, "w"); if (!out_f) { fprintf(stderr, "Error: Failed to open output file %s\n", output_path); return 1; } } // Perform translation bool success = slex_translate_to_file(&options, &rules, out_f); if (out_f != stdout) { fclose(out_f); } // Free parsed rule structures for (uint64_t i = 0; i < rules.rule_count; i++) { free(rules.rules[i].Tag); free(rules.rules[i].Pattern); } free(rules.rules); for (uint64_t i = 0; i < rules.mapping_count; i++) { free(rules.mappings[i].Id); free(rules.mappings[i].Tag); } free(rules.mappings); for (uint64_t i = 0; i < rules.code_block_count; i++) { if (rules.code_blocks[i].post_processor_code) free(rules.code_blocks[i].post_processor_code); if (rules.code_blocks[i].variables) free(rules.code_blocks[i].variables); } free(rules.code_blocks); if (!success) { fprintf(stderr, "Error: Code generation failed\n"); return 1; } printf("Success: Generated lexer source code\n"); return 0; }