sclass NLLogicChecker_v2 { S input; new L facts; StringMatcher matcher = new NLStringMatcher_noVars; new L posted; new ThreadLocal checkingRule; sclass Matching { new LinkedHashMap matches; // var -> match new L output; bool verbose; } bool checkRule(IfThen rule, Matching m) { if (rule == null) false; temp tempSetThreadLocal(checkingRule, rule); if (!checkExpression(rule.in, m)) false; print("Rewriting output: " + sfu(rule.out)); m.output.add(apply(rule.out, m)); true; } Exp apply(Exp e, Matching m) { ret apply(e, m.matches); } Exp apply(Exp e, SS m) { if (e == null) null; if (e cast And) ret And(apply(e.a, m), apply(e.b, m)); if (e cast ExpNot) ret ExpNot(apply(e.a, m)); if (e cast Func) ret Func(e.name, apply(e.arg, m)); if (e cast Sentence) ret Sentence(javaTok(matcher.apply(e.text(), m))); if (e cast Sentence2) ret Sentence2(matcher.apply(e.text(), m)); ret e; } bool checkExpression(Exp e, Matching m) { if (e cast And) ret checkExpression(e.a, m) && checkExpression(e.b, m); if (e cast ExpNot) { temp tempBackupMatches(m); ret !checkExpression(e.a, m); } if (e cast Func) { if (eq(e.name, "input")) { S pat = nlLogic_text(e.arg); L tok = javaTokPlusBrackets2(pat); for (S pat2 : splitAtTokens(tok, ll("|"))) { bool result = matcher.match(pat2, input, m.matches); if (m.verbose) print("matched " + sfu(e) + " with " + quote(input) + " & " + sfu(m.matches) + " => " + result); if (result) true; } } else if (eq(e.name, "fact")) { S pat = nlLogic_text(e.arg); for (S fact : facts) bool result = matcher.match(pat, fact, m.matches); if (m.verbose) print("matched " + sfu(e) + " with " + quote(fact) + " & " + sfu(m.matches) + " => " + result); if (result) true; } } false; } AutoCloseable tempBackupMatches(final Matching m) { final LinkedHashMap oldMatches = (LinkedHashMap) cloneMap(m.matches); ret autocloseable { m.matches = oldMatches; }; } }