Revision: 7717 http://languagetool.svn.sourceforge.net/languagetool/?rev=7717&view=rev Author: gulp21-1 Date: 2012-07-18 11:05:58 +0000 (Wed, 18 Jul 2012) Log Message: ----------- [de] replace ICH_BIST and ER_BIST with a more powerful java rule remove DU_ERHAELST as the error is detected by the spell checker [zh] change id of WORD_REPEAT_BEGINNING_RULE so that there is no conflict
Modified Paths: -------------- trunk/JLanguageTool/src/java/org/languagetool/language/German.java trunk/JLanguageTool/src/java/org/languagetool/rules/zh/ChineseWordRepeatBeginningRule.java trunk/JLanguageTool/src/rules/de/grammar.xml Added Paths: ----------- trunk/JLanguageTool/src/java/org/languagetool/rules/de/VerbAgreementRule.java trunk/JLanguageTool/src/test/org/languagetool/rules/de/VerbAgreementRuleTest.java Modified: trunk/JLanguageTool/src/java/org/languagetool/language/German.java =================================================================== --- trunk/JLanguageTool/src/java/org/languagetool/language/German.java 2012-07-18 09:49:52 UTC (rev 7716) +++ trunk/JLanguageTool/src/java/org/languagetool/language/German.java 2012-07-18 11:05:58 UTC (rev 7717) @@ -36,6 +36,7 @@ import org.languagetool.rules.de.GermanWordRepeatBeginningRule; import org.languagetool.rules.de.GermanWordRepeatRule; import org.languagetool.rules.de.GermanWrongWordInContextRule; +import org.languagetool.rules.de.VerbAgreementRule; import org.languagetool.rules.de.WiederVsWiderRule; import org.languagetool.rules.de.WordCoherencyRule; import org.languagetool.rules.spelling.hunspell.HunspellNoSuggestionRule; @@ -126,6 +127,7 @@ CaseRule.class, CompoundRule.class, DashRule.class, + VerbAgreementRule.class, WordCoherencyRule.class, WiederVsWiderRule.class ); Added: trunk/JLanguageTool/src/java/org/languagetool/rules/de/VerbAgreementRule.java =================================================================== --- trunk/JLanguageTool/src/java/org/languagetool/rules/de/VerbAgreementRule.java (rev 0) +++ trunk/JLanguageTool/src/java/org/languagetool/rules/de/VerbAgreementRule.java 2012-07-18 11:05:58 UTC (rev 7717) @@ -0,0 +1,288 @@ +/* LanguageTool, a natural language style checker + * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +package org.languagetool.rules.de; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.ResourceBundle; +import java.util.Set; + +import org.languagetool.AnalyzedSentence; +import org.languagetool.AnalyzedToken; +import org.languagetool.AnalyzedTokenReadings; +import org.languagetool.JLanguageTool; +import org.languagetool.Language; +import org.languagetool.rules.Category; +import org.languagetool.rules.RuleMatch; +import org.languagetool.tools.StringTools; + +/** + * Simple agreement checker for German verbs and subject. Checks agreement in: + * + * <ul> + * <li>VER:1:SIN w/o ich: e.g. "Max bin da." (incorrect) [same for VER:2:SIN w/o du, VER:1:PLU w/o wir]</li> + * <li>ich + VER:[123]:.* (not VER:1:SIN): e.g. "ich bist" (incorrect) [same for du, er, wir]</li> + * </ul> + * + * TODO + * wenn nur ein mögliches finites Verb -> das nehmen (Max machen das.) + * Sie (i>1) + * bei ich/du/er/wir sofort prüfen, damit alle vorkommen geprüft werden (Ich geht jetzt nach Hause und dort gehe ich sofort unter die Dusche.) [aber: isNear] + * + * @author Markus Brenneis + */ +public class VerbAgreementRule extends GermanRule { + + private AnalyzedTokenReadings finiteVerb; + + private static final Set<String> BIN_IGNORE = new HashSet<String>(Arrays.asList( + "Abdullah", + "Isa", + "Osama", + "Turki" + )); + + private static final Set<String> QUOTATION_MARKS = new HashSet<String>(Arrays.asList( + "\"", "„" + )); + + public VerbAgreementRule(final ResourceBundle messages) { + if (messages != null) + super.setCategory(new Category(messages.getString("category_grammar"))); + } + + @Override + public String getId() { + return "DE_VERBAGREEMENT"; + } + + @Override + public String getDescription() { + return "Kongruenz von Subjekt und Prädikat (nur 1. u. 2. Pers. od. m. Personalpronomen), z.B. 'Er bist (ist)'"; + } + + @Override + public RuleMatch[] match(final AnalyzedSentence text) { + + final List<RuleMatch> ruleMatches = new ArrayList<RuleMatch>(); + AnalyzedTokenReadings[] tokens = text.getTokensWithoutWhitespace(); + + if (tokens.length < 4) // ignore one-word sentences (3 tokens: SENT_START, one word, SENT_END) + return toRuleMatchArray(ruleMatches); + + // position of the pronouns + int posIch = -1, posDu = -1, posEr = -1, posWir = -1; + // positions of verbs which do match in person and number, and do not match any other person nor number + int posVer1Sin = -1, posVer2Sin = -1, posVer1Plu = -1, posVer2Plu = -1; + // positions of verbs which do match in person and number + int posPossibleVer1Sin = -1, posPossibleVer2Sin = -1, posPossibleVer3Sin = -1, + posPossibleVer1Plu = -1, posPossibleVer2Plu = -1; + + for (int i = 1; i < tokens.length; ++i) { // ignore SENT_START + + String strToken = tokens[i].getToken().toLowerCase(); + strToken = strToken.replace("‚",""); + + if (strToken.equals("ich")) { + posIch = i; + } else if (strToken.equals("du")) { + posDu = i; + } else if (strToken.equals("er")) { + posEr = i; + } else if (strToken.equals("wir")) { + posWir = i; + } + + if (tokens[i].hasPartialPosTag("VER") + && (Character.isLowerCase(tokens[i].getToken().charAt(0)) || i == 1) ) { + if (hasUnambiguouslyPersonAndNumber(tokens[i], "1", "SIN") + && !(strToken.equals("bin") && (BIN_IGNORE.contains(tokens[i-1].getToken()) + || (tokens.length != i + 1 && tokens[i+1].getToken().startsWith("Laden")) ))) { + posVer1Sin = i; + } + else if (hasUnambiguouslyPersonAndNumber(tokens[i], "2", "SIN")) { + posVer2Sin = i; + } else if (hasUnambiguouslyPersonAndNumber(tokens[i], "1", "PLU")) { + posVer1Plu = i; + } else if (hasUnambiguouslyPersonAndNumber(tokens[i], "2", "PLU")) { + posVer2Plu = i; + } + + if (tokens[i].hasPartialPosTag(":1:SIN")) + posPossibleVer1Sin = i; + if (tokens[i].hasPartialPosTag(":2:SIN")) + posPossibleVer2Sin = i; + if (tokens[i].hasPartialPosTag(":3:SIN")) + posPossibleVer3Sin = i; + if (tokens[i].hasPartialPosTag(":1:PLU")) + posPossibleVer1Plu = i; + if (tokens[i].hasPartialPosTag(":2:PLU")) + posPossibleVer2Plu = i; + + } + + } // for each token + + // "ich", "du", and "wir" must be subject (no other interpretation possible) + // "ich", "du", "er", and "wir" must have a matching verb + + if (posVer1Sin != -1 && posIch == -1 && !isQuotationMark(tokens[posVer1Sin-1])) { // 1st pers sg verb but no "ich" + ruleMatches.add(ruleMatchWrongVerb(tokens[posVer1Sin])); + } else if (posIch > 0 && !isNear(posPossibleVer1Sin, posIch) // check whether verb next to "ich" is 1st pers sg + && (tokens[posIch].getToken().equals("ich") || tokens[posIch].getStartPos() == 0) // ignore "lyrisches Ich" etc. + && !isQuotationMark(tokens[posIch-1])) { + int plus1 = ((posIch + 1) == tokens.length) ? 0 : +1; // prevent posIch+1 segfault + if (!verbDoesMatchPersonAndNumber(tokens[posIch-1], tokens[posIch+plus1], "1", "SIN")) { + ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posIch], finiteVerb)); + } + } + + if (posVer2Sin != -1 && posDu == -1 && !isQuotationMark(tokens[posVer2Sin-1])) { + ruleMatches.add(ruleMatchWrongVerb(tokens[posVer2Sin])); + } else if (posDu > 0 && !isNear(posPossibleVer2Sin, posDu) && !isQuotationMark(tokens[posDu-1])) { + int plus1 = ((posDu + 1) == tokens.length) ? 0 : +1; + if (!verbDoesMatchPersonAndNumber(tokens[posDu-1], tokens[posDu+plus1], "2", "SIN")) { + ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posDu], finiteVerb)); + } + } + + if (posEr > 0 && !isNear(posPossibleVer3Sin, posEr) && !isQuotationMark(tokens[posEr-1])) { + int plus1 = ((posEr + 1) == tokens.length) ? 0 : +1; + if (!verbDoesMatchPersonAndNumber(tokens[posEr-1], tokens[posEr+plus1], "3", "SIN")) { + ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posEr], finiteVerb)); + } + } + + if (posVer1Plu != -1 && posWir == -1 && !isQuotationMark(tokens[posVer1Plu-1])) { + ruleMatches.add(ruleMatchWrongVerb(tokens[posVer1Plu])); + } else if (posWir > 0 && !isNear(posPossibleVer1Plu, posWir) && !isQuotationMark(tokens[posWir-1])) { + int plus1 = ((posWir + 1) == tokens.length) ? 0 : +1; + if (!verbDoesMatchPersonAndNumber(tokens[posWir-1], tokens[posWir+plus1], "1", "PLU")) { + ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posWir], finiteVerb)); + } + } + + return toRuleMatchArray(ruleMatches); + + } + + /** + * @return true if |@param a - @param b| < 5, and a != -1 + */ + + private boolean isNear(final int a, final int b) { + return ((Math.abs(a - b) < 5) && a != -1); + } + + private boolean isQuotationMark(final AnalyzedTokenReadings token) { + return QUOTATION_MARKS.contains(token.getToken()); + } + + /** + * @return true if the verb @param token (if it is a verb) matches @param person and @param number, and matches no other person/number + */ + private boolean hasUnambiguouslyPersonAndNumber(final AnalyzedTokenReadings token, final String person, final String number) { + if (token.getToken().length() == 0 + || (Character.isUpperCase(token.getToken().charAt(0)) && !(token.getStartPos() == 0) ) + || !token.hasPartialPosTag("VER")) + return false; + + for (int i = 0; i < token.getReadingsLength(); ++i) { + String postag = token.getReadings().get(i).getPOSTag(); + if (postag.contains("_END")) // ignore SENT_END and PARA_END + continue; + if (!postag.contains(":" + person + ":" + number)) + return false; + } // for each reading + + return true; + } + + /** + * @return true if @param token is a finite verb, and it is no pronoun or number + */ + private boolean isFiniteVerb(final AnalyzedTokenReadings token) { + if (token.getToken().length() == 0 + || (Character.isUpperCase(token.getToken().charAt(0)) && token.getStartPos() != 0) + || !token.hasPartialPosTag("VER") + || token.hasPartialPosTag("PRO:") + || token.hasPartialPosTag("ZAL")) + return false; + + return (token.hasPartialPosTag(":1:") || token.hasPartialPosTag(":2:") || token.hasPartialPosTag(":3:")); + } + + /** + * @return false if neither the verb @param token1 (if any) nor @param token2 match @param person and @param number, and none of them is "und" or "," + * if a finite verb is found, it is saved in finiteVerb + */ + private boolean verbDoesMatchPersonAndNumber(final AnalyzedTokenReadings token1, final AnalyzedTokenReadings token2, + final String person, final String number) { + if (token1.getToken().equals(",") || token1.getToken().equals("und") || + token2.getToken().equals(",") || token2.getToken().equals("und")) + return true; + + boolean foundFiniteVerb = false; + + if (isFiniteVerb(token1)) { + foundFiniteVerb = true; + finiteVerb = token1; + if (token1.hasPartialPosTag(":" + person + ":" + number)) { + return true; + } + } + + if (isFiniteVerb(token2)) { + foundFiniteVerb = true; + finiteVerb = token2; + if (token2.hasPartialPosTag(":" + person + ":" + number)) { + return true; + } + } + + return !foundFiniteVerb; + } + + private RuleMatch ruleMatchWrongVerb(final AnalyzedTokenReadings token) { + final String msg = "Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt und Prädikat (" + + token.getToken() + ") bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: " + + "'Max bist' statt 'Max ist')."; + return new RuleMatch(this, token.getStartPos(), token.getStartPos() + token.getToken().length(), msg); + } + + private RuleMatch ruleMatchWrongVerbSubject(final AnalyzedTokenReadings subject, final AnalyzedTokenReadings verb) { + final String msg = "Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (" + subject.getToken() + + ") und Prädikat (" + verb.getToken() + ") bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: " + + "'ich sind' statt 'ich bist')."; + if (subject.getStartPos() < verb.getStartPos()) { + return new RuleMatch(this, subject.getStartPos(), verb.getStartPos() + verb.getToken().length(), msg); + } else { + return new RuleMatch(this, verb.getStartPos(), subject.getStartPos() + subject.getToken().length(), msg); + } + } + + @Override + public void reset() { + finiteVerb = null; + } + +} Modified: trunk/JLanguageTool/src/java/org/languagetool/rules/zh/ChineseWordRepeatBeginningRule.java =================================================================== --- trunk/JLanguageTool/src/java/org/languagetool/rules/zh/ChineseWordRepeatBeginningRule.java 2012-07-18 09:49:52 UTC (rev 7716) +++ trunk/JLanguageTool/src/java/org/languagetool/rules/zh/ChineseWordRepeatBeginningRule.java 2012-07-18 11:05:58 UTC (rev 7717) @@ -24,7 +24,7 @@ @Override public String getId() { - return "WORD_REPEAT_BEGINNING_RULE"; + return "CHINESE_WORD_REPEAT_BEGINNING_RULE"; } @Override Modified: trunk/JLanguageTool/src/rules/de/grammar.xml =================================================================== --- trunk/JLanguageTool/src/rules/de/grammar.xml 2012-07-18 09:49:52 UTC (rev 7716) +++ trunk/JLanguageTool/src/rules/de/grammar.xml 2012-07-18 11:05:58 UTC (rev 7717) @@ -2237,7 +2237,7 @@ </rule> </rulegroup> <rulegroup id="DU_WUENSCHT" name="Möglicher Tippfehler: 'du wünscht (wünschst)'"> - <!-- TODO this should becovered by ICH_BIST but isn't fully. --> + <!-- TODO this should be covered by VerbAgreementRule but isn't fully. --> <rule> <pattern> <token>du</token> @@ -2261,30 +2261,6 @@ <example type="incorrect"><marker>Wünscht</marker> du dir mehr Zeit?</example> </rule> </rulegroup> - <rulegroup id="DU_ERHAELST" name="Möglicher Tippfehler: 'du erhälst (erhältst)'"> - <rule> - <pattern> - <token>du</token> - <marker> - <token>erhälst</token> - </marker> - </pattern> - <message>Meinten Sie <suggestion>erhältst</suggestion>?</message> - <example type="correct">Du <marker>erhältst</marker> als Anlage mein Testament.</example> - <example type="incorrect">Du <marker>erhälst</marker> als Anlage mein Testament.</example> - </rule> - <rule> - <pattern> - <marker> - <token>erhälst</token> - </marker> - <token>du</token> - </pattern> - <message>Meinten Sie <suggestion>erhältst</suggestion>?</message> - <example type="correct">Als Anlage <marker>erhältst</marker> Du mein Testament.</example> - <example type="incorrect">Als Anlage <marker>erhälst</marker> Du mein Testament.</example> - </rule> - </rulegroup> <rule id="HIN_UNS_WIEDER" name="Möglicher Tippfehler: 'hin uns (und) wieder/her'"> <pattern> <token>hin</token> @@ -17364,170 +17340,6 @@ <example type="correct"><marker>Das Konzept eines intelligenten Autos ist nicht neu.</marker></example> <example type="correct"><marker>Das Auto.</marker></example> </rule> - <rulegroup id="ER_BIST" name="Grammatik: Kongruenz von Subjekt und Prädikat (nur 1. u. 2. Person), z.B. 'Er bist (ist)'"> - <!-- TODO the same for 1:SIN, 2:PLU, and 3:PLU, maybe a Java-rule would be easier --> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START" skip="5"><exception scope="next" regexp="yes">[Dd]u</exception></token> - <marker> - <token postag="VER.*:2:SIN.*" postag_regexp="yes" regexp="yes" skip="-1">[a-zäüö].*<exception scope="current" postag="VER.*:2:SIN.*" postag_regexp="yes" negate_pos="yes"/><exception scope="next" regexp="yes">[Dd]u</exception></token> - </marker> - <token postag="SENT_END"></token> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt und Prädikat (\2) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'er bist' statt 'er ist').</message> - <example type="correct">Die Unterlagen <marker>solltet</marker> ihr gründlich durcharbeiten.</example> - <example type="incorrect">Die Unterlagen <marker>solltest</marker> ihr gründlich durcharbeiten.</example> -<!-- <example type="incorrect"><marker>Solltest</marker> ihr das machen?</example> TODO --> - <example type="correct">Er reagierte <marker>äußerst</marker> negativ.</example> - </rule> - </rulegroup> - <rulegroup id="ICH_BIST" name="Grammatik: Kongruenz von Subjekt (nur Personalpronomen!) und Prädikat, z.B. 'Ich bist (bin)'"> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START"></token> - <marker> - <token>Ich</token> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:1:SIN.*" postag_regexp="yes"/></token> - </marker> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\2) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'ich sind' statt 'ich bin').</message> - <example type="correct"><marker>Ich bin</marker> nett.</example> - <example type="incorrect"><marker>Ich bist</marker> nett.</example> - <example type="correct"><marker>Ich kann</marker> heute leider nicht kommen.</example> - <example type="incorrect"><marker>Ich kannst</marker> heute leider nicht kommen.</example> - <example type="correct"><marker>Ich lebe</marker>.</example> - <example type="incorrect"><marker>Ich leben</marker>.</example> - <example type="correct">Er und <marker>ich leben</marker>.</example> - </rule> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START"></token> - <token skip="1"></token> - <marker> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:1:SIN.*" postag_regexp="yes"/></token> - <token skip="-1">ich<exception scope="next">und</exception></token> - </marker> - <token postag="SENT_END"></token> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\4) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'ich sind' statt 'ich bin').</message> - <example type="correct">Nett <marker>bin ich</marker>.</example> - <example type="incorrect">Nett <marker>bist ich</marker> nicht.</example> - <example type="correct">Auch morgen <marker>lebe ich</marker>.</example> - <example type="incorrect">Auch morgen <marker>leben ich</marker>.</example> - <example type="correct">Morgen <marker>kommen ich</marker> und sie.</example> - </rule> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START"></token> - <marker> - <token>Du</token> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:2:SIN.*" postag_regexp="yes"/></token> - </marker> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\2) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'du seid' statt 'du bist').</message> - <example type="correct"><marker>Du bist</marker> nett.</example> - <example type="incorrect"><marker>Du bin</marker> nett.</example> - <example type="correct"><marker>Du kannst</marker> heute leider nicht kommen.</example> - <example type="incorrect"><marker>Du können</marker> heute leider nicht kommen.</example> - <example type="correct"><marker>Du lebst</marker>.</example> - <example type="incorrect"><marker>Du leben</marker>.</example> - <example type="correct">Er und <marker>du leben</marker>.</example> - <example type="correct"><marker>Du wünschst</marker> dir so viel.</example> - <example type="incorrect"><marker>Du wünscht</marker> dir so viel.</example> - </rule> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START" skip="2"></token> - <token skip="1"></token> - <marker> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:2:SIN.*" postag_regexp="yes"/></token> - <token skip="-1">du<exception scope="next">und</exception></token> - </marker> - <token postag="SENT_END"></token> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\4) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'du seid' statt 'du bist').</message> - <example type="correct">Nett <marker>bist du</marker>.</example> - <example type="incorrect">Nett <marker>sind du</marker>.</example> - <example type="correct">Auch morgen <marker>lebst du</marker>.</example> - <example type="incorrect">Auch morgen <marker>leben du</marker>.</example> - <example type="correct">Morgen <marker>kommen du</marker> und ich.</example> - <example type="correct"><marker>Wünschst du</marker> dir mehr Zeit?</example> - <!-- <example type="incorrect"><marker>Wünscht du</marker> dir mehr Zeit?</example> --> - </rule> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START"></token> - <marker> - <token>Er</token> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:3:SIN.*" postag_regexp="yes"/></token> - </marker> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\2) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'er sind' statt 'er ist').</message> - <example type="correct"><marker>Er ist</marker> nett.</example> - <example type="incorrect"><marker>Er bin</marker> nett.</example> - <example type="correct"><marker>Er kann</marker> heute leider nicht kommen.</example> - <example type="incorrect"><marker>Er können</marker> heute leider nicht kommen.</example> - <example type="correct"><marker>Er lebt</marker>.</example> - <example type="incorrect"><marker>Er lebst</marker>.</example> - <example type="correct"><marker>Er geht</marker> zu ihr.</example> - <example type="incorrect"><marker>Er gelangst</marker> zu ihr.</example> - <example type="correct">Sie und <marker>er leben</marker>.</example> - </rule> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START" skip="2"></token> - <token skip="1"></token> - <marker> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:3:SIN.*" postag_regexp="yes"/></token> - <token skip="-1">er<exception scope="next">und</exception></token> - </marker> - <token postag="SENT_END"></token> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\4) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'er sind' statt 'er ist').</message> - <example type="correct">Nett <marker>ist er</marker>.</example> - <example type="incorrect">Nett <marker>sind er</marker>.</example> - <example type="correct">Auch morgen <marker>lebt er</marker>.</example> - <example type="incorrect">Auch morgen <marker>leben er</marker>.</example> - <example type="correct">Morgen <marker>kommen er</marker> und ich.</example> - <example type="correct">Morgen <marker>kommen er</marker>, den ich sehr mag, und ich.</example> - <example type="correct">Welche <marker>Aufgaben er</marker> dabei tatsächlich übernehmen könnte</example> - </rule> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START"></token> - <marker> - <token>Wir</token> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:1:PLU.*" postag_regexp="yes"/></token> - </marker> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\2) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'wir ist' statt 'wir sind').</message> - <example type="correct"><marker>Wir sind</marker> nett.</example> - <example type="incorrect"><marker>Wir bin</marker> nett.</example> - <example type="correct"><marker>Wir können</marker> heute leider nicht kommen.</example> - <example type="incorrect"><marker>Wir könnt</marker> heute leider nicht kommen.</example> - <example type="correct"><marker>Wir leben</marker> noch.</example> - <example type="incorrect"><marker>Wir lebst</marker> noch.</example> - <example type="correct"><marker>Wir gelangen</marker> zu dir.</example> - <example type="incorrect"><marker>Wir gelangst</marker> zu ihr.</example> - <example type="correct">Sie lebt und <marker>wir leben</marker>.</example> - </rule> - <rule> - <pattern case_sensitive="yes"> - <token postag="SENT_START" skip="2"></token> - <token skip="1"></token> - <marker> - <token postag="VER.*:[123]:.*" postag_regexp="yes" regexp="yes">[a-zäüö].*<exception postag="VER.*:1:PLU.*" postag_regexp="yes"/></token> - <token skip="-1">wir</token> - </marker> - </pattern> - <message>Möglicherweise fehlende grammatische Übereinstimmung zwischen Subjekt (\4) und Prädikat (\3) bezüglich Person oder Numerus (Einzahl, Mehrzahl - Beispiel: 'wir ist' statt 'wir sind').</message> - <example type="correct">Nett <marker>sind wir</marker>.</example> - <example type="incorrect">Nett <marker>warst wir</marker>.</example> - <example type="correct">Auch morgen <marker>leben wir</marker> noch.</example> - <example type="incorrect">Auch morgen <marker>lebte wir</marker> noch.</example> - <example type="correct">Morgen <marker>kommen wir</marker> und sie.</example> - </rule> - </rulegroup> <rulegroup id="NACHDEM_PRAETERITUM" name="Grammatik: 'nachdem' mit Präteritum"> <rule> <pattern case_sensitive="yes"> Added: trunk/JLanguageTool/src/test/org/languagetool/rules/de/VerbAgreementRuleTest.java =================================================================== --- trunk/JLanguageTool/src/test/org/languagetool/rules/de/VerbAgreementRuleTest.java (rev 0) +++ trunk/JLanguageTool/src/test/org/languagetool/rules/de/VerbAgreementRuleTest.java 2012-07-18 11:05:58 UTC (rev 7717) @@ -0,0 +1,176 @@ +/* LanguageTool, a natural language style checker + * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +package org.languagetool.rules.de; + +import java.io.IOException; +import java.util.List; + +import junit.framework.TestCase; + +import org.languagetool.JLanguageTool; +import org.languagetool.Language; +import org.languagetool.rules.RuleMatch; + +/** + * @author Markus Brenneis + */ +public class VerbAgreementRuleTest extends TestCase { + + private VerbAgreementRule rule; + private JLanguageTool langTool; + + @Override + public void setUp() throws IOException { + rule = new VerbAgreementRule(null); + langTool = new JLanguageTool(Language.GERMAN); + } + + public void testWrongVerb() throws IOException { + // correct sentences: + assertGood("Das Wort „schreibst“ ist schön."); + assertGood("Die Jagd nach bin Laden."); + assertGood("Die Unterlagen solltet ihr gründlich durcharbeiten."); + assertGood("Er reagierte äußerst negativ."); + assertGood("Max und ich sollten das machen."); + assertGood("Osama bin Laden stammt aus Saudi-Arabien."); + assertGood("Solltet ihr das machen?"); + // incorrect sentences: + assertBad("Als Borcarbid weißt es eine hohe Härte auf."); + assertBad("Das greift auf Vorläuferinstitutionen bist auf die Zeit von 1234 zurück."); + assertBad("Die Eisenbahn dienst überwiegend dem Güterverkehr."); + assertBad("Die Unterlagen solltest ihr gründlich durcharbeiten."); + assertBad("Peter bin nett."); + assertBad("Solltest ihr das machen?", "Subjekt und Prädikat (Solltest)"); + assertBad("Weiter befindest sich im Osten die Gemeinde Dorf."); + } + + public void testWrongVerbSubject() throws IOException { + // correct sentences: + assertGood("Auch morgen lebe ich."); + assertGood("Auch morgen leben wir noch."); + assertGood("Auch morgen lebst du."); + assertGood("Auch morgen lebt er."); + assertGood("Auch wenn du leben möchtest."); + assertGood("auf der er sieben Jahre blieb."); + assertGood("Das absolute Ich ist nicht mit dem individuellen Geist zu verwechseln."); + assertGood("Das Ich ist keine Einbildung"); + assertGood("Das lyrische Ich ist verzweifelt."); + assertGood("Den Park, von dem er äußerst genaue Karten zeichnete."); + assertGood("Der Vorfall, bei dem er einen Teil seines Vermögens verloren hat, ist lange vorbei."); + assertGood("Diese Lösung wurde in der 64'er beschrieben, kam jedoch nie."); + assertGood("Die Theorie, mit der ich arbeiten konnte."); +// assertGood("Die Zeitschrift film-dienst."); TODO + assertGood("Du bist nett."); + assertGood("Du kannst heute leider nicht kommen."); + assertGood("Du lebst."); + assertGood("Du wünschst dir so viel."); + assertGood("Er geht zu ihr."); + assertGood("Er ist nett."); + assertGood("Er kann heute leider nicht kommen."); + assertGood("Er lebt."); + assertGood("Er wisse nicht, ob er lachen oder weinen solle."); + assertGood("Er und du leben."); + assertGood("Er und ich leben."); + assertGood("Falls er bestehen sollte, gehen sie weg."); +// assertGood("Fest wie unsere Eichen halten allezeit wir stand, wenn Stürme brausen übers Land."); // TODO (remembers "brausen", forgets about "halten") + assertGood("Heere, des Gottes der Schlachtreihen Israels, den du verhöhnt hast."); + assertGood("Ich bin"); + assertGood("Ich bin Frankreich!"); + assertGood("Ich bin froh, dass ich arbeiten kann."); + assertGood("Ich bin nett."); + assertGood("‚ich bin tot‘"); // TODO 1st token is "‚ich" ? + assertGood("Ich kann heute leider nicht kommen."); + assertGood("Ich lebe."); + assertGood("Lebst du?"); + assertGood("Morgen kommen du und ich."); + assertGood("Morgen kommen er, den ich sehr mag, und ich."); + assertGood("Morgen kommen er und ich."); + assertGood("Morgen kommen ich und sie."); + assertGood("Morgen kommen wir und sie."); + assertGood("nachdem er erfahren hatte"); + assertGood("Nett bin ich."); + assertGood("Nett bist du."); + assertGood("Nett ist er."); + assertGood("Nett sind wir."); + assertGood("Sie lebt und wir leben."); + assertGood("Sie und er leben."); + assertGood("Sind ich und Peter nicht nette Kinder?"); + assertGood("Sodass ich sagen möchte, dass unsere schönen Erinnerungen gut sind."); + assertGood("Wann ich meinen letzten Film drehen werde, ist unbekannt."); + assertGood("Was ich tun muss."); + assertGood("Welche Aufgaben er dabei tatsächlich übernehmen könnte"); + assertGood("wie er beschaffen war"); + assertGood("Wir gelangen zu dir."); + assertGood("Wir können heute leider nicht kommen."); + assertGood("Wir leben noch."); + assertGood("Wir sind nett."); + assertGood("Wobei wir benutzt haben, dass der Satz gilt."); + assertGood("Wünschst du dir mehr Zeit?"); + assertGood("Wyrjtjbst du?"); // make sure that "UNKNOWN" is handled correctly + // incorrect sentences: + assertBad("Auch morgen leben du."); + assertBad("Auch morgen leben du"); // do not segfault because "du" is the last token + assertBad("Auch morgen leben er."); + assertBad("Auch morgen leben ich."); + assertBad("Auch morgen lebte wir noch."); + assertBad2("Du bin nett."); // TODO 2 errors + assertBad("Du können heute leider nicht kommen."); + assertBad("Du leben."); + assertBad("Du wünscht dir so viel."); + assertBad2("Er bin nett."); + assertBad2("Er gelangst zu ihr."); + assertBad("Er können heute leider nicht kommen.", "Subjekt (Er) und Prädikat (können)"); + assertBad2("Er lebst."); + assertBad2("Ich bist nett."); +// assertBad("Ich geht jetzt nach Hause und dort gehe ich sofort unter die Dusche."); TODO + assertBad2("Ich kannst heute leider nicht kommen."); + assertBad("Ich leben."); + assertBad("Lebe du?"); +// assertBad("Leben du?"); // TODO "Leben" not tagged as verb + assertBad2("Nett bist ich nicht."); + assertBad("Nett sind du."); + assertBad("Nett sind er."); + assertBad2("Nett warst wir."); + assertBad2("Wir bin nett."); + assertBad2("Wir gelangst zu ihr."); + assertBad("Wir könnt heute leider nicht kommen."); + assertBad2("Wir lebst noch."); + assertBad("Wünscht du dir mehr Zeit?", "Subjekt (du) und Prädikat (Wünscht)"); + } + + private void assertGood(String s) throws IOException { + assertEquals(0, rule.match(langTool.getAnalyzedSentence(s)).length); + } + + private void assertBad(String s) throws IOException { + assertEquals(1, rule.match(langTool.getAnalyzedSentence(s)).length); + } + + private void assertBad2(String s) throws IOException { + assertEquals(2, rule.match(langTool.getAnalyzedSentence(s)).length); + } + + private void assertBad(String s, String expectedErrorSubstring) throws IOException { + assertEquals(1, rule.match(langTool.getAnalyzedSentence(s)).length); + final String errorMessage = rule.match(langTool.getAnalyzedSentence(s))[0].getMessage(); + assertTrue("Got error '" + errorMessage + "', expected substring '" + expectedErrorSubstring + "'", + errorMessage.contains(expectedErrorSubstring)); + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ Languagetool-cvs mailing list Languagetool-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/languagetool-cvs