From b53eb6e4f1b5fa4e2a4907022f591eb9a1860c33 Mon Sep 17 00:00:00 2001 From: udo Date: Mon, 20 Apr 2026 21:41:23 +0000 Subject: [PATCH] Enhance template parser to handle C++ comments and refactor preprocessing logic - Updated parser to correctly interpret C++ `//` and `/* ... */` comments within template code. - Split preprocessing implementation into separate files for better organization. - Added regression test for comment parsing in templates. - Adjusted CSS styles for improved layout and readability in documentation. --- README.md | 4 + site/doc/index.uce | 99 +++++--- site/doc/style.css | 96 ++++--- site/test/index.uce | 1 + site/test/preprocessor-comments.uce | 39 +++ site/test/style.css | 8 +- src/lib/compiler-parser.cpp | 373 ++++++++++++++++++++++++++++ src/lib/compiler-parser.h | 5 + src/lib/compiler.cpp | 331 +----------------------- src/lib/compiler.h | 1 - src/lib/uce_lib.cpp | 1 + 11 files changed, 568 insertions(+), 390 deletions(-) create mode 100644 site/test/preprocessor-comments.uce create mode 100644 src/lib/compiler-parser.cpp create mode 100644 src/lib/compiler-parser.h diff --git a/README.md b/README.md index a24249d..d7c04ea 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,10 @@ Inside `<> ... ` literal blocks, UCE supports three inline forms: Use `` by default for user-visible text. Use `` only for trusted markup or content that has already been escaped. +The parser now treats C++ `//` and `/* ... */` comments as comments in both normal code and `` islands, so quotes or `<>` markers inside comments do not confuse template parsing. + +The preprocessing implementation is now split between `src/lib/compiler.cpp` and `src/lib/compiler-parser.cpp`. `compiler.cpp` owns unit compilation and cache orchestration, while `compiler-parser.cpp` owns source rewriting and template parsing. + ## Components UCE includes a native component layer built on top of ordinary `.uce` files: diff --git a/site/doc/index.uce b/site/doc/index.uce index 70cb1d4..0f38682 100644 --- a/site/doc/index.uce +++ b/site/doc/index.uce @@ -133,10 +133,25 @@ RENDER(Request& context) } else { - ?>
+
1) + String new_class = s.substr(1); + + // Close previous section's div if it was rendered + if(line_idx > 1 && !section_hidden) { ?>

Parameters

Signature

Description

Related PHP and JS

Related

Parameters

Signature

Description

Related

0) + if(line_idx > 0 && !section_hidden) { ?>
0) + { + ?> diff --git a/site/doc/style.css b/site/doc/style.css index 5d2b492..1f639ba 100644 --- a/site/doc/style.css +++ b/site/doc/style.css @@ -2,12 +2,12 @@ Color palette: deep blue gradient · warm gold accents · frosted glass surfaces */ :root { - --bg: #0b1d4e; - --bg-grad: linear-gradient(168deg, #0f2462 0%, #0b1d4e 40%, #091840 100%); + --bg: #113399; + --bg-grad: linear-gradient(168deg, #1a3daa 0%, #113399 40%, #0d2880 100%); --bg-surface: rgba(255, 255, 255, 0.05); --bg-surface-hover: rgba(255, 255, 255, 0.09); - --bg-inset: rgba(0, 0, 0, 0.3); - --bg-code: rgba(0, 0, 0, 0.32); + --bg-inset: rgba(0, 0, 0, 0.28); + --bg-code: rgba(0, 0, 0, 0.3); --text: #dfe5f2; --text-dim: rgba(200, 210, 235, 0.6); --text-muted: rgba(200, 210, 235, 0.35); @@ -67,7 +67,7 @@ body { h1 { font-family: var(--font-mono); - font-size: 1.6rem; + font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; padding: 32px 0 20px; @@ -88,7 +88,7 @@ h1 a:hover { h2 { font-family: var(--font-mono); - font-size: 1.2rem; + font-size: 1.15rem; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 16px; @@ -97,7 +97,7 @@ h2 { h3 { font-family: var(--font-mono); - font-size: 0.82rem; + font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; @@ -170,7 +170,7 @@ a:hover { .category li a { font-family: var(--font-mono); - font-size: 0.85rem; + font-size: 0.875rem; display: block; padding: 3px 8px; border-radius: 4px; @@ -194,7 +194,7 @@ a:hover { .func-item { font-family: var(--font-mono); - font-size: 0.88rem; + font-size: 0.875rem; } .func-item a { @@ -211,7 +211,7 @@ a:hover { } .badge { - font-size: 0.65rem; + font-size: 0.7rem; font-weight: 600; padding: 2px 8px; border-radius: 10px; @@ -229,7 +229,7 @@ a:hover { /* ── Detail Page ── */ .doc-detail { - max-width: 780px; + min-width: 0; } .doc-section { @@ -251,7 +251,7 @@ a:hover { .sig { font-family: var(--font-mono); - font-size: 1.05rem; + font-size: 0.95rem; white-space: pre-wrap; line-height: 1.5; background: var(--bg-code); @@ -287,21 +287,61 @@ a:hover { font-weight: 500; } -.related { - background: var(--accent-dim); - border: 1px solid rgba(240, 196, 48, 0.12); +/* ── Detail Layout (sidebar for related) ── */ + +.detail-layout { + display: grid; + grid-template-columns: 1fr 220px; + gap: 24px; + align-items: start; +} + +.detail-layout.no-sidebar { + grid-template-columns: 1fr; +} + +@media (max-width: 900px) { + .detail-layout { + grid-template-columns: 1fr; + } +} + +.detail-sidebar { + position: sticky; + top: 20px; +} + +.sidebar-card { + background: var(--bg-surface); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid var(--border); border-radius: var(--radius); - padding: 14px 20px; - font-size: 0.9rem; + padding: 16px 20px; + box-shadow: var(--shadow-sm); +} + +.sidebar-card h3 { + margin-bottom: 10px; + padding-bottom: 8px; + border-bottom: 1px solid var(--border); +} + +.sidebar-card div { + padding: 3px 0; + font-size: 0.875rem; + line-height: 1.5; color: var(--text-dim); } -.related div { - padding: 2px 0; +.sidebar-card strong { + color: var(--text); + font-weight: 600; } -.related strong { - color: var(--text); +.sidebar-card code { + font-size: 0.8rem; + padding: 1px 5px; } .see { @@ -312,7 +352,7 @@ a:hover { .see a { font-family: var(--font-mono); - font-size: 0.92rem; + font-size: 0.875rem; } .see .category { @@ -376,7 +416,7 @@ pre { border: 1px solid var(--border); border-radius: var(--radius); font-family: var(--font-mono); - font-size: 0.86rem; + font-size: 0.875rem; line-height: 1.6; white-space: pre-wrap; box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.12); @@ -384,7 +424,7 @@ pre { code { font-family: var(--font-mono); - font-size: 0.9em; + font-size: 0.875rem; padding: 2px 6px; background: var(--bg-inset); border-radius: 4px; @@ -457,7 +497,7 @@ details pre { border-radius: 8px; color: var(--text); font-family: var(--font-sans); - font-size: 0.95rem; + font-size: 0.875rem; transition: border-color 150ms var(--ease), box-shadow 150ms var(--ease); } @@ -472,7 +512,7 @@ details pre { } .search-count { - font-size: 0.82rem; + font-size: 0.75rem; color: var(--text-muted); white-space: nowrap; } @@ -505,11 +545,11 @@ details pre { .search-hit a { flex-shrink: 0; font-family: var(--font-mono); - font-size: 0.92rem; + font-size: 0.875rem; } .search-snippet { - font-size: 0.78rem; + font-size: 0.75rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; diff --git a/site/test/index.uce b/site/test/index.uce index 7323524..856e027 100644 --- a/site/test/index.uce +++ b/site/test/index.uce @@ -33,6 +33,7 @@ RENDER(Request& context)
Data Types & Parsing
+ diff --git a/site/test/preprocessor-comments.uce b/site/test/preprocessor-comments.uce new file mode 100644 index 0000000..7a2c632 --- /dev/null +++ b/site/test/preprocessor-comments.uce @@ -0,0 +1,39 @@ +RENDER(Request& context) +{ + // Regression: this comment contains <> and an apostrophe that shouldn't start a literal block: <> + String outer_status = "outer parser ok"; + + <> + +

+ UCE Test: + Preprocessor Comments +

+ +

This page exists to prove the template parser ignores quotes and template markers that appear inside C++ comments.

+ + marker. + String inline_status = "inline comment ok"; + ?> + + markers + without confusing the parser or the generated .cpp output. + */ + String block_status = "block comment ok"; + ?> + + + +
+ Request Parameters +
+
+ +} \ No newline at end of file diff --git a/site/test/style.css b/site/test/style.css index 51966a4..1584c59 100644 --- a/site/test/style.css +++ b/site/test/style.css @@ -2,12 +2,12 @@ Color palette: deep blue gradient · warm gold accents · frosted glass surfaces */ :root { - --bg: #0b1d4e; - --bg-grad: linear-gradient(168deg, #0f2462 0%, #0b1d4e 40%, #091840 100%); + --bg: #113399; + --bg-grad: linear-gradient(168deg, #1a3daa 0%, #113399 40%, #0d2880 100%); --bg-surface: rgba(255, 255, 255, 0.05); --bg-surface-hover: rgba(255, 255, 255, 0.09); - --bg-inset: rgba(0, 0, 0, 0.3); - --bg-code: rgba(0, 0, 0, 0.32); + --bg-inset: rgba(0, 0, 0, 0.28); + --bg-code: rgba(0, 0, 0, 0.3); --text: #dfe5f2; --text-dim: rgba(200, 210, 235, 0.6); --text-muted: rgba(200, 210, 235, 0.35); diff --git a/src/lib/compiler-parser.cpp b/src/lib/compiler-parser.cpp new file mode 100644 index 0000000..a4effc8 --- /dev/null +++ b/src/lib/compiler-parser.cpp @@ -0,0 +1,373 @@ +#include "compiler-parser.h" + +#include "compiler.h" + +namespace { + +const char* UCE_NAMED_RENDER_SYMBOL = "__uce_render"; +const char* UCE_NAMED_COMPONENT_SYMBOL = "__uce_component"; + +struct CompilerCodeState +{ + char quote_char = '\0'; + bool inside_quote = false; + bool inside_line_comment = false; + bool inside_block_comment = false; +}; + +bool compiler_code_state_is_neutral(const CompilerCodeState& state) +{ + return(!state.inside_quote && !state.inside_line_comment && !state.inside_block_comment); +} + +void compiler_code_state_consume(CompilerCodeState& state, String& buffer, const String& content, u32& i) +{ + char c = content[i]; + char c1 = (i + 1 < content.length()) ? content[i + 1] : '\0'; + + buffer.append(1, c); + + if(state.inside_quote) + { + if(state.quote_char == c && (i == 0 || content[i-1] != '\\')) + state.inside_quote = false; + return; + } + + if(state.inside_line_comment) + { + if(c == '\n') + state.inside_line_comment = false; + return; + } + + if(state.inside_block_comment) + { + if(c == '*' && c1 == '/') + { + buffer.append(1, c1); + state.inside_block_comment = false; + i += 1; + } + return; + } + + if(c == '/' && c1 == '/') + { + buffer.append(1, c1); + state.inside_line_comment = true; + i += 1; + return; + } + + if(c == '/' && c1 == '*') + { + buffer.append(1, c1); + state.inside_block_comment = true; + i += 1; + return; + } + + if(c == '"' || c == '\'') + { + state.inside_quote = true; + state.quote_char = c; + } +} + +String compiler_capture_markup_literal(const String& content, u32& i) +{ + String buffer = ""; + u32 depth = 0; + bool inside_code = false; + CompilerCodeState code_state; + u32 j = i + 2; + + while(j < content.length()) + { + char c = content[j]; + char c1 = (j + 1 < content.length()) ? content[j + 1] : '\0'; + char c2 = (j + 2 < content.length()) ? content[j + 2] : '\0'; + + if(inside_code) + { + if(compiler_code_state_is_neutral(code_state) && c == '?' && c1 == '>') + { + buffer.append(1, c); + buffer.append(1, c1); + inside_code = false; + j += 2; + continue; + } + + compiler_code_state_consume(code_state, buffer, content, j); + j += 1; + continue; + } + + if(c == '<' && c1 == '?') + { + inside_code = true; + code_state = CompilerCodeState(); + buffer.append(1, c); + buffer.append(1, c1); + j += 2; + continue; + } + + if(c == '<' && c1 == '/' && c2 == '>') + { + if(depth > 0) + { + depth -= 1; + buffer.append(""); + j += 3; + continue; + } + + i = j + 2; + return(buffer); + } + + if(c == '<' && c1 == '>') + { + depth += 1; + buffer.append("<>"); + j += 2; + continue; + } + + buffer.append(1, c); + j += 1; + } + + i = content.length(); + return(buffer); +} + +String compiler_process_text_literal(Request* context, SharedUnit* su, String content) +{ + String parsed_content; + String html_output_start = "print(R\"("; + String html_output_end = ")\");"; + String code_buffer = ""; + CompilerCodeState code_state; + bool inside_code = false; + bool is_field = false; + bool escape_field = false; + + for(u32 i = 0; i < content.length(); i++) + { + char c = content[i]; + char c1 = (i + 1 < content.length()) ? content[i + 1] : '\0'; + char c2 = (i + 2 < content.length()) ? content[i + 2] : '\0'; + + if(!inside_code) + { + if(c == '<' && c1 == '?') + { + inside_code = true; + code_buffer = ""; + code_state = CompilerCodeState(); + if(c2 == '=') + { + is_field = true; + escape_field = true; + i += 2; + } + else if(c2 == ':') + { + is_field = true; + escape_field = false; + i += 2; + } + else + { + is_field = false; + escape_field = false; + i += 1; + } + continue; + } + + parsed_content.append(1, c); + continue; + } + + if(compiler_code_state_is_neutral(code_state) && c == '?' && c1 == '>') + { + inside_code = false; + i += 1; + if(is_field) + { + if(escape_field) + { + parsed_content.append( + html_output_end + + "print(html_escape( " + + code_buffer + + " )); " + + html_output_start + ); + } + else + { + parsed_content.append( + html_output_end + + "print( " + + code_buffer + + " ); " + + html_output_start + ); + } + } + else + { + parsed_content.append(html_output_end + code_buffer + html_output_start); + } + continue; + } + + if(compiler_code_state_is_neutral(code_state) && c == '<' && c1 == '>') + { + String nested_markup = compiler_capture_markup_literal(content, i); + code_buffer.append(compiler_process_text_literal(context, su, nested_markup)); + continue; + } + + compiler_code_state_consume(code_state, code_buffer, content, i); + } + + return(html_output_start + parsed_content + html_output_end); +} + +String compiler_rewrite_named_render_syntax(String content) +{ + String result = ""; + String current_line = ""; + + auto flush_line = [&]() { + if(current_line.length() == 0) + return; + + String line = current_line; + String line_break = ""; + if(line.length() > 0 && line.back() == '\n') + { + line_break = "\n"; + line.pop_back(); + } + + u32 indent_length = 0; + while(indent_length < line.length() && isspace(line[indent_length])) + indent_length += 1; + + String indent = line.substr(0, indent_length); + String trimmed = trim(line); + if(trimmed.rfind("RENDER:", 0) == 0) + { + String signature = trimmed.substr(7); + auto open_paren_pos = signature.find("("); + if(open_paren_pos != String::npos) + { + String render_name = trim(signature.substr(0, open_paren_pos)); + String render_signature = signature.substr(open_paren_pos); + if(render_name != "") + line = indent + "EXPORT void " + String(UCE_NAMED_RENDER_SYMBOL) + "_" + safe_name(render_name) + render_signature; + } + } + else if(trimmed.rfind("COMPONENT:", 0) == 0) + { + String signature = trimmed.substr(10); + auto open_paren_pos = signature.find("("); + if(open_paren_pos != String::npos) + { + String render_name = trim(signature.substr(0, open_paren_pos)); + String render_signature = signature.substr(open_paren_pos); + if(render_name != "") + line = indent + "EXPORT void " + String(UCE_NAMED_COMPONENT_SYMBOL) + "_" + safe_name(render_name) + render_signature; + } + } + + result += line + line_break; + current_line = ""; + }; + + for(auto c : content) + { + current_line.append(1, c); + if(c == '\n') + flush_line(); + } + flush_line(); + + return(result); +} + +String compiler_preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String content) +{ + String parsed_content = + ("#include \"")+context->server->config["COMPILER_SYS_PATH"] +"/src/lib/uce_lib.h\" \n"+ + file_get_contents( + context->server->config["COMPILER_SYS_PATH"] + "/" + context->server->config["SETUP_TEMPLATE"] + )+ + "#line 1\n"; + CompilerCodeState code_state; + String current_line = ""; + + for(u32 i = 0; i < content.length(); i++) + { + char c = content[i]; + char c1 = (i + 1 < content.length()) ? content[i + 1] : '\0'; + current_line.append(1, c); + + if(compiler_code_state_is_neutral(code_state) && c == '<' && c1 == '>') + { + String markup_literal = compiler_capture_markup_literal(content, i); + parsed_content.append(compiler_process_text_literal(context, su, markup_literal)); + if(i < content.length() && content[i] == '\n') + current_line = "\n"; + continue; + } + + compiler_code_state_consume(code_state, parsed_content, content, i); + + if(c == 10 && current_line.substr(0, 6) == "#load ") + { + parsed_content.resize(parsed_content.length() - current_line.length()); + nibble(current_line, "\""); + String unit_name = nibble(current_line, "\""); + SharedUnit* sub_su = compiler_load_shared_unit(context, unit_name, su->src_path, true); + if(sub_su) + parsed_content.append("#include \"" + sub_su->bin_path + "/" + sub_su->pre_file_name + "\"\n"); + } + else + { + String trimmed_line = trim(current_line); + if(c == 10 && trimmed_line.length() > 7 && trimmed_line.substr(0, 6) == "EXPORT" && isspace(trimmed_line[6])) + { + current_line = ""; + auto end_declaration_pos = content.find("{", i); + if(end_declaration_pos != std::string::npos) + { + parsed_content.append(1, '\n'); + String declaration = trim(content.substr(i, end_declaration_pos - i)); + su->api_declarations.push_back(declaration+";\n"); + } + } + } + + if(c == 10) + current_line = ""; + } + + return(parsed_content); +} + +} + +String compiler_preprocess_source(Request* context, SharedUnit* su, String content) +{ + content = compiler_rewrite_named_render_syntax(content); + return(compiler_preprocess_shared_unit_char_wise(context, su, content)); +} \ No newline at end of file diff --git a/src/lib/compiler-parser.h b/src/lib/compiler-parser.h new file mode 100644 index 0000000..42433d9 --- /dev/null +++ b/src/lib/compiler-parser.h @@ -0,0 +1,5 @@ +#pragma once + +#include "types.h" + +String compiler_preprocess_source(Request* context, SharedUnit* su, String content); \ No newline at end of file diff --git a/src/lib/compiler.cpp b/src/lib/compiler.cpp index 8a0108a..fabd57d 100644 --- a/src/lib/compiler.cpp +++ b/src/lib/compiler.cpp @@ -1,4 +1,5 @@ #include "compiler.h" +#include "compiler-parser.h" #include #include #include @@ -103,6 +104,8 @@ time_t compiler_runtime_abi_time(Request* context) return(std::max({ file_mtime(root + "/src/lib/compiler.h"), file_mtime(root + "/src/lib/compiler.cpp"), + file_mtime(root + "/src/lib/compiler-parser.h"), + file_mtime(root + "/src/lib/compiler-parser.cpp"), file_mtime(root + "/bin/uce_fastcgi.linux.bin") })); } @@ -201,7 +204,8 @@ SharedUnitFilesystemState inspect_shared_unit_filesystem(Request* context, Share state.source_time = file_mtime(su->file_name); state.setup_template_time = file_mtime( context->server->config["COMPILER_SYS_PATH"] + "/" + - context->server->config["SETUP_TEMPLATE"]); + context->server->config["SETUP_TEMPLATE"] + ); state.compiler_header_time = file_mtime(context->server->config["COMPILER_SYS_PATH"] + "/src/lib/compiler.h"); state.compiler_source_time = file_mtime(context->server->config["COMPILER_SYS_PATH"] + "/src/lib/compiler.cpp"); state.runtime_binary_time = file_mtime(context->server->config["COMPILER_SYS_PATH"] + "/bin/uce_fastcgi.linux.bin"); @@ -425,333 +429,10 @@ bool compiler_can_write_response(Request* context) } -String process_text_literal(Request* context, SharedUnit* su, String content) -{ - String pc; - String HT_START = "print(R\"("; - String HT_END = ")\");"; - - u8 mode = 0; - char quote_char; - bool inside_quote = false; - String code_buffer = ""; - bool is_field = false; - bool escape_field = false; - - for(u32 i = 0; i < content.length(); i++) - { - char c = content[i]; - char c1 = (i + 1 < content.length()) ? content[i + 1] : '\0'; - char c2 = (i + 2 < content.length()) ? content[i + 2] : '\0'; - - switch(mode) - { - case(0): - if(c == '<' && c1 == '?') - { - code_buffer = ""; - if(c2 == '=') - { - is_field = true; - escape_field = true; - i += 2; - } - else if(c2 == ':') - { - is_field = true; - escape_field = false; - i += 2; - } - else - { - is_field = false; - escape_field = false; - i += 1; - } - mode = 1; // code-parsing mode - } - else - { - pc.append(1, c); - } - break; - case(1): - if(inside_quote) - { - if(quote_char == c && (i == 0 || content[i-1] != '\\')) - inside_quote = false; - code_buffer.append(1, c); - } - else - { - if(c == '\"' || c == '\'') - { - inside_quote = true; - quote_char = c; - code_buffer.append(1, c); - } - else if(c == '?' && c1 == '>') - { - mode = 0; - i += 1; - if(is_field) - { - if(escape_field) - { - pc.append( - HT_END + - "print(html_escape( " + - code_buffer + - " )); " + - HT_START - ); - } - else - { - pc.append( - HT_END + - "print( " + - code_buffer + - " ); " + - HT_START - ); - } - } - else - { - pc.append(HT_END + code_buffer + HT_START); - } - } - else if(c == '<' && c1 == '>') - { - // Nested <> markup block inside code - String sub_buffer = ""; - u32 sub_depth = 0; - u32 j = i + 2; - while(j < content.length()) - { - char jc = content[j]; - char jc1 = (j + 1 < content.length()) ? content[j + 1] : '\0'; - char jc2 = (j + 2 < content.length()) ? content[j + 2] : '\0'; - if(jc == '<' && jc1 == '/' && jc2 == '>') - { - if(sub_depth > 0) - { - sub_depth--; - sub_buffer.append(""); - j += 3; - } - else - { - j += 3; - break; - } - } - else if(jc == '<' && jc1 == '>') - { - sub_depth++; - sub_buffer.append("<>"); - j += 2; - } - else - { - sub_buffer.append(1, jc); - j++; - } - } - i = j - 1; // -1 because outer for loop increments - code_buffer.append(process_text_literal(context, su, sub_buffer)); - } - else - { - code_buffer.append(1, c); - } - } - break; - } - - } - - return(HT_START + pc + HT_END); -} - -String preprocess_named_render_syntax(String content) -{ - String result = ""; - String current_line = ""; - - auto flush_line = [&]() { - if(current_line.length() == 0) - return; - - String line = current_line; - String line_break = ""; - if(line.length() > 0 && line.back() == '\n') - { - line_break = "\n"; - line.pop_back(); - } - - u32 indent_length = 0; - while(indent_length < line.length() && isspace(line[indent_length])) - indent_length += 1; - - String indent = line.substr(0, indent_length); - String trimmed = trim(line); - if(trimmed.rfind("RENDER:", 0) == 0) - { - String signature = trimmed.substr(7); - auto open_paren_pos = signature.find("("); - if(open_paren_pos != String::npos) - { - String render_name = trim(signature.substr(0, open_paren_pos)); - String render_signature = signature.substr(open_paren_pos); - if(render_name != "") - line = indent + "EXPORT void " + String(UCE_RENDER_SYMBOL) + "_" + safe_name(render_name) + render_signature; - } - } - else if(trimmed.rfind("COMPONENT:", 0) == 0) - { - String signature = trimmed.substr(10); - auto open_paren_pos = signature.find("("); - if(open_paren_pos != String::npos) - { - String render_name = trim(signature.substr(0, open_paren_pos)); - String render_signature = signature.substr(open_paren_pos); - if(render_name != "") - line = indent + "EXPORT void " + String(UCE_COMPONENT_SYMBOL) + "_" + safe_name(render_name) + render_signature; - } - } - - result += line + line_break; - current_line = ""; - }; - - for(auto c : content) - { - current_line.append(1, c); - if(c == '\n') - flush_line(); - } - flush_line(); - - return(result); -} - -String preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String content) -{ - String pc = - ("#include \"")+context->server->config["COMPILER_SYS_PATH"] +"/src/lib/uce_lib.h\" \n"+ - file_get_contents( - context->server->config["COMPILER_SYS_PATH"] + "/" + context->server->config["SETUP_TEMPLATE"] - )+ - "#line 1\n"; - String token = ""; - String html_buffer = ""; - u8 mode = 0; - u32 depth = 0; - bool inside_quote = false; - u32 source_length = content.length(); - String current_line = ""; - for(u32 i = 0; i < source_length; i++) - { - char c = content[i]; - char c1 = (i + 1 < source_length) ? content[i + 1] : '\0'; - char c2 = (i + 2 < source_length) ? content[i + 2] : '\0'; - current_line.append(1, c); - if(mode == 1) - { - if(c == '<' && c1 == '/' && c2 == '>') - { - if(depth > 0) - { - depth -= 1; - token.append(""); - html_buffer.append(""); - i += 2; - } - else - { - i += 2; - pc.append(process_text_literal(context, su, html_buffer)); - mode = 0; - } - } - else if(c == '<' && c1 == '>') - { - depth += 1; - token.append("<>"); - html_buffer.append("<>"); - i += 1; - } - else - { - token.append(1, c); - html_buffer.append(1, c); - } - } - else if(!inside_quote && c == '<' && c1 == '>') - { - mode = 1; - token = ""; - html_buffer = ""; - i += 1; - } - else if(c == '\"') - { - inside_quote = !inside_quote; - pc.append(1, c); - } - else // we're in C++ code here - { - pc.append(1, c); - if(c == 10 && current_line.substr(0, 6) == "#load ") - { - //printf("#load directive\n"); - pc.resize(pc.length() - current_line.length()); - nibble(current_line, "\""); - String unit_name = nibble(current_line, "\""); - //printf("(i) #load %s\n", unit_name.c_str()); - SharedUnit* sub_su = compiler_load_shared_unit(context, unit_name, su->src_path, true); - if(sub_su) - { - pc.append("#include \"" + sub_su->bin_path + "/" + sub_su->pre_file_name + "\"\n"); - } - } - else - { - String trimmed_line = trim(current_line); - if(c == 10 && trimmed_line.length() > 7 && trimmed_line.substr(0, 6) == "EXPORT" && isspace(trimmed_line[6])) - { - current_line = ""; - auto end_declaration_pos = content.find("{", i); - if(end_declaration_pos != std::string::npos) - { - pc.append(1, '\n'); - String declaration = trim(content.substr(i, end_declaration_pos - i)); - su->api_declarations.push_back(declaration+";\n"); - //printf("declaration found: %s\n", declaration.c_str()); - } - } - } - } - if(c == 10) - current_line = ""; - } - return(pc); -} - String preprocess_shared_unit(Request* context, SharedUnit* su) { String content = file_get_contents(su->file_name); - content = preprocess_named_render_syntax(content); - return( - preprocess_shared_unit_char_wise( - context, - su, - content - ) - ); + return(compiler_preprocess_source(context, su, content)); } void setup_unit_paths(Request* context, SharedUnit* su, String file_name) diff --git a/src/lib/compiler.h b/src/lib/compiler.h index 0f2a57c..d0cdf9a 100644 --- a/src/lib/compiler.h +++ b/src/lib/compiler.h @@ -5,7 +5,6 @@ #define WS(X) extern "C" void __uce_websocket(Request& context) #define EXPORT extern "C" -String process_html_literal(Request* context, SharedUnit* su, String content); String preprocess_shared_unit(Request* context, SharedUnit* su); void setup_unit_paths(Request* context, SharedUnit* su, String file_name); void load_shared_unit(Request* context, SharedUnit* su, String file_name); diff --git a/src/lib/uce_lib.cpp b/src/lib/uce_lib.cpp index b5836fb..d845bf5 100644 --- a/src/lib/uce_lib.cpp +++ b/src/lib/uce_lib.cpp @@ -6,6 +6,7 @@ #include "hash.cpp" #include "sys.cpp" #include "uri.cpp" +#include "compiler-parser.cpp" #include "compiler.cpp" #include "markdown.cpp" #include "mysql-connector.cpp"