!752 static PersistentMap map; static new HashSet joiners; static PersistentMap splitters; p { map = new PersistentMap("map"); splitters = new PersistentMap("splitters"); load("joiners"); } static S dialog(S snl, S line) { new Map m; Lisp input = snlToTree(line); if (snlMatch("A < says < i < love < *", input, m)) ret "oh < that < is < nice"; if (snlMatch("A < says < i < hate < *", input, m)) ret snlApply("? < why < do < you < hate < *", m); ret line; } synchronized static S answer(S s) { new Matches m; print("1002700 user=" + getUserName() + " attn=" + attn() + ", dedicated=" + dedicated()); if (!attn()) ret null; if "are we dedicated" ret yn(dedicated()); if "add joiner * *" { S j = preSimplify(m.unq(0) + " " + m.unq(1)); if (joiners.contains(j)) ret format("Joiner * exists", j); joiners.add(j); save("joiners"); ret format("OK, joiner * added", j); } if "add splitter * = * *" { S a = preSimplify(m.unq(0)); S b = preSimplify(m.unq(1) + " " + m.unq(2)); S old = splitters.get(a); if (eq(old, b)) ret format("Splitter * => * exists", a, b); splitters.put(a, b); ret format("OK, splitter * => * added" + (old != null ? " (old: " + structure(old) + ")" : ""), a, b); } if (!dedicated()) ret null; exceptionToUser { /*if (isSNL(s)) ret "SNL";*/ s = preSimplify(s); S snl = map.get(s); S snlSource = "map"; if (snl == null) { snlSource = "naive"; snl = naiveSNL(s); } print("1002700: got snl"); S user = getUserName(); if (user == null) user = master() ? "master" : "user"; //user = user.replaceAll("[0-9]", ""); S line = snlSimplifyBrackets(user + " < says < [" + snl + "]"); print("1002700: calling dialog, line = " + line + ", user=" + user + ", snl=" + snl); S answer = dialog(snl, line); print("1002700: answer=" + answer); ret answer; } } //static L keepPunctuation = litlist("*", "<", ">", "[", "]", "?", "!", ":", "@"); static L tokensForSNL(S s) { L tok = nlTok(s); //ret codeTokensOnly(dropPunctuationExcept(tok, keepPunctuation)); ret codeTokensOnly(tok); } static synchronized S naiveSNL(S s) { print("Input: " + s); s = preSimplify(s); L l = tokensForSNL(s); print("Tokens: " + structure(l)); processJoiners(l); processSplitters(l); addArrows(l); ret join(" ", l); } // just a preprocessing for NL (does not generate SNL) static S preSimplify(S s) { ret join(" ", codeTokensOnly(/*wordTokensToLowerCase*/(nlTok(s)))); } static void processJoiners(L l) { for (int i = 0; i < l(l)-1; i++) { S x = l.get(i) + " " + l.get(i+1); if (joiners.contains(x)) { l.set(i, x); l.remove(i+1); --i; } } } static void processSplitters(L l) { for (int i = 0; i < l(l); i++) { S x = splitters.get(l.get(i)); if (x != null) { L tokens = tokensForSNL(x); l.remove(i); l.addAll(i, tokens); i += l(tokens)-1; } } } static void addArrows(L l) { for (int i = 0; i < l(l)-1; i++) { if (isWord(l.get(i)) && isWord(l.get(i+1))) l.add(++i, "<"); } } static boolean isWord(S s) { if (empty(s)) ret false; if (isQuoted(s)) ret true; char c = s.charAt(0); ret Character.isLetter(c) || c == '\''; } static boolean isSNL(S s) { L tok = javaTok(s); ret tok.contains("<") || tok.contains("["); } static S snlSimplifyBrackets(S s) { ret snlFromTree(snlToTree(s)); }