Libraryless. Click here for Pure Java version (2068L/14K/46K).
1 | !752 |
2 | |
3 | static L<S> data = toLinesFullTrim([[ |
4 | If A likes B then A will greet B. |
5 | If X then Y. |
6 | If U then V. && U. => V. |
7 | John likes Paul. |
8 | ]]); |
9 | |
10 | static L<L<S>> log; |
11 | |
12 | static S toCheck = "John will greet Paul."; |
13 | |
14 | sclass Flow { |
15 | new StringBuilder desc; |
16 | new L<Flow> subs; |
17 | |
18 | Flow sub(S desc) { |
19 | new Flow flow; |
20 | flow.append(desc); |
21 | subs.add(flow); |
22 | ret flow; |
23 | } |
24 | |
25 | void append(O o) { |
26 | desc.append(o).append("\n"); |
27 | } |
28 | |
29 | void x(O o) { append(o); } |
30 | |
31 | public S toString() { |
32 | ret str(desc) + indentx(allToStringWithLineBreaks(subs)); |
33 | } |
34 | } |
35 | |
36 | p-typewriter { |
37 | // Parse data |
38 | log = map("tok", data); |
39 | |
40 | new TreeSet<S> newData; |
41 | |
42 | // Go through all rules |
43 | new Flow flow; |
44 | for (L<S> tok : log) { |
45 | SS m = matchSingle("I => O", tok); |
46 | if (m == null) continue; |
47 | S i = m.get("I"), o = m.get("O"); |
48 | // Parse left-hand |
49 | L<S> tokI = tok(i); |
50 | L<L<S>> is = splitAtAmpersands(tokI); |
51 | flow.x("Processing LHS: " + struct(is)); |
52 | // Apply rule to input |
53 | for (SS m2 : gSatAnd(is, flow)) |
54 | newData.add(join(" ", replaceVars(tok(o), m2))); |
55 | } |
56 | |
57 | print("Lines made (\*l(newData)*/):"); |
58 | psl(asList(newData)); |
59 | printWithAsciiHeading("FLOW", flow); |
60 | } |
61 | |
62 | // null = no satisfaction |
63 | // otherwise return var map |
64 | static Iterable<SS> gSatAnd(L<L<S>> statements, Flow flow) { |
65 | flow = flow.sub("gSatAnd" + struct(statements)); |
66 | assertTrue(l(statements) >= 1); |
67 | |
68 | if (l(statements) == 1) |
69 | ret gSat(first(statements), flow); |
70 | |
71 | new L<SS> l; |
72 | for (SS map : gSat(first(statements), flow)) { |
73 | flow.x("First clause satisfied. " + struct(map)); |
74 | L<L<S>> s2 = mapReplaceVars(dropFirst(statements), map); |
75 | flow.x("Now looking for: " + struct(s2)); |
76 | for (SS map2 : gSatAnd(s2, flow)) { |
77 | flow.x("Sub gSatAnd returned: " + struct(map2)); |
78 | addIfNotEmpty(l, mergeMappings(map, map2)); |
79 | } |
80 | } |
81 | ret l; |
82 | } |
83 | |
84 | static IterableIterator<SS> gSat(L<S> pat, Flow flow) { |
85 | flow = flow.sub("gSat" + struct(pat)); |
86 | ret gMatch(pat, flow); |
87 | } |
88 | |
89 | static IterableIterator<SS> gMatch(final L<S> pat, final Flow flow) { |
90 | ret new IterableIterator<SS>() { |
91 | int i = l(log); |
92 | Iterator<SS> m; |
93 | |
94 | public bool hasNext() { |
95 | if (m != null && m.hasNext()) true; |
96 | m = null; |
97 | while (--i >= 0) { |
98 | L<SS> l = match(pat, get(log, i)); |
99 | if (nempty(l)) { |
100 | flow.x("gMatch found: " + struct(l)); |
101 | m = l.iterator(); |
102 | true; |
103 | } |
104 | } |
105 | false; |
106 | } |
107 | |
108 | public SS next() { ret m.next(); } |
109 | }; |
110 | } |
111 | |
112 | static L<L<S>> splitAtAmpersands(L<S> tok) { |
113 | new L<L<S>> l; |
114 | int iAmp; |
115 | while ((iAmp = indexOfSubList(tok, ll("&", "&"))) >= 0) { |
116 | //print("&& found at " + iAmp); |
117 | l.add(subList(tok, 0, iAmp)); |
118 | tok = subList(tok, iAmp+2); |
119 | } |
120 | l.add(tok); |
121 | ret l; |
122 | } |
123 | |
124 | static SS matchSingle(S pat, L<S> input) { |
125 | ret getSingletonOpt(match(tok(pat), input)); |
126 | } |
127 | |
128 | static SS matchSingle(S pat, S input) { |
129 | ret getSingletonOpt(match(pat, input)); |
130 | } |
131 | |
132 | static L<S> tok(S s) { |
133 | ret s == null ? null : codeTokens(nlTok(s)); |
134 | } |
135 | |
136 | static L<SS> match(S pat, S input) { |
137 | ret match(tok(pat), tok(input)); |
138 | } |
139 | |
140 | static L<SS> match(L<S> pat, L<S> input) { |
141 | Map<Int, S> vars = singleCharacterVars(pat); |
142 | new L<SS> matches; |
143 | matchImpl(pat, vars, 0, input, 0, new HashMap, matches); |
144 | ret matches; |
145 | } |
146 | |
147 | static void matchImpl(L<S> pat, Map<Int, S> vars, |
148 | int iPat, L<S> input, int iInput, SS values, |
149 | L<SS> matches) { |
150 | if (iPat >= l(pat)) { |
151 | if (iInput < l(input)) ret; // fail, too much input |
152 | //print("Match! " + struct(values)); |
153 | matches.add(cloneMap(values)); |
154 | ret; |
155 | } |
156 | if (iInput >= l(input)) ret; // out of input |
157 | S t = pat.get(iPat); |
158 | S var = vars.get(iPat); |
159 | if (var != null) { |
160 | // it's a variable, try different lengths of input as match |
161 | for (int jInput = iInput+1; jInput <= l(input); jInput++) { |
162 | S value = join(" ", subList(input, iInput, jInput)); |
163 | S oldValue = values.get(var); |
164 | if (oldValue != null && !eqic(value, oldValue)) ret; // fail, bad multi-assignment |
165 | if (oldValue == null) |
166 | values.put(var, value); |
167 | // proceed |
168 | matchImpl(pat, vars, iPat+1, input, jInput, values, matches); |
169 | // delete assignment |
170 | if (oldValue == null) values.remove(var); else values.put(var, oldValue); |
171 | } |
172 | } else { |
173 | // it's a literal |
174 | if (!eqic(t, input.get(iInput))) ret; // fail |
175 | // match, proceed |
176 | matchImpl(pat, vars, iPat+1, input, iInput+1, values, matches); |
177 | } |
178 | } |
179 | |
180 | static Map<Int, S> singleCharacterVars(L<S> tok) { |
181 | new Map<Int, S> vars; |
182 | for i over tok: { |
183 | S t = tok.get(i); |
184 | if (l(t) == 1 && isUpperCaseLetter(t.charAt(0))) |
185 | vars.put(i, t); |
186 | } |
187 | ret vars; |
188 | } |
189 | |
190 | static L<L<S>> mapReplaceVars(L<L<S>> patterns, final SS map) { |
191 | ret map(func(L<S> pat) { replaceVars(pat, map) }, patterns); |
192 | } |
193 | |
194 | static L<S> replaceVars(L<S> tok, final Map<S, S> map) { |
195 | ret flattenList(map(tok, func(S t) { or((O) tok(map.get(t)), t) })); |
196 | } |
Began life as a copy of #1005169
download show line numbers debug dex old transpilations
Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ddnzoavkxhuk, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1005173 |
Snippet name: | Rule Matching Test [dev.] |
Eternal ID of this version: | #1005173/1 |
Text MD5: | f9b0375363a7b51dfc00af59a4429c45 |
Transpilation MD5: | 4c5d2caab5b5bb4337a2cc3d9c6b8742 |
Author: | stefan |
Category: | javax / a.i. |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-11-20 17:23:37 |
Source code size: | 5090 bytes / 196 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 795 / 851 |
Referenced in: | [show references] |