// adapters are immutable! (plus returns a modified clone) abstract sclass Adapter { abstract bool canMatch(S in, S out); Adapter plus(S in, S out) { ret this; } S get(S in) { ret in; } double size() { ret 0; } } abstract sclass GenericAdapter { void modify(OccTree2 node) {} } // node in flight (+ optional adapter) sclass InFlight { OccTree2 node; Adapter adapter; *(OccTree2 *node) {} *(OccTree2 *node, Adapter *adapter) {} E adapted() { // TODO: security when rewriting states ret adapter == null ? node.e : new E(adapter.get(node.e.text()), node.e.type()); } } sclass LooseBot { sbool debug, repeat = true; OccTree2 tree; new L<InFlight> nodes; new L<L> rewindStack; O newAdapter; O grabber; // func(S -> E) GenericAdapter genericAdapter; // WordAdapter now default *(OccTree2 tree) { this(tree, func { new WordAdapter }); } // main constructor *(OccTree2 *tree, O *newAdapter) { expandEllipsis(tree); } *(S theme) { this(makeOccTree(theme)); } *(S theme, O newAdapter) { this(makeOccTree(theme), newAdapter); } Adapter makeAdapter() { ret newAdapter == null ? null : (Adapter) call(newAdapter); } void take(E in) { remember(); // try starting over from beginning of tree too if (repeat) setAdd(nodes, new InFlight(tree, makeAdapter())); new L<InFlight> l; // try grabber if (grabber != null && in.q()) try { E grabbed = cast callFunction(grabber, in.text()); if (grabbed != null) { if (debug) print("Grabber worked! " + in.text() + " => " + grabbed); // make a mini tree with Q + A so it is matched in // next call to getSingleOutput() OccTree2 node = new OccTree2(in); node.next.add(new OccTree2(grabbed)); l.add(new InFlight(node)); } else if (debug) print("Grabber didnt't return anything. " + in.text()); } catch e { if (debug) printStackTrace(e); } for (InFlight flight : nodes) for (OccTree2 n : flight.node.next) { if (genericAdapter != null) genericAdapter.modify(n); if (eq(n.e.type(), in.type()) && (flight.adapter != null ? flight.adapter.canMatch(n.e.text(), in.text()) : matchE(n.e, in))) { l.add(new InFlight(n, flight.adapter == null ? null : flight.adapter.plus(n.e.text(), in.text()))); } } nodes = l; } L<E> possibleNextInput() { new HashSet<E> l; if (repeat) l.add(tree.e); L<InFlight> ns = cloneList(nodes); if (repeat) setAdd(ns, new InFlight(tree, makeAdapter())); for (InFlight flight : ns) for (OccTree2 n : flight.node.next) l.add(new InFlight(n, flight.adapter).adapted()); ret asList(l); } void remember() { if (rewindStack != null) rewindStack.add(cloneList(nodes)); } E getSingleOutput() { remember(); new L<InFlight> l; for (InFlight flight : nodes) for (OccTree2 n : flight.node.next) if (n.e.a() || isCommand(n.e)) l.add(new InFlight(n, flight.adapter)); if (empty(l)) { rewind(); null; } nodes = l; ret first(nodes).adapted(); } void rewind() { nodes = popLast(rewindStack); } bool isCommand(E e) { ret e.state() && matchStart("bot", e.state); } void noRewind() { rewindStack = null; } bool matchE(E a, E b) { // standard NL matching ret eq(a.type(), b.type()) && match(a.text(), b.text()); } S nodesToString(L<InFlight> nodes) { new L<S> l; l.add(n(l(nodes), "node")); for (InFlight flight : nodes) { l.add(str(flight.node.e)); if (flight.adapter != null) l.add(" " + flight.adapter); } ret rtrim(fromLines(l)); } S thoughts() { new L<S> l; l.add("Expecting input:\n"); for (E e : possibleNextInput()) if (e != null) l.add(" " + e); l.add(""); l.add(nodesToString(nodes)); if (rewindStack != null) { l.add("\nHistory\n"); for (L<InFlight> nodes : reversedList(rewindStack)) l.add(indent(nodesToString(nodes))); } ret fromLines(l); } LooseBot debugOn() { debug = true; ret this; } } sclass WordAdapter extends Adapter { new Map<S, S> wordMap; L<S> tok(S s) { ret nlTok2(dropPunctuation2(s)); } bool canMatch(S in, S out) { L<S> t1 = tok(in), t2 = tok(out); ret l(t1) == l(t2); } Adapter plus(S in, S out) { L<S> t1 = tok(in), t2 = tok(out); if (l(t1) != l(t2)) ret this; WordAdapter a = cast nuObject(getClass()); a.wordMap = cloneMap(wordMap); for (int i = 1; i < l(t1); i += 2) { S w1 = t1.get(i), w2 = t2.get(i); if (!eqic(w1, w2)) // just overwrite - be flexible! a.wordMap.put(w1.toLowerCase(), w2.toLowerCase()); } ret a; } S get(S s) { L<S> tok = nlTok2(s); for (int i = 1; i < l(tok); i += 2) { S w = lookupToken(tok.get(i)); if (nempty(w)) tok.set(i, w); } ret join(tok); } S lookupToken(S s) { ret wordMap.get(s.toLowerCase()); } double size() { ret l(wordMap); } public S toString() { ret structure(wordMap); } } sclass WordAdapter2 extends WordAdapter { new Map<S, S> wordMap; L<S> tok(S s) { ret nlTok2(s); } }
Began life as a copy of #1003413
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1003575 |
Snippet name: | LooseBot v6 (with generic adapters) |
Eternal ID of this version: | #1003575/1 |
Text MD5: | 0174bb8b912c2c411b624bfcc5bc9b0c |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-07-20 00:54:32 |
Source code size: | 5649 bytes / 229 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 565 / 528 |
Referenced in: | [show references] |