!7 cmodule SmartHomeParsing > DynPrintLog { switchable S text = [[ Die Haustür führt in das Zimmer Flur. Von da aus kommt man in den Essbereich des Zimmers Wohnzimmer. Vom Flur kommt man (auch) in das Zimmer GästeWC. Das Wohnzimmer hat auch einen Wohnbereich. Vom Wohnzimmer gelangt man in das Zimmer Küche und auf die Außenfläche Terrasse. Eine Treppe führt vom Wohnzimmer nach oben in das Zimmer Flur im ersten Stock. Vom Flur im ersten Stock kommt man in das Zimmer Badzimmer und in das Zimmer Kinderzimmer eins und in das Zimmer Kinderzimmer zwei und in das Kinderzimmer drei. Das Zimmer Flur im ersten Stock hat eine Treppe nach oben in den zweiten Stock zum Zimmer Elternschlafzimmer. Eine Treppe führt vom Wohnzimmer nach unten in das Zimmer Vorkeller. Vom Vorkeller kommt man in das Zimmer Waschküche und in das Zimmer Kombüse und in das Zimmer Hauptkeller. Das Zimmer Hauptkeller hat einen Bereich Heizungsanlage. Der Durchgang zwischen Wohnzimmer und Küche hat keine Tür. Die Tür im Elternschlafzimmer geht nach innen auf. Die Tür (im Wohnzimmer) zur [Außenfläche] Terrasse geht nach Innen auf. ]]; transient S rules = [[ "Ein/eine/der/die/das führt (nach/in/hin zu/ins) " => satz => $1 leads to $2 "Ein/eine/der/die/das führt von/vom (nach/in/hin zu/ins) " => satz => $1 leads from $2 to $3 "Ein/eine/der/die/das führt von/vom nach (in/hin zu/ins) " => satz => $1 leads from $2 to $3 to $4 "der/die/dem/das/den " => nomen => the $1 "der/die/dem/das/den des/der " => nomen => $1 of $2 " in/im " => ding => $1 in $2 "erster/erste/ersten " => nomen => first $1 "zimmer " => zimmer => room $1 zimmer => ort ding => nomen ort => nomen bereich => ort "auch " => nomen => also $1 "ein/eine/einen/einem " => nomen => a $1 "kein/keine/keinen/keinem " => nomen => no $1 "bereich " => bereich => area $1 "der/... zwischen und " => ding => the $1 between $2 and $3 " geht nach auf" => satz => $1 opens to the $2 " und " => nomen => $1 and $2 "vom/... kommt/gelangt man in/nach/... " => satz => $1 connects to $2 "von da aus kommt/gelangt man in/nach/... " => satz => last mentioned place connects to $1 " hat " => satz => $1 has $2 " hat einen Bereich " => satz => $1 has an area $2 ]]; transient S simpleTranslations = [[ Haustür => main door Wohnzimmer => living room Treppe => set of stairs Tür => door Flur => hallway innen => inside aussen => outside Küche => kitchen Durchgang => passage ]]; LS sentences; LS translations, translations2; L otherProductions; transient int recursionLevels = 10; srecord Production(LS tok, S outClass, S rewritten) {} start-thread { setField(sentences := sentences(text)); new L productions; for (LS l : lambdaMap splitAtDoubleArrow(tlft(rules))) { continue unless isBetween(l(l), 2, 3); S lhs = first(l), rhs = second(l), rewritten = third(l); continue unless isQuoted(lhs); LS tok = javaTokWithAllPlusAngleBrackets(replaceWithNothing("/...", unquote(lhs))); tok = tok_combineSpacelessSlashCombos(tok); tok = mapCodeTokens tok_deRoundBracket(tok); //printStruct(codeTokens(tok)); //print(patternToRule(new ProbabilisticParser1, tok)); productions.add(new Production(tok, rhs, rewritten)); } new LS translations; for (S sentence : sentences) { print(sentence); ProbabilisticParser1.State s = parserForInputAndProductions(javaTok(sentence), objectsWhereIC(productions, outClass := "satz")).bestDoneState(); S translated = getTranslation(s); addIfNempty(translations, translated); printIfNempty(" => ", translated); } setField(+translations); printWithAsciiHeading("Translated", lines(translations)); printAsciiHeading("Just the top-level patterns"); print(mapToLines(translations, s -> jreplace(s, "", "*"))); printAsciiHeading("Let's translate some more"); setField(otherProductions := objectsWhereNotIC(productions, outClass := "satz")); LS translations2 = map(translations, line -> translateQuotedParts(line, recursionLevels)); translations2 = lambdaMap recursiveUnquoteStartingAtLevel2(translations2); SS map = parseDoubleArrowMapCI(simpleTranslations); translations2 = map(line -> join(translatePhrases(javaTokNoQuotes(line), map)), translations2); setField(+translations2); pnl(translations2); } // also parses ProbabilisticParser1 parserForInputAndProductions(LS tok, Cl productions) { new ProbabilisticParser1 parser; //parser.verbose = parser.pm.verbose = true; //parser.pm.cutoffPercentage = 10; for (Production p : productions) parser.addState(tok, patternToRule(parser, p.tok)).userObject = p; parser.pm.think(); ret parser; } BasicLogicRule patternToRule(ProbabilisticParser1 parser, LS tok) { ret BasicLogicRule( makeAnd(listPlus( mapWithIndex(tok, (i, t) -> even(i) || eqic(t, "") ? parser.new Filler : isAngleBracketed(t) ? set(parser.new Any, minTokensToConsume := 1) : containsSlash(t) ? parser.new ConsumeOneOfTokens(asCISet(splitAtSlash(t))) : parser.new ConsumeToken(t)), parser.new EndOfInput)), formatFrag("parsed " + join(tok))); } S getTranslation(ProbabilisticParser1.State state) { if (state == null) null; Production prod = cast state.userObject; Matches m = state.parser().stateToMatches(state); ret expandDollarRefsToMatches_alwaysQuote(prod.rewritten, m); } S translateQuotedParts(S line, int recursionLimit) { LS tok = javaTok(line); for (int i : indicesOfQuoted(tok)) { S x = unquote(tok.get(i)); ProbabilisticParser1.State s = parserForInputAndProductions(javaTok(x), otherProductions).bestDoneState(); //printVars(+x, +s); if (s != null && s.probability >= 80) { S y = getTranslation(s); //printVars(+x, +y, probability := s.probability); if (recursionLimit > 0) { S yy = y; y = translateQuotedParts(y, recursionLimit-1); //if (neq(y, yy)) printVars(+yy, +y); } tok.set(i, quote(y)); } } ret join(tok); } }