sclass NLLogicChecker_v2 { S input; new L facts; StringMatcher matcher = ai_standardMatcher(); new L posted; new ThreadLocal checkingRule; VF2 onChecking; // first arg: IfThen or Exp VF3 onhecked; // first arg: IfThen or Exp, last arg: Bool or Throwable sclass Matching { new LinkedHashMap matches; // var -> match new L output; bool verbose; } bool checkRule(IfThen rule, Matching m) { if (rule == null) false; ret check(e, m, func -> Bool { checkRule_impl(e, m) }); } bool checkRule_impl(IfThen rule, Matching m) { 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; } A check(O o, Matching m, F0 f) { callF(onChecking, e, m); try { A result = callF(f); callF(onChecked, e, m, result); ret result; } catch _e { callF(onChecked, e, m, _e); throw rethrow(_e); } } final bool checkExpression(Exp e, Matching m) { ret check(e, m, func -> Bool { checkExpression_impl(e, m) }); } bool checkExpression_impl(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; }; } }