Warning: session_start(): open(/var/lib/php/sessions/sess_poqo4h24e9sgfbgnma9s07ktam, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!752
static L data = toLinesFullTrim([[
If A likes B then A will greet B.
If X then Y.
If U then V. && U. => V.
John likes Paul.
]]);
static L> log;
static S toCheck = "John will greet Paul.";
sclass Flow {
new StringBuilder desc;
new L subs;
Flow sub(S desc) {
new Flow flow;
flow.append(desc);
subs.add(flow);
ret flow;
}
void append(O o) {
desc.append(o).append("\n");
}
void x(O o) { append(o); }
public S toString() {
ret str(desc) + indentx(allToStringWithLineBreaks(subs));
}
}
p-typewriter {
// Parse data
log = map("tok", data);
new TreeSet newData;
// Go through all rules
new Flow flow;
for (L tok : log) {
SS m = matchSingle("I => O", tok);
if (m == null) continue;
S i = m.get("I"), o = m.get("O");
// Parse left-hand
L tokI = tok(i);
L> is = splitAtAmpersands(tokI);
flow.x("Processing LHS: " + struct(is));
// Apply rule to input
for (SS m2 : gSatAnd(is, flow))
newData.add(join(" ", replaceVars(tok(o), m2)));
}
print("Lines made (\*l(newData)*/):");
psl(asList(newData));
printWithAsciiHeading("FLOW", flow);
}
// null = no satisfaction
// otherwise return var map
static Iterable gSatAnd(L> statements, Flow flow) {
flow = flow.sub("gSatAnd" + struct(statements));
assertTrue(l(statements) >= 1);
if (l(statements) == 1)
ret gSat(first(statements), flow);
new L l;
for (SS map : gSat(first(statements), flow)) {
flow.x("First clause satisfied. " + struct(map));
L> s2 = mapReplaceVars(dropFirst(statements), map);
flow.x("Now looking for: " + struct(s2));
for (SS map2 : gSatAnd(s2, flow)) {
flow.x("Sub gSatAnd returned: " + struct(map2));
addIfNotEmpty(l, mergeMappings(map, map2));
}
}
ret l;
}
static IterableIterator gSat(L pat, Flow flow) {
flow = flow.sub("gSat" + struct(pat));
ret gMatch(pat, flow);
}
static IterableIterator gMatch(final L pat, final Flow flow) {
ret new IterableIterator() {
int i = l(log);
Iterator m;
public bool hasNext() {
if (m != null && m.hasNext()) true;
m = null;
while (--i >= 0) {
L l = match(pat, get(log, i));
if (nempty(l)) {
flow.x("gMatch found: " + struct(l));
m = l.iterator();
true;
}
}
false;
}
public SS next() { ret m.next(); }
};
}
static L> splitAtAmpersands(L tok) {
new L> l;
int iAmp;
while ((iAmp = indexOfSubList(tok, ll("&", "&"))) >= 0) {
//print("&& found at " + iAmp);
l.add(subList(tok, 0, iAmp));
tok = subList(tok, iAmp+2);
}
l.add(tok);
ret l;
}
static SS matchSingle(S pat, L input) {
ret getSingletonOpt(match(tok(pat), input));
}
static SS matchSingle(S pat, S input) {
ret getSingletonOpt(match(pat, input));
}
static L tok(S s) {
ret s == null ? null : codeTokens(nlTok(s));
}
static L match(S pat, S input) {
ret match(tok(pat), tok(input));
}
static L match(L pat, L input) {
Map vars = singleCharacterVars(pat);
new L matches;
matchImpl(pat, vars, 0, input, 0, new HashMap, matches);
ret matches;
}
static void matchImpl(L pat, Map vars,
int iPat, L input, int iInput, SS values,
L matches) {
if (iPat >= l(pat)) {
if (iInput < l(input)) ret; // fail, too much input
//print("Match! " + struct(values));
matches.add(cloneMap(values));
ret;
}
if (iInput >= l(input)) ret; // out of input
S t = pat.get(iPat);
S var = vars.get(iPat);
if (var != null) {
// it's a variable, try different lengths of input as match
for (int jInput = iInput+1; jInput <= l(input); jInput++) {
S value = join(" ", subList(input, iInput, jInput));
S oldValue = values.get(var);
if (oldValue != null && !eqic(value, oldValue)) ret; // fail, bad multi-assignment
if (oldValue == null)
values.put(var, value);
// proceed
matchImpl(pat, vars, iPat+1, input, jInput, values, matches);
// delete assignment
if (oldValue == null) values.remove(var); else values.put(var, oldValue);
}
} else {
// it's a literal
if (!eqic(t, input.get(iInput))) ret; // fail
// match, proceed
matchImpl(pat, vars, iPat+1, input, iInput+1, values, matches);
}
}
static Map singleCharacterVars(L tok) {
new Map vars;
for i over tok: {
S t = tok.get(i);
if (l(t) == 1 && isUpperCaseLetter(t.charAt(0)))
vars.put(i, t);
}
ret vars;
}
static L> mapReplaceVars(L> patterns, final SS map) {
ret map(func(L pat) { replaceVars(pat, map) }, patterns);
}
static L replaceVars(L tok, final Map map) {
ret flattenList(map(tok, func(S t) { or((O) tok(map.get(t)), t) }));
}