!747 !multi-line strings m { static S input = [[ // Dogmas A "clock time" consists of "minutes" and "seconds". "Minutes" is a number between 0 and 99. "Seconds" is a number between 0 and 59. A "clock time" is usually written in the format "Minutes:Seconds". // Questions What are the minutes in the "clock time" "12:35"? What are the seconds in the "clock time" "05:12"? ]]; !include #2000515 // unquote !include #1000709 // formatSnippetID static class Struct { new L components; S format; Map parse(S s) { L tok = nlTok(s); L form = nlTok(format); if (l(tok) != l(form)) ret null; new Map map; for (int i = 1; i < l(form); i += 2) { String f = form.get(i), t = tok.get(i); if (components.contains(simplifyName(f))) { map.put(simplifyName(f), t); } else if (!eq(f, t)) ret null; } ret map; } } static class Number { int min, max; boolean checkString(S s) { int i = parseInt(s); ret i >= min && i <= max; } } static new Map concepts; p { for (S line : toLinesFullTrim(input)) print(answer(line)); } static S answer(S line) { L tok = nlTok(line); if (l(tok) == 1) ret "..."; simplify(tok); S s = join(tok); print(" " + s); new Matches m; // Dogmas if (match3("a * consists of * and *", s, m)) { S name = simplifyName(m.unq(0)); S a = simplifyName(m.unq(1)); S b = simplifyName(m.unq(2)); new Struct st; st.components.addAll(litlist(a, b)); concepts.put(name, st); ret "OK. " + name; } if (match3("* is a number between * and *", s, m)) { new Number n; n.min = parseInt(m.get(1)); n.max = parseInt(m.get(2)); S name = simplifyName(m.unq(0)); concepts.put(name, n); ret "OK. " + name; } if (match3("A * is written in the format *", s, m)) { S name = simplifyName(m.unq(0)); S format = m.unq(1); O concept = concepts.get(name); setOpt(concept, "format", format); ret "OK."; } // Questions if (match3("What are the * in the * *?", s, m)) { S component = simplifyName(m.unq(0)); S name = simplifyName(m.unq(1)); S pattern = m.unq(2); O concept = concepts.get(name); Map instance = (Map) call(concept, "parse", pattern); ret structureOrText(instance.get(component)); } ret "huh?"; } static S simplifyName(S s) { ret join(" ", codeTokensOnly(tokensToLowerCase(nlTok(s)))); } static void simplify(L tok) { for (int i = 1; i < l(tok); ) if (equalsIgnoreCase(tok.get(i), "usually")) { removeToken(tok, i); } else i += 2; } }