!7 concept RewriteExample { S in, out; O trail; } concept Result { S in, out; O trail; RewriteExample existing; } cmodule RewriteDatabase { transient CRUD rewriteExamplesCRUD; transient CRUD resultsCRUD; transient SingleComponentPanel scpSuggestions; transient ReliableSingleThread rstMakeSuggestions = dm_rst(me(), r makeSuggestions).cancelBeforeTrigger(); transient ReliableSingleThread rstProcessInput = dm_rst(me(), r processInput).cancelBeforeTrigger(); S input; int selectedTab; switchable int maxResults = 1000; start { dbIndexingCI(RewriteExample, 'in); dbIndexingCI(Result, 'out); rewriteExamplesCRUD = CRUD(RewriteExample); resultsCRUD = CRUD(Result); } visualize { JComponent c = dm_rememberSelectedTab selectedTab(jtabs( "Rewrite Examples", centerAndSouthWithMargin( rewriteExamplesCRUD.visualize(), jCenteredSection("Suggestions", jMinHeight(100, scpSuggestions = singleComponentPanel()))), "Input", northAndCenterWithMargins( withRightAlignedButtons(dm_centeredTextFieldAsSection input(), "Make rule...", rThreadEnter makeRuleDialog), jCenteredSection("Results", resultsCRUD.visualize())) )); resultsCRUD.addSelectionDependentButton("Accept", r { acceptResult(resultsCRUD.selected()) }); resultsCRUD.addSelectionDependentButton("Use as new input", r { setField(input := resultsCRUD.selected().out) }); onTableSelectionChanged(rewriteExamplesCRUD.table(), rstMakeSuggestions); onConceptChangeByClass_notOnAllChanged RewriteExample(r { rstMakeSuggestions.trigger(); rstProcessInput.trigger(); }); dm_watchFieldAndNow input(rstProcessInput); ret c; } void makeSuggestions { RewriteExample e = rewriteExamplesCRUD.selected(), ret if null; new L buttons; S transferred = transferCurlyBracketPhrases(e.out, e.in); if (neq(transferred, e.in)) buttons.add(jbutton("Change LHS to: " + transferred, r { cset(e, in := transferred) })); Set sharedPhrases = sharedCurlyBracketPhrases(e.in, e.out); if (nempty(sharedPhrases)) { S var = firstUnusedCountingDollarVar(e.in); for (S phrase : sharedPhrases) { S in2 = jreplaceIC_literal(e.in, curly(phrase), var); S out2 = jreplaceIC_literal(e.out, curly(phrase), var); if (!hasConceptIC RewriteExample(in := in2, out := out2)) buttons.add(jbutton("Replace " + curly(phrase) + " with " + var, r { addExample(in2, out2, ll('sharedCurlyBracketPhrases, e)) })); } } setComponent(scpSuggestions, scrollableStackWithSpacing(buttons)); } void processInput { input = simplify(this.input); print("Processing input: " + input); deleteConcepts Result(); // flexMatch input with all examples for ping (RewriteExample e) { if (containsDollarVars(e.in)) for (SS map : flexMatchDollarVarsIC_all(e.in, input)) addResult(cnew Result(in := input, out := replaceVars(e.out, map), trail := ll('flexMatch, e))); } // Offer grouping last tokens LS tok = javaTokWithAllBrackets_cached(input); for (S s : tok_groupAfterNTokens_all(tok)) addResult(cnew Result(in := input, out := s)); // Offer grouping first tokens for (S s : tok_groupFirstNTokens_all(tok)) addResult(cnew Result(in := input, out := s)); } void acceptResult(Result r) { if (r == null || r.existing != null) ret; RewriteExample e = addExample(r.in, r.out, r.trail); if (e == null) ret; cset(r, existing := e); } void addResult(Result r) { cset(r, existing := conceptWhereCI RewriteExample(in := r.in, out := r.out)); if (countConcepts Result() >= maxResults) quickFail("Maximum number of results reached"); } void makeRuleDialog { JTextField tfIn = jTextField(input); JTextField tfOut = jTextField(input); showFormTitled2("Make rule", "In", tfIn, "Out", tfOut, r { RewriteExample e = addExample(getText(tfIn), getText(tfOut), 'userDialog); infoBox(e == null ? "Rule exists" : "Rule made: " + e.id); }); } S simplify(S s) { ret simpleSpacesAndTrim(s); } RewriteExample addExample(S in, S out, O trail) { ret csetAndReturn(uniqIC_returnIfNew RewriteExample(in := simplify(in), out := simplify(out)), +trail); } }