diff --git a/CMakeLists.txt b/CMakeLists.txt index e4090db..1cc4a1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,8 @@ function(target_set_common target) CXX_STANDARD 17 ) if (EMSCRIPTEN) + target_compile_options(${target} PRIVATE "-fwasm-exceptions") + target_link_options(${target} PRIVATE "-fwasm-exceptions") # Nothing elseif (MSVC) target_compile_options(${target} PRIVATE "/wd4244") @@ -155,8 +157,7 @@ if (EMSCRIPTEN) #string(APPEND CMAKE_CXX_FLAGS " -s WASM_ASYNC_COMPILATION=0") #string(APPEND CMAKE_CXX_FLAGS " -s SIDE_MODULE=1") #string(APPEND CMAKE_CXX_FLAGS " -s DISABLE_EXCEPTION_CATCHING=0") - string(APPEND CMAKE_CXX_FLAGS " -s EXPORTED_FUNCTIONS='[\"_translate\", \"_main\", \"_API\"]'") - string(APPEND CMAKE_CXX_FLAGS " -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'") + string(APPEND CMAKE_CXX_FLAGS " -s EXPORTED_RUNTIME_METHODS='[\"ccall\",\"cwrap\"]'") option(ADD_GOOGLE_ANALYTICS "Build the static library" ON) if (ADD_GOOGLE_ANALYTICS) diff --git a/src/api.cpp b/src/api.cpp index 5de97a3..a192aa8 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -5,6 +5,12 @@ using json = nlohmann::json; +#ifdef __EMSCRIPTEN__ +#include +#else +#define EMSCRIPTEN_KEEPALIVE +#endif + template json API(const std::vector& container) { auto json = json::array(); @@ -50,6 +56,7 @@ json API(const TranslatorPtr& translator) { return json; } +EMSCRIPTEN_KEEPALIVE extern "C" const char* API() { static std::string out; if (out.size() == 0) diff --git a/src/index.html b/src/index.html index 129ce5f..39f1a5d 100644 --- a/src/index.html +++ b/src/index.html @@ -12,6 +12,7 @@ + @@ -85,15 +86,20 @@

Diagram Online

- - -
+ +
+ + +
+ + +
@@ -101,384 +107,398 @@

Diagram Online

Copy
- + +
+ +
-
- - +
+ +
- - - + + const PushState = async function() { + await new Promise(r => setTimeout(r, 0)); + + let data = tools_data[tools.value].tool; + history.pushState({},'Flowchart', '#' + data); + } + + const PullState = async function() { + push_state = PushState; + + if (!location.hash || location.hash == "#landing_page") { + document.querySelector("#landing_page").scrollIntoView(); + return; + } + + let data = location.hash.substr(1); + for(let i in tools_data) { + if (tools_data[i].tool !== data) + continue; + tools.selectedIndex = i; + document.querySelector("#code_area").scrollIntoView(); + OnToolsChanged(); + } + } + window.onpopstate = PullState; + + + + diff --git a/src/input_output_test.cpp b/src/input_output_test.cpp index feb5ae6..6331710 100644 --- a/src/input_output_test.cpp +++ b/src/input_output_test.cpp @@ -73,7 +73,7 @@ int main(int, const char**) { std::cout << output << std::endl; std::cout << "---------------------" << std::endl; - std::ofstream(test.path() / "output") << output_computed; + //std::ofstream(test.path() / "output") << output_computed; result = EXIT_FAILURE; } diff --git a/src/main.cpp b/src/main.cpp index 6e611f4..5ead433 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,8 @@ #ifdef __EMSCRIPTEN__ #include + +EMSCRIPTEN_KEEPALIVE extern "C" const char* translate(const char* translator_name, const char* input, const char* options) { @@ -24,6 +26,21 @@ extern "C" const char* translate(const char* translator_name, } return out.c_str(); } + +EMSCRIPTEN_KEEPALIVE +extern "C" const char* highlight(const char* translator_name, + const char* input) { + auto* translator = FindTranslator(translator_name); + if (!translator) + std::cerr << "Translator not found" << std::endl; + + static std::string out; + try { + out = translator->Highlight(input); + } catch (...) { + } + return out.c_str(); +} #endif namespace { diff --git a/src/style.css b/src/style.css index 5c7efdb..406bf72 100644 --- a/src/style.css +++ b/src/style.css @@ -1,26 +1,46 @@ -div { +html, body, div { margin: 0px; padding: 0px; } /* Theme */ -:root { - --bg-color: white; - --fg-color: black; - --begin-button-hover: #3cb0ff; - --code-area-bg-color: #AAA; - --select-bg-color: #EEE; +html { --transition-time: 0s; /* Modified via JS */ --displaylatex: none; --displayhtml: none; + + --code-blue-color:blue; + --code-red-color:red; + --code-green-color:green; + + --begin-button-hover: #3cb0ff; + + --bg-color: white; + --fg-color: black; + --input-bg-color: #fff; + --output-bg-color: #fff; + --errors-bg-color: #fff; + + --menu-bar-bg-color: #EEE; + --select-bg-color: #DDD; + --select-fg-color: #000; } [data-theme="dark"] { + --code-blue-color:lightblue; + --code-red-color:#FFCCCB; + --code-green-color:lightgreen; + + --begin-button-hover: green; + --bg-color: black; --fg-color: white; - --begin-button-hover: green; - --code-area-bg-color: #222; - --select-bg-color: #111; + --input-bg-color: #000; + --output-bg-color: #000; + --errors-bg-color: #000; + --menu-bar-bg-color: #111; + --select-bg-color: #222; + --select-fg-color: #FFF; } [data-display-latex="true"] { @@ -41,11 +61,6 @@ html { scroll-behavior: smooth; } -html, body { - margin: 0; - padding: 0; -} - /* Layout */ .displaylatex { display: var(--displaylatex) !important; @@ -57,7 +72,7 @@ html, body { display: var(--displayhtml) !important; overflow: auto; min-height: 0; - background-color: white; + background-color:var(--input-bg-color); } .gutter { @@ -67,7 +82,6 @@ html, body { /* Containers */ .container { - /* overflow: hidden; */ min-height: 0 } @@ -103,6 +117,12 @@ html, body { flex-shrink: 1; } +.flex-equal { + flex-grow: 1; + flex-shrink: 1; + flex-basis:0; +} + .nonflex { flex-grow: 0; flex-shrink: 0; @@ -142,7 +162,7 @@ html, body { font-size: 20vmin; margin: 0; padding: 0; - transition: text-shadow 1s ease-in-out 1s; + transition: text-shadow 1s cubic-bezier(0.26, -1.23, 0.67, 1.97) 1s } #landing_page_content h1:hover { @@ -237,29 +257,49 @@ html, body { opacity: 1.0; } +#highlights { + z-index:0; +} + + +#input > textarea { + grid-area: 1 / 1 / 2 / 2; + z-index:1; + color: transparent; + caret-color: var(--fg-color); +} + /* Application area */ -textarea { - font-variant-numeric: tabular-nums lining-nums; +textarea, #highlights { + color: var(--fg-color); + background: transparent; + overflow: auto; + border-radius: 0; + border: 0; + border: none; font-family: 'Dejavu Sans Mono', monospace; font-kerning:none; - border: none; - background-color: transparent; - resize: none; + font-size: 12pt; + font-variant-numeric: tabular-nums lining-nums; + margin: 0; outline: none; + padding:0; + resize: none; white-space: pre; - overflow: auto; + word-wrap: break-word; } /* Menu bar */ #menu_bar { display: flex; + background-color: var(--menu-bar-bg-color); + z-index: 1; } .menu_bar_submenu { margin: 0px; padding: 12px; display: inline-block; - border-right: 1px solid black; vertical-align: center; white-space: nowrap; } @@ -267,6 +307,8 @@ textarea { select { font: inherit; size: 50px; + border: 0; + padding: 7px; } .option { @@ -276,31 +318,135 @@ select { padding-left: 3px; } -select { - border: 0; - padding: 7px; -} - option { border: 0; padding: 7px; margin: 7px; } -#input, #output, #latex, #html{ - padding: 1vh; - margin: 1vh; +#highlights { + grid-area: 1 / 1 / 2 / 2; + overflow: auto; +} + +.flowchart > .IF, +.flowchart > .ELSE, +.flowchart > .WHILE, +.flowchart > .DO, +.flowchart > .SWITCH, +.flowchart > .RETURN +{ + color:var(--code-blue-color); +} +.flowchart > .STRING_DOUBLE_QUOTE, +.flowchart > .STRING_SIMPLE_QUOTE +{ + color:var(--code-green-color); +} +.flowchart > .COMMENT, +.flowchart > .LINE_COMMENT +{ + color:gray; +} +.flowchart > .SEMICOLON +{ + font-weight: bold; } -#input, #output, #errors, #menu_bar, #latex { +.Math > .VARIABLE, +.Math > .STRING { color:var(--fg-color); - background-color:var(--bg-color); - border:0px solid; - box-shadow: 0px 0.5vmin 0.5vmin 0 rgba(0,0,0,0.4); - overflow-y: auto; - min-height: 0; - white-space: pre; - overflow: auto; +} + +.Math > .LPAREN , +.Math > .RPAREN , +.Math > .LBRACE, +.Math > .RBRACE , +.Math > .LBRACKET , +.Math > .RBRACKET +{ + font-weight: bold +} + +.Math > .PLUS , +.Math > .MINUS , +.Math > .TIMES , +.Math > .BANG, +.Math > .DIV , +.Math > .GT , +.Math > .LT , +.Math > .GE , +.Math > .LE , +.Math > .EQ , +.Math > .POW , +.Math > .SUBSCRIPT, +.Math > .EOL +{ + color:var(--code-red-color); + font-weight: bold; +} + +.Sequence > .LOWER, +.Sequence > .GREATER, +.Sequence > .COLON, +.Sequence > .EOL, +.Sequence > .NUMBER, +.Sequence > .SPACE, +.Sequence > .OTHER { +} + +.Sequence > .COMMA, +.Sequence > .ARROW_RIGHT, +.Sequence > .ARROW_LEFT { + color:var(--code-red-color); + font-weight: bold; +} + +.GraphPlanar > .STRING, +.GraphPlanar > .ID { +} + +.GraphPlanar > .STRING { + color:var(--code-green-color); +} +.GraphPlanar > .ID { + color:var(--code-red-color); +} + +.highlight-container { + display: grid; + grid-template-columns: 100%; + grid-template-rows: 100%; + + color:var(--fg-color); + + overflow: hidden; +} + +#highlights { + overflow: hidden; +} + +#input, #output, .highlight-container, .displayhtml, .displaylatex { + padding-left: 2vmin; + padding-top: 2vmin; + padding-right:4px; + border-bottom: 1px solid rgba(128,128,128,0.3); + border-right: 1px solid rgba(128,128,128,0.3); +} + +#input { + background-color:var(--input-bg-color); +} + +#output { + background-color:var(--output-bg-color); + border-bottom: 1px solid rgba(128,128,128,0.3); + border-right: 1px solid rgba(128,128,128,0.3); +} + +#errors { + background-color:var(--errors-bg-color); } /* Begin Button */ @@ -315,16 +461,11 @@ option { } #code_area { - background-color: var(--code-area-bg-color); tab-size: 2; } -#menu_bar { - margin-bottom: 1vmin; -} - select, option { - color: var(--fg-color); + color: var(--select-fg-color); background-color: var(--select-bg-color); } @@ -336,14 +477,12 @@ select, option { .copy { display: block; position: absolute; - color: white; background-color: black; color: white; opacity: 0.7; right: 0; top: 0; z-index: 2; - margin: 1vh; padding: 1vh; transition: opacity 0.3s, background-color 0.3s; box-shadow: x 0.5vmin 0.5vmin 0 inset rgba(0,0,0,0.4); @@ -357,3 +496,38 @@ select, option { .copy[data-active=true] { background-color: green; } + +textarea::-webkit-scrollbar { + width: 3px; + height:3px; +} + +textarea:hover::-webkit-scrollbar { + width: 8px; + height:8px; +} + +textarea::-webkit-scrollbar-track { + background: transparent; +} + +textarea::-webkit-scrollbar-thumb { + background-color: rgba(128,128,128,0.5); + border-radius: 8px; +} + +textarea::-webkit-scrollbar-thumb:hover { + background-color: rgba(128,128,128,1.0); +} + +html::-webkit-scrollbar { + display: none; +} + +html { + scrollbar-width: none; /* Firefox */ +} + +iframe { + border:0; +} diff --git a/src/translator/Translator.h b/src/translator/Translator.h index 3d35dc9..7fe80d0 100644 --- a/src/translator/Translator.h +++ b/src/translator/Translator.h @@ -12,6 +12,7 @@ class Translator { // Main API implemented by translator. --------------------------------------- virtual std::string Translate(const std::string& input, const std::string& option) = 0; + virtual std::string Highlight(const std::string& input) { return input; } virtual ~Translator() = default; // Reflection API ------------------------------------------------------------ diff --git a/src/translator/flowchart/Flowchart.cpp b/src/translator/flowchart/Flowchart.cpp index d6b4740..5687919 100644 --- a/src/translator/flowchart/Flowchart.cpp +++ b/src/translator/flowchart/Flowchart.cpp @@ -29,6 +29,7 @@ class Flowchart : public Translator { std::vector Examples() final; std::string Translate(const std::string& input, const std::string& options_string) final; + std::string Highlight(const std::string& input) final; }; std::vector Flowchart::Examples() { @@ -638,12 +639,48 @@ std::string Flowchart::Translate(const std::string& input, try { context = parser.program(); } catch (...) { - return ""; + return "Error"; } return Parse(context, true).screen.ToString(); } +std::string Flowchart::Highlight(const std::string& input) { + std::stringstream out; + + antlr4::ANTLRInputStream input_stream(input); + + // Lexer. + FlowchartLexer lexer(&input_stream); + antlr4::CommonTokenStream tokens(&lexer); + + try { + tokens.fill(); + } + catch (...) { // Ignore + } + + size_t matched = 0; + out << ""; + for(antlr4::Token* token : tokens.getTokens()) { + std::string text = token->getText(); + if (text == "") { + continue; + } + out << ""; + matched += text.size(); + out << std::move(text); + out << ""; + } + + out << input.substr(matched); + out << ""; + + return out.str(); +} + Draw Parse(FlowchartParser::WhileloopContext* whileloop, bool is_final) { Draw if_ = Diamond(Parse(whileloop->string()), /*is_final=*/false); Screen if_screen; diff --git a/src/translator/flowchart/Flowchart.g4 b/src/translator/flowchart/Flowchart.g4 index 7d957cd..a69b124 100644 --- a/src/translator/flowchart/Flowchart.g4 +++ b/src/translator/flowchart/Flowchart.g4 @@ -1,9 +1,25 @@ grammar Flowchart; // Ignored TOKENS -WS: [ \t\n] -> skip; -COMMENT: '/*' .*? '*/' -> skip; -LINE_COMMENT: '//' .*? '\r'? '\n' -> skip; +WS: [ \t\n]+ -> channel(HIDDEN); +COMMENT: '/*' .*? '*/' -> channel(HIDDEN); +LINE_COMMENT: '//' .*? ('\r'? '\n' | EOF) -> channel(HIDDEN); + +SEMICOLON: ';'; +PL: '('; +PR: ')'; +BL: '{'; +BR: '}'; +DO: 'do'; +ELSE: 'else'; +IF: 'if'; +NOOP: 'noop'; +RETURN: 'return'; +SWITCH: 'switch'; +WHILE: 'while'; + +STRING_SIMPLE_QUOTE: '\'' ( '\\\'' | . )*? '\''; +STRING_DOUBLE_QUOTE: '"' ( '\\"' | . )*? '"'; // Program program: instruction*; @@ -18,30 +34,28 @@ instruction: noop | switchinstruction ; -noop: 'noop' ';'?; +noop: NOOP SEMICOLON?; -element: string ';'?; +element: string SEMICOLON?; string: STRING_SIMPLE_QUOTE | STRING_DOUBLE_QUOTE ; -STRING_SIMPLE_QUOTE: '\'' ( '\\\'' | . )*? '\''; -STRING_DOUBLE_QUOTE: '"' ( '\\"' | . )*? '"'; -condition: 'if' '(' string ')' instruction ( 'else' instruction )?; +condition: IF PL string PR instruction ( ELSE instruction )?; -whileloop: 'while' '(' string ')' instruction; +whileloop: WHILE PL string PR instruction; -doloop: 'do' instruction 'while' '(' string ')' ';'?; +doloop: DO instruction WHILE PL string PR SEMICOLON?; -group: '{' program '}'; +group: BL program BR; -returninstruction: 'return' instruction; +returninstruction: RETURN instruction; switchinstruction: - 'switch' '(' string ')' '{' - ( 'case' string ':' instruction)* - '}' + SWITCH PL string PR BL + ( CASE string ':' instruction)* + BR ; // vim: filetype=antlr diff --git a/src/translator/graph_planar/GraphPlanar.cpp b/src/translator/graph_planar/GraphPlanar.cpp index 7f8973d..f277aee 100644 --- a/src/translator/graph_planar/GraphPlanar.cpp +++ b/src/translator/graph_planar/GraphPlanar.cpp @@ -129,6 +129,7 @@ class GraphPlanar : public Translator { std::vector Examples() final; std::string Translate(const std::string& input, const std::string& options_string) final; + std::string Highlight(const std::string& input) final; void Read(const std::string& input); void ReadGraph(GraphPlanarParser::GraphContext* graph); @@ -511,6 +512,42 @@ void DrawnEdge::Draw(Screen& screen, GraphPlanar& graph) { screen.DrawPixel(x, bottom, L'▽'); } +std::string GraphPlanar::Highlight(const std::string& input) { + std::stringstream out; + + antlr4::ANTLRInputStream input_stream(input); + + // Lexer. + GraphPlanarLexer lexer(&input_stream); + antlr4::CommonTokenStream tokens(&lexer); + + try { + tokens.fill(); + } + catch (...) { // Ignore + } + + size_t matched = 0; + out << ""; + for(antlr4::Token* token : tokens.getTokens()) { + std::string text = token->getText(); + if (text == "") { + continue; + } + out << ""; + matched += text.size(); + out << std::move(text); + out << ""; + } + + out << input.substr(matched); + out << ""; + + return out.str(); +} + std::unique_ptr GraphPlanarTranslator() { return std::make_unique(); } diff --git a/src/translator/math/Math.cpp b/src/translator/math/Math.cpp index 11d99eb..5ef1116 100644 --- a/src/translator/math/Math.cpp +++ b/src/translator/math/Math.cpp @@ -6,9 +6,9 @@ #include #include "screen/Screen.h" #include "translator/Translator.h" +#include "translator/antlr_error_listener.h" #include "translator/math/MathLexer.h" #include "translator/math/MathParser.h" -#include "translator/antlr_error_listener.h" class Screen; @@ -602,71 +602,71 @@ std::wstring ParseFunctionMultLatex(MathParser::FunctionContext* context, Draw ParseFunctionMathBB(MathParser::FunctionContext* context, Style* style) { static const std::map known = { - {"0", "𝟘"}, // - {"1", "𝟙"}, // - {"2", "𝟚"}, // - {"3", "𝟛"}, // - {"4", "𝟜"}, // - {"5", "𝟝"}, // - {"6", "𝟞"}, // - {"7", "𝟟"}, // - {"8", "𝟠"}, // - {"9", "𝟡"}, // - {"A", "𝔸"}, // - {"B", "𝔹"}, // - {"C", "ℂ"}, // - {"D", "𝔻"}, // - {"E", "𝔼"}, // - {"F", "𝔽"}, // - {"G", "𝔾"}, // - {"H", "ℍ"}, // - {"I", "𝕀"}, // - {"J", "𝕁"}, // - {"K", "𝕂"}, // - {"L", "𝕃"}, // - {"M", "𝕄"}, // - {"N", "ℕ"}, // - {"O", "𝕆"}, // - {"P", "ℙ"}, // - {"PI", "ℿ"}, // - {"Q", "ℚ"}, // - {"R", "ℝ"}, // - {"S", "𝕊"}, // - {"T", "𝕋"}, // - {"U", "𝕌"}, // - {"V", "𝕍"}, // - {"W", "𝕎"}, // - {"X", "𝕏"}, // - {"Y", "𝕐"}, // - {"Z", "ℤ"}, // - {"a", "𝕒"}, // - {"b", "𝕓"}, // - {"c", "𝕔"}, // - {"d", "𝕕"}, // - {"e", "𝕖"}, // - {"f", "𝕗"}, // - {"g", "𝕘"}, // - {"h", "𝕙"}, // - {"i", "ⅈ"}, // - {"i", "𝕚"}, // - {"j", "𝕛"}, // - {"k", "𝕜"}, // - {"l", "𝕝"}, // - {"m", "𝕞"}, // - {"n", "𝕟"}, // - {"o", "𝕠"}, // - {"p", "𝕡"}, // - {"pi", "ℼ"}, // - {"q", "𝕢"}, // - {"r", "𝕣"}, // - {"s", "𝕤"}, // - {"t", "𝕥"}, // - {"u", "𝕦"}, // - {"v", "𝕧"}, // - {"w", "𝕨"}, // - {"x", "𝕩"}, // - {"y", "𝕪"}, // - {"z", "𝕫"}, // + {"0", "𝟘"}, // + {"1", "𝟙"}, // + {"2", "𝟚"}, // + {"3", "𝟛"}, // + {"4", "𝟜"}, // + {"5", "𝟝"}, // + {"6", "𝟞"}, // + {"7", "𝟟"}, // + {"8", "𝟠"}, // + {"9", "𝟡"}, // + {"A", "𝔸"}, // + {"B", "𝔹"}, // + {"C", "ℂ"}, // + {"D", "𝔻"}, // + {"E", "𝔼"}, // + {"F", "𝔽"}, // + {"G", "𝔾"}, // + {"H", "ℍ"}, // + {"I", "𝕀"}, // + {"J", "𝕁"}, // + {"K", "𝕂"}, // + {"L", "𝕃"}, // + {"M", "𝕄"}, // + {"N", "ℕ"}, // + {"O", "𝕆"}, // + {"P", "ℙ"}, // + {"PI", "ℿ"}, // + {"Q", "ℚ"}, // + {"R", "ℝ"}, // + {"S", "𝕊"}, // + {"T", "𝕋"}, // + {"U", "𝕌"}, // + {"V", "𝕍"}, // + {"W", "𝕎"}, // + {"X", "𝕏"}, // + {"Y", "𝕐"}, // + {"Z", "ℤ"}, // + {"a", "𝕒"}, // + {"b", "𝕓"}, // + {"c", "𝕔"}, // + {"d", "𝕕"}, // + {"e", "𝕖"}, // + {"f", "𝕗"}, // + {"g", "𝕘"}, // + {"h", "𝕙"}, // + {"i", "ⅈ"}, // + {"i", "𝕚"}, // + {"j", "𝕛"}, // + {"k", "𝕜"}, // + {"l", "𝕝"}, // + {"m", "𝕞"}, // + {"n", "𝕟"}, // + {"o", "𝕠"}, // + {"p", "𝕡"}, // + {"pi", "ℼ"}, // + {"q", "𝕢"}, // + {"r", "𝕣"}, // + {"s", "𝕤"}, // + {"t", "𝕥"}, // + {"u", "𝕦"}, // + {"v", "𝕧"}, // + {"w", "𝕨"}, // + {"x", "𝕩"}, // + {"y", "𝕪"}, // + {"z", "𝕫"}, // }; std::string name; @@ -1317,6 +1317,41 @@ class Math : public Translator { // Print th return to_string(Parse(content, &style)); } + + std::string Highlight(const std::string& input) final { + std::stringstream out; + + antlr4::ANTLRInputStream input_stream(input); + + // Lexer. + MathLexer lexer(&input_stream); + antlr4::CommonTokenStream tokens(&lexer); + + try { + tokens.fill(); + } catch (...) { // Ignore + } + + size_t matched = 0; + out << ""; + for (antlr4::Token* token : tokens.getTokens()) { + std::string text = token->getText(); + if (text == "") { + continue; + } + out << ""; + matched += text.size(); + out << std::move(text); + out << ""; + } + + out << input.substr(matched); + out << ""; + + return out.str(); + } }; std::unique_ptr MathTranslator() { diff --git a/src/translator/math/Math.g4 b/src/translator/math/Math.g4 index a87fa77..b80ffb4 100644 --- a/src/translator/math/Math.g4 +++ b/src/translator/math/Math.g4 @@ -85,7 +85,7 @@ EQ : '=' ; POW : '^' ; SUBSCRIPT: '_' ; EOL : '\r\n' | '\n' ; -WS : [ \t] + -> skip ; +WS : [ \t]+ -> channel(HIDDEN); fragment CHAR : ~[!+-<>=_^(){}[\] \t\r\n"*] | [.0123456789]; VARIABLE: CHAR+; diff --git a/src/translator/sequence/Sequence.cpp b/src/translator/sequence/Sequence.cpp index bc86ac2..9163875 100644 --- a/src/translator/sequence/Sequence.cpp +++ b/src/translator/sequence/Sequence.cpp @@ -458,13 +458,13 @@ void Sequence::AddMessageCommand( Message message; if (auto dependency_id = message_command->dependencyID()) { message.id = - std::stoi(dependency_id->number()->Number()->getSymbol()->getText()); + std::stoi(dependency_id->number()->NUMBER()->getSymbol()->getText()); } message.from = GetText(message_command->text(0)); message.to = GetText(message_command->text(1)); - if (message_command->arrow()->NormalLeftArrow()) { + if (message_command->arrow()->ARROW_LEFT()) { std::swap(message.from, message.to); } @@ -486,9 +486,9 @@ void Sequence::AddDependencyCommand( auto numbers = dependency->number(); auto comparison = dependency->comparison(); for (int i = 0; i < comparison.size(); ++i) { - int left = std::stoi(numbers[i]->Number()->getSymbol()->getText()); - int right = std::stoi(numbers[i + 1]->Number()->getSymbol()->getText()); - if (comparison[i]->More()) { + int left = std::stoi(numbers[i]->NUMBER()->getSymbol()->getText()); + int right = std::stoi(numbers[i + 1]->NUMBER()->getSymbol()->getText()); + if (comparison[i]->GREATER()) { std::swap(left, right); } actor.dependencies.insert(Dependency{left, right}); @@ -501,7 +501,7 @@ std::wstring Sequence::GetText(SequenceParser::TextContext* text) { } int Sequence::GetNumber(SequenceParser::NumberContext* number) { - return std::stoi(number->Number()->getSymbol()->getText()); + return std::stoi(number->NUMBER()->getSymbol()->getText()); } void Sequence::Layout() { @@ -699,3 +699,39 @@ std::string Sequence::Draw() { std::unique_ptr SequenceTranslator() { return std::make_unique(); } + +std::string Sequence::Highlight(const std::string& input) { + std::stringstream out; + + antlr4::ANTLRInputStream input_stream(input); + + // Lexer. + SequenceLexer lexer(&input_stream); + antlr4::CommonTokenStream tokens(&lexer); + + try { + tokens.fill(); + } + catch (...) { // Ignore + } + + size_t matched = 0; + out << ""; + for(antlr4::Token* token : tokens.getTokens()) { + std::string text = token->getText(); + if (text == "") { + continue; + } + out << ""; + matched += text.size(); + out << std::move(text); + out << ""; + } + + out << input.substr(matched); + out << ""; + + return out.str(); +} diff --git a/src/translator/sequence/Sequence.g4 b/src/translator/sequence/Sequence.g4 index b84ac4f..ba7cac7 100644 --- a/src/translator/sequence/Sequence.g4 +++ b/src/translator/sequence/Sequence.g4 @@ -2,38 +2,37 @@ grammar Sequence; // Lexer ----- -NormalRightArrow: '->'; -NormalLeftArrow: '<-'; -Comma: ':'; -Less: '<'; -More: '>'; -Colon: ','; +ARROW_RIGHT: '->'; +ARROW_LEFT: '<-'; +COMMA: ':'; +LOWER: '<'; +GREATER: '>'; +COLON: ','; EOL: '\r\n' | '\n'; -fragment Digit: [0-9]+; -Number: Digit+; +NUMBER: [0-9]+; -Space: ' ' | '\t'; -Other: .; +SPACE: ' ' | '\t'; +OTHER: .; // Parser ----- program: (command? (EOL command?)*) EOF; command: messageCommand | dependencyCommand; -messageCommand: dependencyID? text arrow text Comma text; -dependencyCommand: text Comma dependencies; +messageCommand: dependencyID? text arrow text COMMA text; +dependencyCommand: text COMMA dependencies; dependency: number (comparison number)+; dependencyID: number ')'; -dependencies: (dependency (Colon dependency)*)?; +dependencies: (dependency (COLON dependency)*)?; -text: Space* textInternal Space*; -textInternal: ~(Space|EOL) (~EOL* ~(Space|EOL))?; +text: SPACE* textInternal SPACE*; +textInternal: ~(SPACE|EOL) (~EOL* ~(SPACE|EOL))?; -number: Space* Number Space*; +number: SPACE* NUMBER SPACE*; -comparison: Less | More; +comparison: LOWER | GREATER; -arrow: NormalLeftArrow | NormalRightArrow; -// vim: filetype=antlr +arrow: ARROW_LEFT | ARROW_RIGHT; +// vim: filetype=ANTLR diff --git a/src/translator/sequence/Sequence.hpp b/src/translator/sequence/Sequence.hpp index 4734a4d..2cd789b 100644 --- a/src/translator/sequence/Sequence.hpp +++ b/src/translator/sequence/Sequence.hpp @@ -119,6 +119,7 @@ class Sequence : public Translator { std::vector Examples() final; std::string Translate(const std::string& input, const std::string& options_string) override; + std::string Highlight(const std::string& input) override; std::vector actors; std::vector messages; diff --git a/test/Flowchart/xkcd-do-you-understand-flowchart-2/output b/test/Flowchart/xkcd-do-you-understand-flowchart-2/output index 1fd0044..d3807d3 100644 --- a/test/Flowchart/xkcd-do-you-understand-flowchart-2/output +++ b/test/Flowchart/xkcd-do-you-understand-flowchart-2/output @@ -1,13 +1 @@ - ┌─────────────┐ - │Unimplemented│ - └──────┬──────┘ - ┌───────▽──────┐ - │LET'S GO DRING│ - └───────┬──────┘ - ┌────▽───┐ - │6 DRINKS│ - └────┬───┘ -┌─────────▽─────────┐ -│HEY, I SHOULD TRY │ -│INSTALLING FREEBSD!│ -└───────────────────┘ +Error \ No newline at end of file diff --git a/test/GraphPlanar/numpad/input b/test/GraphPlanar/numpad/input index c640ac5..79a4f37 100644 --- a/test/GraphPlanar/numpad/input +++ b/test/GraphPlanar/numpad/input @@ -1,7 +1,6 @@ 1 -- 2 -- 3 4 -- 5 -- 6 7 -- 8 -- 9 - 1 -- 4 -- 7 2 -- 5 -- 8 3 -- 6 -- 9