Finished the implemenation with Antigravity.

This commit is contained in:
Creeper Lv
2026-05-26 04:45:32 +10:00
parent 7d974680a6
commit 2950db1efb
10 changed files with 1760 additions and 5 deletions
+315 -2
View File
@@ -1,7 +1,320 @@
#include "../../../Headers/slex_core.h"
#include "../../../Headers/slex_regex.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Helper to check if a tag is mapped to an ID, and return it.
static const char* get_mapped_id(slex_rules* rules, const char* tag) {
for (uint64_t i = 0; i < rules->mapping_count; i++) {
if (strcmp(rules->mappings[i].Tag, tag) == 0) {
return rules->mappings[i].Id;
}
}
return NULL;
}
static void generate_declarations(FILE* f, slex_options* options, slex_rules* rules) {
char* prefix = options->prefix ? options->prefix : "slex_";
char* data_type = options->data_type_name ? options->data_type_name : "slex_segment";
fprintf(f, "#include <stdint.h>\n");
fprintf(f, "#include <stdio.h>\n\n");
// slex_segment_tag enum
fprintf(f, "typedef enum %ssegment_tag {\n", prefix);
for (uint64_t i = 0; i < rules->rule_count; i++) {
fprintf(f, " %stag_%s,\n", prefix, rules->rules[i].Tag);
}
fprintf(f, "} %ssegment_tag;\n\n", prefix);
// slex_segment_id enum
fprintf(f, "typedef enum %ssegment_id {\n", prefix);
fprintf(f, " %sid_default = 0,\n", prefix);
// Find all unique mapping Ids
for (uint64_t i = 0; i < rules->mapping_count; i++) {
// Only print if not already printed (unique check)
bool unique = true;
for (uint64_t j = 0; j < i; j++) {
if (strcmp(rules->mappings[j].Id, rules->mappings[i].Id) == 0) {
unique = false;
break;
}
}
if (unique) {
fprintf(f, " %sid_%s,\n", prefix, rules->mappings[i].Id);
}
}
fprintf(f, "} %ssegment_id;\n\n", prefix);
// slex_segment struct
fprintf(f, "typedef struct %s {\n", data_type);
fprintf(f, " char* head;\n");
fprintf(f, " int64_t length;\n");
fprintf(f, " char* file_name;\n");
fprintf(f, " int64_t line;\n");
fprintf(f, " int64_t col;\n");
fprintf(f, " %ssegment_tag tag;\n", prefix);
fprintf(f, " %ssegment_id id;\n", prefix);
fprintf(f, " struct %s* prev;\n", data_type);
fprintf(f, " struct %s* next;\n", data_type);
fprintf(f, "} %s;\n\n", data_type);
// post_process_result enum
fprintf(f, "typedef enum %spost_process_result {\n", prefix);
fprintf(f, " %scontinue,\n", prefix);
fprintf(f, " %sskip,\n", prefix);
fprintf(f, " %scontinue_with_output,\n", prefix);
fprintf(f, "} %spost_process_result;\n\n", prefix);
// Function declarations
fprintf(f, "%spost_process_result %spost_process(%s* input, %s** output);\n", prefix, prefix, data_type, data_type);
fprintf(f, "char %sfile(FILE* f, char* file_name, %s** head);\n", prefix, data_type);
fprintf(f, "char %scstr(char* input, char* file_name, %s** head);\n", prefix, data_type);
fprintf(f, "char %sfree(%s* head);\n\n", prefix, data_type);
}
bool slex_translate_to_file_c(slex_options *options, slex_rules *rules, FILE *output_file)
{
// TODO: Stub for moment.
return false;
if (!options || !rules || !output_file) return false;
char* prefix = options->prefix ? options->prefix : "slex_";
char* data_type = options->data_type_name ? options->data_type_name : "slex_segment";
// 1. Compile regexes to DFA
char** patterns = (char**)malloc(rules->rule_count * sizeof(char*));
for (uint64_t i = 0; i < rules->rule_count; i++) {
patterns[i] = rules->rules[i].Pattern;
}
int dfa_state_count = 0;
DFAState* dfa = slex_compile_regexes(patterns, (int)rules->rule_count, &dfa_state_count);
free(patterns);
if (!dfa) return false;
// 2. Open header file if requested
FILE* header_f = NULL;
char* header_base = NULL;
if (options->header_output && strlen(options->header_output) > 0) {
header_f = fopen(options->header_output, "w");
if (!header_f) {
slex_free_dfa(dfa, dfa_state_count);
return false;
}
// Find basename of header_output to include it in the implementation
char* last_slash = strrchr(options->header_output, '/');
char* last_backslash = strrchr(options->header_output, '\\');
char* base = options->header_output;
if (last_slash && last_slash > base) base = last_slash + 1;
if (last_backslash && last_backslash > base) base = last_backslash + 1;
header_base = strdup(base);
// Write header guard
fprintf(header_f, "#ifndef __SLEX_GENERATED_H__\n");
fprintf(header_f, "#define __SLEX_GENERATED_H__\n\n");
generate_declarations(header_f, options, rules);
fprintf(header_f, "#endif\n");
fclose(header_f);
}
// 3. Write implementation to output_file
fprintf(output_file, "#include <stdio.h>\n");
fprintf(output_file, "#include <stdlib.h>\n");
fprintf(output_file, "#include <string.h>\n");
fprintf(output_file, "#include <stdbool.h>\n\n");
if (header_base) {
fprintf(output_file, "#include \"%s\"\n\n", header_base);
free(header_base);
} else {
// Output inline declarations
generate_declarations(output_file, options, rules);
}
// Extract variables and post-processor code
char* variables = "";
char* post_processor = "";
for (uint64_t i = 0; i < rules->code_block_count; i++) {
if (rules->code_blocks[i].target_languge == c_language) {
if (rules->code_blocks[i].variables) {
variables = rules->code_blocks[i].variables;
}
if (rules->code_blocks[i].post_processor_code) {
post_processor = rules->code_blocks[i].post_processor_code;
}
break;
}
}
// Write variables
if (strlen(variables) > 0) {
fprintf(output_file, "/* --- User Variables --- */\n%s\n/* ---------------------- */\n\n", variables);
}
// Write slex_post_process function
fprintf(output_file, "%spost_process_result %spost_process(%s* input, %s** output) {\n", prefix, prefix, data_type, data_type);
if (strlen(post_processor) > 0) {
fprintf(output_file, "%s\n", post_processor);
} else {
// Default implementation
fprintf(output_file, " *output = input;\n");
fprintf(output_file, " return %scontinue;\n", prefix);
}
fprintf(output_file, "}\n\n");
// Write transition table
fprintf(output_file, "static const int transitions[%d][256] = {\n", dfa_state_count);
for (int i = 0; i < dfa_state_count; i++) {
fprintf(output_file, " {");
for (int c = 0; c < 256; c++) {
fprintf(output_file, "%d", dfa[i].transitions[c]);
if (c < 255) fprintf(output_file, ", ");
}
fprintf(output_file, "}");
if (i < dfa_state_count - 1) fprintf(output_file, ",\n");
else fprintf(output_file, "\n");
}
fprintf(output_file, "};\n\n");
// Write accepting rules table
fprintf(output_file, "static const int accepting_rules[%d] = {\n ", dfa_state_count);
for (int i = 0; i < dfa_state_count; i++) {
fprintf(output_file, "%d", dfa[i].accept_rule_index);
if (i < dfa_state_count - 1) fprintf(output_file, ", ");
}
fprintf(output_file, "\n};\n\n");
// Write mapping mappings table/resolver
fprintf(output_file, "static void assign_tag_and_id(%s* node, int rule_idx) {\n", data_type);
fprintf(output_file, " switch(rule_idx) {\n");
for (uint64_t i = 0; i < rules->rule_count; i++) {
fprintf(output_file, " case %d:\n", (int)i);
fprintf(output_file, " node->tag = %stag_%s;\n", prefix, rules->rules[i].Tag);
const char* mapped_id = get_mapped_id(rules, rules->rules[i].Tag);
if (mapped_id) {
fprintf(output_file, " node->id = %sid_%s;\n", prefix, mapped_id);
} else {
fprintf(output_file, " node->id = %sid_default;\n", prefix);
}
fprintf(output_file, " break;\n");
}
fprintf(output_file, " }\n");
fprintf(output_file, "}\n\n");
// Write slex_free function
fprintf(output_file, "char %sfree(%s* head) {\n", prefix, data_type);
fprintf(output_file, " while (head) {\n");
fprintf(output_file, " %s* next = head->next;\n", data_type);
fprintf(output_file, " free(head->head);\n");
fprintf(output_file, " if (head->file_name) free(head->file_name);\n");
fprintf(output_file, " free(head);\n");
fprintf(output_file, " head = next;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " return 1;\n");
fprintf(output_file, "}\n\n");
// Write slex_cstr function (DFA matching loop)
fprintf(output_file, "char %scstr(char* input, char* file_name, %s** head) {\n", prefix, data_type);
fprintf(output_file, " if (!input || !head) return 0;\n");
fprintf(output_file, " *head = NULL;\n");
fprintf(output_file, " %s* tail = NULL;\n", data_type);
fprintf(output_file, " char* p = input;\n");
fprintf(output_file, " int64_t current_line = 1;\n");
fprintf(output_file, " int64_t current_col = 1;\n\n");
fprintf(output_file, " while (*p != '\\0') {\n");
fprintf(output_file, " int state = 0;\n");
fprintf(output_file, " char* match_end = NULL;\n");
fprintf(output_file, " int match_rule = -1;\n");
fprintf(output_file, " int64_t token_line = current_line;\n");
fprintf(output_file, " int64_t token_col = current_col;\n\n");
fprintf(output_file, " char* curr_p = p;\n");
fprintf(output_file, " while (*curr_p != '\\0') {\n");
fprintf(output_file, " unsigned char c = (unsigned char)*curr_p;\n");
fprintf(output_file, " int next_state = transitions[state][c];\n");
fprintf(output_file, " if (next_state == -1) break;\n");
fprintf(output_file, " state = next_state;\n");
fprintf(output_file, " if (accepting_rules[state] != -1) {\n");
fprintf(output_file, " match_end = curr_p + 1;\n");
fprintf(output_file, " match_rule = accepting_rules[state];\n");
fprintf(output_file, " }\n");
fprintf(output_file, " curr_p++;\n");
fprintf(output_file, " }\n\n");
fprintf(output_file, " if (match_rule != -1 && match_end > p) {\n");
fprintf(output_file, " int64_t len = match_end - p;\n");
fprintf(output_file, " %s* node = (%s*)malloc(sizeof(%s));\n", data_type, data_type, data_type);
fprintf(output_file, " node->head = (char*)malloc(len + 1);\n");
fprintf(output_file, " memcpy(node->head, p, len);\n");
fprintf(output_file, " node->head[len] = '\\0';\n");
fprintf(output_file, " node->length = len;\n");
fprintf(output_file, " node->file_name = file_name ? strdup(file_name) : NULL;\n");
fprintf(output_file, " node->line = token_line;\n");
fprintf(output_file, " node->col = token_col;\n");
fprintf(output_file, " node->prev = NULL;\n");
fprintf(output_file, " node->next = NULL;\n");
fprintf(output_file, " assign_tag_and_id(node, match_rule);\n\n");
fprintf(output_file, " // Update line/col tracker\n");
fprintf(output_file, " for (char* t = p; t < match_end; t++) {\n");
fprintf(output_file, " if (*t == '\\n') {\n");
fprintf(output_file, " current_line++;\n");
fprintf(output_file, " current_col = 1;\n");
fprintf(output_file, " } else {\n");
fprintf(output_file, " current_col++;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n\n");
fprintf(output_file, " %s* output_node = NULL;\n", data_type);
fprintf(output_file, " %spost_process_result pr = %spost_process(node, &output_node);\n", prefix, prefix);
fprintf(output_file, " if (pr == %sskip) {\n", prefix);
fprintf(output_file, " free(node->head);\n");
fprintf(output_file, " if (node->file_name) free(node->file_name);\n");
fprintf(output_file, " free(node);\n");
fprintf(output_file, " } else {\n");
fprintf(output_file, " %s* to_append = (pr == %scontinue_with_output) ? output_node : node;\n", data_type, prefix);
fprintf(output_file, " if (to_append) {\n");
fprintf(output_file, " if (!*head) {\n");
fprintf(output_file, " *head = to_append;\n");
fprintf(output_file, " tail = to_append;\n");
fprintf(output_file, " } else {\n");
fprintf(output_file, " tail->next = to_append;\n");
fprintf(output_file, " to_append->prev = tail;\n");
fprintf(output_file, " tail = to_append;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n");
fprintf(output_file, " p = match_end;\n");
fprintf(output_file, " } else if (*p == ' ' || *p == '\\t' || *p == '\\r' || *p == '\\n') {\n");
fprintf(output_file, " if (*p == '\\n') {\n");
fprintf(output_file, " current_line++;\n");
fprintf(output_file, " current_col = 1;\n");
fprintf(output_file, " } else {\n");
fprintf(output_file, " current_col++;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " p++;\n");
fprintf(output_file, " } else {\n");
fprintf(output_file, " fprintf(stderr, \"Lexical error at %%s:%%lld:%%lld near '%%c'\\n\", file_name ? file_name : \"<input>\", (long long)token_line, (long long)token_col, *p);\n");
fprintf(output_file, " %sfree(*head);\n", prefix);
fprintf(output_file, " *head = NULL;\n");
fprintf(output_file, " return 0;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n");
fprintf(output_file, " return 1;\n");
fprintf(output_file, "}\n\n");
// Write slex_file function
fprintf(output_file, "char %sfile(FILE* f, char* file_name, %s** head) {\n", prefix, data_type);
fprintf(output_file, " if (!f || !head) return 0;\n");
fprintf(output_file, " fseek(f, 0, SEEK_END);\n");
fprintf(output_file, " long size = ftell(f);\n");
fprintf(output_file, " fseek(f, 0, SEEK_SET);\n\n");
fprintf(output_file, " char* buf = (char*)malloc(size + 1);\n");
fprintf(output_file, " if (!buf) return 0;\n");
fprintf(output_file, " size_t read_bytes = fread(buf, 1, size, f);\n");
fprintf(output_file, " buf[read_bytes] = '\\0';\n\n");
fprintf(output_file, " char success = %scstr(buf, file_name, head);\n", prefix);
fprintf(output_file, " free(buf);\n");
fprintf(output_file, " return success;\n");
fprintf(output_file, "}\n");
slex_free_dfa(dfa, dfa_state_count);
return true;
}
+254 -2
View File
@@ -1,7 +1,259 @@
#include "../../../Headers/slex_core.h"
#include "../../../Headers/slex_regex.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Helper to check if a tag is mapped to an ID, and return it.
static const char* get_mapped_id(slex_rules* rules, const char* tag) {
for (uint64_t i = 0; i < rules->mapping_count; i++) {
if (strcmp(rules->mappings[i].Tag, tag) == 0) {
return rules->mappings[i].Id;
}
}
return NULL;
}
// Print a string as a safe C# verbatim string literal
static void print_verbatim_string(FILE* f, const char* str) {
fprintf(f, "@\"");
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == '"') {
fprintf(f, "\"\"");
} else {
fputc(str[i], f);
}
}
fprintf(f, "\"");
}
bool slex_translate_to_file_csharp(slex_options *options, slex_rules *rules, FILE *output_file)
{
// TODO: Stub for moment.
return false;
if (!options || !rules || !output_file) return false;
char* ns_name = (options->namespace_name && strlen(options->namespace_name) > 0) ? options->namespace_name : "SLexGenerated";
char* class_name = (options->class_name && strlen(options->class_name) > 0) ? options->class_name : "SLexer";
char* data_type = (options->data_type_name && strlen(options->data_type_name) > 0) ? options->data_type_name : "Segment";
char* prefix = options->prefix ? options->prefix : "";
// Extract C# code block variables & post_processor
char* variables = "";
char* post_processor = "";
for (uint64_t i = 0; i < rules->code_block_count; i++) {
if (rules->code_blocks[i].target_languge == csharp) {
if (rules->code_blocks[i].variables) {
variables = rules->code_blocks[i].variables;
}
if (rules->code_blocks[i].post_processor_code) {
post_processor = rules->code_blocks[i].post_processor_code;
}
break;
}
}
// Generate file content
fprintf(output_file, "using System;\n");
fprintf(output_file, "using System.IO;\n");
fprintf(output_file, "using System.Text;\n");
fprintf(output_file, "using System.Text.RegularExpressions;\n\n");
fprintf(output_file, "namespace %s\n{\n", ns_name);
// SegmentTag enum
fprintf(output_file, " public enum %sTag\n {\n", data_type);
for (uint64_t i = 0; i < rules->rule_count; i++) {
fprintf(output_file, " %s,\n", rules->rules[i].Tag);
}
fprintf(output_file, " }\n\n");
// SegmentId enum
fprintf(output_file, " public enum %sId\n {\n", data_type);
fprintf(output_file, " Default = 0,\n");
for (uint64_t i = 0; i < rules->mapping_count; i++) {
bool unique = true;
for (uint64_t j = 0; j < i; j++) {
if (strcmp(rules->mappings[j].Id, rules->mappings[i].Id) == 0) {
unique = false;
break;
}
}
if (unique) {
fprintf(output_file, " %s,\n", rules->mappings[i].Id);
}
}
fprintf(output_file, " }\n\n");
// PostProcessResult enum
fprintf(output_file, " public enum PostProcessResult\n {\n");
fprintf(output_file, " Continue,\n");
fprintf(output_file, " Skip,\n");
fprintf(output_file, " ContinueWithOutput\n");
fprintf(output_file, " }\n\n");
// Segment class
fprintf(output_file, " public class %s\n {\n", data_type);
fprintf(output_file, " public string Content { get; set; } = string.Empty;\n");
fprintf(output_file, " public string FileName { get; set; } = string.Empty;\n");
fprintf(output_file, " public %s? Prev { get; set; }\n", data_type);
fprintf(output_file, " public %s? Next { get; set; }\n", data_type);
fprintf(output_file, " public long Line { get; set; }\n");
fprintf(output_file, " public long Column { get; set; }\n");
fprintf(output_file, " public %sTag Tag { get; set; }\n", data_type);
fprintf(output_file, " public %sId Id { get; set; }\n", data_type);
fprintf(output_file, " }\n\n");
// SLexer class
fprintf(output_file, " public class %s\n {\n", class_name);
// User variables
if (strlen(variables) > 0) {
fprintf(output_file, " // --- User Variables ---\n%s\n // ----------------------\n\n", variables);
}
// slex_post_process method
fprintf(output_file, " private PostProcessResult slex_post_process(%s Input, out %s Output)\n {\n", data_type, data_type);
if (strlen(post_processor) > 0) {
fprintf(output_file, "%s\n", post_processor);
} else {
fprintf(output_file, " Output = Input;\n");
fprintf(output_file, " return PostProcessResult.Continue;\n");
}
fprintf(output_file, " }\n\n");
// Compiled System.Text.RegularExpressions.Regex rules using the \G anchor
fprintf(output_file, " private static readonly Regex[] Rules = new Regex[] {\n");
for (uint64_t i = 0; i < rules->rule_count; i++) {
fprintf(output_file, " new Regex(@\"\\G\" + ");
print_verbatim_string(output_file, rules->rules[i].Pattern);
fprintf(output_file, ", RegexOptions.Compiled)");
if (i < rules->rule_count - 1) fprintf(output_file, ",\n");
else fprintf(output_file, "\n");
}
fprintf(output_file, " };\n\n");
// Tag and ID assignment
fprintf(output_file, " private void AssignTagAndId(%s node, int ruleIdx)\n {\n", data_type);
fprintf(output_file, " switch (ruleIdx)\n {\n");
for (uint64_t i = 0; i < rules->rule_count; i++) {
fprintf(output_file, " case %d:\n", (int)i);
fprintf(output_file, " node.Tag = %sTag.%s;\n", data_type, rules->rules[i].Tag);
const char* mapped_id = get_mapped_id(rules, rules->rules[i].Tag);
if (mapped_id) {
fprintf(output_file, " node.Id = %sId.%s;\n", data_type, mapped_id);
} else {
fprintf(output_file, " node.Id = %sId.Default;\n", data_type);
}
fprintf(output_file, " break;\n");
}
fprintf(output_file, " }\n");
fprintf(output_file, " }\n\n");
// SLex overloads
// 1. FileInfo
fprintf(output_file, " public bool %sSLex(FileInfo inputFile, out %s? Head)\n {\n", prefix, data_type);
fprintf(output_file, " if (inputFile == null)\n {\n");
fprintf(output_file, " Head = null;\n");
fprintf(output_file, " return false;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " using (var stream = inputFile.OpenRead())\n {\n");
fprintf(output_file, " return %sSLex(stream, inputFile.FullName, out Head);\n", prefix);
fprintf(output_file, " }\n");
fprintf(output_file, " }\n\n");
// 2. Stream
fprintf(output_file, " public bool %sSLex(Stream inputStream, out %s? Head)\n {\n", prefix, data_type);
fprintf(output_file, " return %sSLex(inputStream, string.Empty, out Head);\n", prefix);
fprintf(output_file, " }\n\n");
// helper Stream with filename
fprintf(output_file, " public bool %sSLex(Stream inputStream, string fileName, out %s? Head)\n {\n", prefix, data_type);
fprintf(output_file, " if (inputStream == null)\n {\n");
fprintf(output_file, " Head = null;\n");
fprintf(output_file, " return false;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " using (var reader = new StreamReader(inputStream))\n {\n");
fprintf(output_file, " return %sSLex(reader.ReadToEnd(), fileName, out Head);\n", prefix);
fprintf(output_file, " }\n");
fprintf(output_file, " }\n\n");
// 3. string
fprintf(output_file, " public bool %sSLex(string inputContent, out %s? Head)\n {\n", prefix, data_type);
fprintf(output_file, " return %sSLex(inputContent, string.Empty, out Head);\n", prefix);
fprintf(output_file, " }\n\n");
// Core matching loop: string with filename
fprintf(output_file, " public bool %sSLex(string inputContent, string fileName, out %s? Head)\n {\n", prefix, data_type);
fprintf(output_file, " Head = null;\n");
fprintf(output_file, " if (inputContent == null) return false;\n\n");
fprintf(output_file, " %s? head = null;\n", data_type);
fprintf(output_file, " %s? tail = null;\n", data_type);
fprintf(output_file, " int idx = 0;\n");
fprintf(output_file, " int len = inputContent.Length;\n");
fprintf(output_file, " long currentLine = 1;\n");
fprintf(output_file, " long currentCol = 1;\n\n");
fprintf(output_file, " while (idx < len)\n {\n");
fprintf(output_file, " int bestRule = -1;\n");
fprintf(output_file, " int bestLen = 0;\n");
fprintf(output_file, " string bestVal = \"\";\n");
fprintf(output_file, " long tokenLine = currentLine;\n");
fprintf(output_file, " long tokenCol = currentCol;\n\n");
fprintf(output_file, " for (int r = 0; r < Rules.Length; r++)\n");
fprintf(output_file, " {\n");
fprintf(output_file, " var m = Rules[r].Match(inputContent, idx);\n");
fprintf(output_file, " if (m.Success && m.Length > bestLen)\n");
fprintf(output_file, " {\n");
fprintf(output_file, " bestLen = m.Length;\n");
fprintf(output_file, " bestRule = r;\n");
fprintf(output_file, " bestVal = m.Value;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n\n");
fprintf(output_file, " if (bestRule != -1 && bestLen > 0)\n {\n");
fprintf(output_file, " var node = new %s\n {\n", data_type);
fprintf(output_file, " Content = bestVal,\n");
fprintf(output_file, " FileName = fileName,\n");
fprintf(output_file, " Line = tokenLine,\n");
fprintf(output_file, " Column = tokenCol\n");
fprintf(output_file, " };\n");
fprintf(output_file, " AssignTagAndId(node, bestRule);\n\n");
fprintf(output_file, " // Update line/col tracker\n");
fprintf(output_file, " for (int t = idx; t < idx + bestLen; t++)\n {\n");
fprintf(output_file, " if (inputContent[t] == '\\n')\n {\n");
fprintf(output_file, " currentLine++;\n");
fprintf(output_file, " currentCol = 1;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " else\n {\n");
fprintf(output_file, " currentCol++;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n\n");
fprintf(output_file, " %s? outputNode;\n", data_type);
fprintf(output_file, " PostProcessResult pr = slex_post_process(node, out outputNode);\n");
fprintf(output_file, " if (pr != PostProcessResult.Skip)\n {\n");
fprintf(output_file, " %s? toAppend = (pr == PostProcessResult.ContinueWithOutput) ? outputNode : node;\n", data_type);
fprintf(output_file, " if (toAppend != null)\n {\n");
fprintf(output_file, " if (head == null)\n {\n");
fprintf(output_file, " head = toAppend;\n");
fprintf(output_file, " tail = toAppend;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " else\n {\n");
fprintf(output_file, " tail.Next = toAppend;\n");
fprintf(output_file, " toAppend.Prev = tail;\n");
fprintf(output_file, " tail = toAppend;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n");
fprintf(output_file, " idx += bestLen;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " else\n {\n");
fprintf(output_file, " Console.Error.WriteLine($\"Lexical error at {fileName}:{tokenLine}:{tokenCol} near '{inputContent[idx]}'\");\n");
fprintf(output_file, " Head = null;\n");
fprintf(output_file, " return false;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n\n");
fprintf(output_file, " Head = head;\n");
fprintf(output_file, " return true;\n");
fprintf(output_file, " }\n");
fprintf(output_file, " }\n");
fprintf(output_file, "}\n");
return true;
}