in languagetool-language-modules/de/src/main/java/org/languagetool/rules/de/VerbAgreementRule.java [677:826]
private List<RuleMatch> match(AnalyzedSentence sentence, int pos, AnalyzedSentence wholeSentence) {
AnalyzedTokenReadings finiteVerb = null;
List<RuleMatch> ruleMatches = new ArrayList<>();
AnalyzedTokenReadings[] tokens = getSentenceWithImmunization(sentence).getTokensWithoutWhitespace();
if (tokens.length < 4) { // ignore one-word sentences (3 tokens: SENT_START, one word, SENT_END)
return ruleMatches;
}
// position of the pronouns:
int posIch = -1;
int posDu = -1;
int posEr = -1;
int posWir = -1;
// positions of verbs which do match in person and number, and do not match any other person nor number:
int posVer1Sin = -1;
int posVer2Sin = -1;
int posVer1Plu = -1;
/*int posVer2Plu = -1;*/
// positions of verbs which do match in person and number:
int posPossibleVer1Sin = -1;
int posPossibleVer2Sin = -1;
int posPossibleVer3Sin = -1;
int posPossibleVer1Plu = -1;
/*int posPossibleVer2Plu = -1;*/
for (int i = 1; i < tokens.length; ++i) { // ignore SENT_START
String strToken = tokens[i].getToken().toLowerCase();
strToken = COMMA.matcher(strToken).replaceAll("");
switch (strToken) {
case "ich":
posIch = i;
break;
case "du":
posDu = i;
break;
case "er":
posEr = i;
break;
case "wir":
posWir = i;
break;
}
if (tokens[i].hasPartialPosTag("VER")
&& (Character.isLowerCase(tokens[i].getToken().charAt(0)) || i == 1 || isQuotationMark(tokens[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") && !"Probst".equals(tokens[i].getToken())) {
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"
if (!tokens[posVer1Sin].isImmunized()) {
ruleMatches.add(ruleMatchWrongVerb(tokens[posVer1Sin], pos, wholeSentence));
}
} 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() <= 1 ||
(tokens[posIch].getToken().equals("Ich") && posIch >= 2 && tokens[posIch-2].getToken().equals(":")) ||
(tokens[posIch].getToken().equals("Ich") && posIch >= 1 && tokens[posIch-1].getToken().equals(":"))) // ignore "lyrisches Ich" etc.
&& (!isQuotationMark(tokens[posIch-1]) || posIch < 3 || (posIch > 1 && tokens[posIch-2].getToken().equals(":")))) {
int plus1 = ((posIch + 1) == tokens.length) ? 0 : +1; // prevent posIch+1 segfault
BooleanAndFiniteVerb check = verbDoesMatchPersonAndNumber(tokens[posIch - 1], tokens[posIch + plus1], "1", "SIN", finiteVerb);
if (!check.verbDoesMatchPersonAndNumber && !nextButOneIsModal(tokens, posIch) && !"äußerst".equals(check.finiteVerb.getToken())) {
if (!tokens[posIch].isImmunized()) {
ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posIch], check.finiteVerb, "1:SIN", pos, wholeSentence));
}
}
}
if (posVer2Sin != -1 && posDu == -1 && !isQuotationMark(tokens[posVer2Sin-1])) {
if (!tokens[posVer2Sin].isImmunized()) {
ruleMatches.add(ruleMatchWrongVerb(tokens[posVer2Sin], pos, wholeSentence));
}
} else if (posDu > 0 && !isNear(posPossibleVer2Sin, posDu)
&&(!isQuotationMark(tokens[posDu-1]) || posDu < 3 || (posDu > 1 && tokens[posDu-2].getToken().equals(":")))) {
int plus1 = ((posDu + 1) == tokens.length) ? 0 : +1;
BooleanAndFiniteVerb check = verbDoesMatchPersonAndNumber(tokens[posDu - 1], tokens[posDu + plus1], "2", "SIN", finiteVerb);
if (!check.verbDoesMatchPersonAndNumber &&
!tokens[posDu+plus1].hasPosTagStartingWith("VER:1:SIN:KJ2") && // "Wenn ich du wäre"
!(tokens[posDu+plus1].hasPosTagStartingWith("ADJ:") && !tokens[posDu+plus1].hasPosTag("ADJ:PRD:GRU"))&& // "dass du billige Klamotten..."
!tokens[posDu-1].hasPosTagStartingWith("VER:1:SIN:KJ2") &&
!nextButOneIsModal(tokens, posDu) &&
!tokens[posDu].isImmunized()
) {
ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posDu], check.finiteVerb, "2:SIN", pos, wholeSentence));
}
}
if (posEr > 0 && !isNear(posPossibleVer3Sin, posEr)
&& (!isQuotationMark(tokens[posEr-1]) || posEr < 3 || (posEr > 1 && tokens[posEr-2].getToken().equals(":")))) {
int plus1 = ((posEr + 1) == tokens.length) ? 0 : +1;
BooleanAndFiniteVerb check = verbDoesMatchPersonAndNumber(tokens[posEr - 1], tokens[posEr + plus1], "3", "SIN", finiteVerb);
if (!check.verbDoesMatchPersonAndNumber
&& !nextButOneIsModal(tokens, posEr)
&& !"äußerst".equals(check.finiteVerb.getToken())
&& !"regen".equals(check.finiteVerb.getToken()) // "wo er regen Anteil nahm"
&& !tokens[posEr].isImmunized()
) {
ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posEr], check.finiteVerb, "3:SIN", pos, wholeSentence));
}
}
if (posVer1Plu != -1 && posWir == -1 && !isQuotationMark(tokens[posVer1Plu-1])) {
if (!tokens[posVer1Plu].isImmunized()) {
ruleMatches.add(ruleMatchWrongVerb(tokens[posVer1Plu], pos, wholeSentence));
}
} else if (posWir > 0 && !isNear(posPossibleVer1Plu, posWir) && !isQuotationMark(tokens[posWir-1])) {
int plus1 = ((posWir + 1) == tokens.length) ? 0 : +1;
BooleanAndFiniteVerb check = verbDoesMatchPersonAndNumber(tokens[posWir - 1], tokens[posWir + plus1], "1", "PLU", finiteVerb);
if (!check.verbDoesMatchPersonAndNumber && !nextButOneIsModal(tokens, posWir) && !tokens[posWir].isImmunized() &&
!check.finiteVerb.getToken().equals("äußerst")) {
ruleMatches.add(ruleMatchWrongVerbSubject(tokens[posWir], check.finiteVerb, "1:PLU", pos, wholeSentence));
}
}
return ruleMatches;
}