/** * Collect a list of pairs of constituents with the same syntactic function * from the right periphery of two sentences. The right periphery * encompasses the complements of the main verb, and its postmodifiers. * * @param sentences * the list of sentences * @return a list of pairs of constituents with the same function, if any * are found */ public static IList <PhraseSet> rightPeriphery(params NLGElement[] sentences) { IList <PhraseSet> funcsets = new List <PhraseSet>(); PhraseSet comps = new PhraseSet(DiscourseFunction.OBJECT); // new PhraseSet(DiscourseFunction.INDIRECT_OBJECT); PhraseSet pmods = new PhraseSet(DiscourseFunction.POST_MODIFIER); foreach (NLGElement s in sentences) { NLGElement vp = s.getFeatureAsElement(InternalFeature.VERB_PHRASE); if (vp != null) { if (vp.hasFeature(InternalFeature.COMPLEMENTS)) { comps.addPhrases(vp.getFeatureAsElementList(InternalFeature.COMPLEMENTS)); } if (vp.hasFeature(InternalFeature.POSTMODIFIERS)) { pmods.addPhrases(vp.getFeatureAsElementList(InternalFeature.POSTMODIFIERS)); } } if (s.hasFeature(InternalFeature.POSTMODIFIERS)) { pmods.addPhrases(s.getFeatureAsElementList(InternalFeature.POSTMODIFIERS)); } } funcsets.Add(comps); funcsets.Add(pmods); return(funcsets); }
/** * Applies aggregation to two NLGElements e1 and e2, succeeding only if they * are clauses (that is, e1.getCategory() == e2.getCategory == * {@link simplenlg.framework.PhraseCategory#CLAUSE}). */ public override NLGElement apply(NLGElement previous, NLGElement next) { NLGElement aggregated = null; if (previous.Category == PhraseCategory.PhraseCategoryEnum.CLAUSE && next.Category == PhraseCategory.PhraseCategoryEnum.CLAUSE && PhraseChecker.nonePassive(previous, next) && !PhraseChecker.expletiveSubjects(previous, next)) { if (PhraseChecker.sameSentences(previous, next)) { // case 1: identical sentences: remove the current aggregated = previous; } else if (PhraseChecker.sameFrontMods(previous, next) && PhraseChecker.sameSubjects(previous, next) && PhraseChecker.samePostMods(previous, next)) { // case 2: subjects identical: coordinate VPs aggregated = factory.createClause(); aggregated.setFeature(InternalFeature.SUBJECTS, previous.getFeatureAsElementList(InternalFeature.SUBJECTS)); aggregated.setFeature(InternalFeature.FRONT_MODIFIERS, previous.getFeatureAsElement(InternalFeature.FRONT_MODIFIERS)); aggregated.setFeature(Feature.CUE_PHRASE, previous.getFeatureAsElement(Feature.CUE_PHRASE)); aggregated.setFeature(InternalFeature.POSTMODIFIERS, previous.getFeatureAsElementList(InternalFeature.POSTMODIFIERS)); NLGElement vp; if (!PhraseChecker.sameVPArgs(previous, next) && PhraseChecker.sameVPHead(previous, next) && PhraseChecker.sameVPModifiers(previous, next)) { // case 2.1: VPs have different arguments but same head & mods NLGElement vp1 = previous.getFeatureAsElement(InternalFeature.VERB_PHRASE); vp = factory.createVerbPhrase(); vp.setFeature(InternalFeature.HEAD, vp1.getFeatureAsElement(InternalFeature.HEAD)); vp.setFeature(InternalFeature.COMPLEMENTS, vp1.getFeatureAsElementList(InternalFeature.COMPLEMENTS)); vp.setFeature(InternalFeature.PREMODIFIERS, vp1.getFeatureAsElementList(InternalFeature.PREMODIFIERS)); vp.setFeature(InternalFeature.POSTMODIFIERS, vp1.getFeatureAsElementList(InternalFeature.POSTMODIFIERS)); } else { // case 2.2: just create a coordinate vP NLGElement vp1 = previous.getFeatureAsElement(InternalFeature.VERB_PHRASE); NLGElement vp2 = next.getFeatureAsElement(InternalFeature.VERB_PHRASE); vp = factory.createCoordinatedPhrase(vp1, vp2); } // case 2.3: expletive subjects aggregated.setFeature(InternalFeature.VERB_PHRASE, vp); } else if (PhraseChecker.sameFrontMods(previous, next) && PhraseChecker.sameVP(previous, next) && PhraseChecker.samePostMods(previous, next)) { // case 3: identical VPs: conjoin subjects and front modifiers aggregated = factory.createClause(); aggregated.setFeature(InternalFeature.FRONT_MODIFIERS, previous.getFeatureAsElementList(InternalFeature.FRONT_MODIFIERS)); CoordinatedPhraseElement subjects = factory.createCoordinatedPhrase(); subjects.Category = new PhraseCategory(PhraseCategory.PhraseCategoryEnum.NOUN_PHRASE); IList <NLGElement> allSubjects = previous.getFeatureAsElementList(InternalFeature.SUBJECTS); ((List <NLGElement>)allSubjects).AddRange(next.getFeatureAsElementList(InternalFeature.SUBJECTS)); foreach (NLGElement subj in allSubjects) { subjects.addCoordinate(subj); } aggregated.setFeature(InternalFeature.SUBJECTS, subjects); aggregated.setFeature(InternalFeature.POSTMODIFIERS, previous.getFeatureAsElementList(InternalFeature.POSTMODIFIERS)); aggregated.setFeature(InternalFeature.VERB_PHRASE, previous.getFeature(InternalFeature.VERB_PHRASE)); } } return(aggregated); }
/** * Copies the front modifiers of the clause to the list of post-modifiers of * the verb only if the phrase has infinitive form. * * @param phrase * the <code>PhraseElement</code> representing this clause. * @param verbElement * the <code>NLGElement</code> representing the verb phrase for * this clause. */ private static void copyFrontModifiers(PhraseElement phrase, NLGElement verbElement) { IList <NLGElement> frontModifiers = phrase.getFeatureAsElementList(InternalFeature.FRONT_MODIFIERS); object clauseForm = phrase.getFeature(Feature.FORM); // bug fix by Chris Howell (Agfa) -- do not overwrite existing post-mods in the VP if (verbElement != null) { IList <NLGElement> phrasePostModifiers = phrase.getFeatureAsElementList(InternalFeature.POSTMODIFIERS); if (verbElement is PhraseElement) { IList <NLGElement> verbPostModifiers = verbElement.getFeatureAsElementList(InternalFeature.POSTMODIFIERS); foreach (NLGElement eachModifier in phrasePostModifiers) { // need to check that VP doesn't already contain the // post-modifier // this only happens if the phrase has already been realised // and later modified, with realiser called again. In that // case, postmods will be copied over twice if (!verbPostModifiers.Contains(eachModifier)) { ((PhraseElement)verbElement).addPostModifier(eachModifier); } } } } // if (verbElement != null) { // verbElement.setFeature(InternalFeature.POSTMODIFIERS, phrase // .getFeature(InternalFeature.POSTMODIFIERS)); // } if (Form.INFINITIVE.Equals(clauseForm)) { phrase.setFeature(Feature.SUPRESSED_COMPLEMENTISER, true); foreach (NLGElement eachModifier in frontModifiers) { if (verbElement is PhraseElement) { ((PhraseElement)verbElement).addPostModifier(eachModifier); } } phrase.removeFeature(InternalFeature.FRONT_MODIFIERS); if (verbElement != null) { verbElement.setFeature(InternalFeature.NON_MORPH, true); } } }
/** * check that the phrases supplied are sentences and have the same VP * premodifiers and postmodifiers * * @param sentences * the sentences * @return <code>true</code> if all pairs of sentences have VPs with the * same pre and postmodifiers */ public static bool sameVPModifiers(params NLGElement[] sentences) { bool equal = sentences.Length >= 2; for (int i = 1; i < sentences.Length && equal; i++) { NLGElement vp1 = sentences[i - 1].getFeatureAsElement(InternalFeature.VERB_PHRASE); NLGElement vp2 = sentences[i].getFeatureAsElement(InternalFeature.VERB_PHRASE); equal = vp1.getFeatureAsElementList(InternalFeature.POSTMODIFIERS).Equals(vp2.getFeatureAsElementList(InternalFeature.POSTMODIFIERS)) && vp1.getFeatureAsElementList(InternalFeature.PREMODIFIERS).Equals(vp2.getFeatureAsElementList(InternalFeature.PREMODIFIERS)); } return(equal); }
/** * Check that the sentences supplied have the same complements at VP level. * * @param sentences * the sentences * @return <code>true</code> if for every pair of sentences <code>s1</code> * and <code>s2</code>, their VPs have the same pre- and * post-modifiers and complements. */ public static bool sameVPArgs(params NLGElement[] sentences) { bool equal = sentences.Length >= 2; for (int i = 1; i < sentences.Length && equal; i++) { NLGElement vp1 = sentences[i - 1].getFeatureAsElement(InternalFeature.VERB_PHRASE); NLGElement vp2 = sentences[i].getFeatureAsElement(InternalFeature.VERB_PHRASE); equal = vp1.getFeatureAsElementList(InternalFeature.COMPLEMENTS).Equals(vp2.getFeatureAsElementList(InternalFeature.COMPLEMENTS)); } return(equal); }
private void recursiveElide(NLGElement component) { if (component is ListElement) { foreach (NLGElement subcomponent in component.getFeatureAsElementList(InternalFeature.COMPONENTS)) { recursiveElide(subcomponent); } } else { component.setFeature(Feature.ELIDED, true); } }
private static IList <NLGElement> getAllChildren(NLGElement element) { IList <NLGElement> children = new List <NLGElement>(); IList <NLGElement> components = element is ListElement?element.getFeatureAsElementList(InternalFeature.COMPONENTS) : element.Children; foreach (NLGElement child in components) { children.Add(child); if (child.Category == PhraseCategory.PhraseCategoryEnum.VERB_PHRASE || (DiscourseFunction)child.getFeature(InternalFeature.DISCOURSE_FUNCTION) == DiscourseFunction.VERB_PHRASE) { ((List <NLGElement>)children).AddRange(getAllChildren(child)); } } return(children); }
/** * Realises the complements of passive clauses; also sets number, person for * passive * * @param phrase * the <code>PhraseElement</code> representing this clause. * @param parent * the parent <code>SyntaxProcessor</code> that will do the * realisation of the complementiser. * @param realisedElement * the current realisation of the clause. * @param verbElement * the <code>NLGElement</code> representing the verb phrase for * this clause. */ private static NLGElement addPassiveComplementsNumberPerson(PhraseElement phrase, SyntaxProcessor parent, ListElement realisedElement, NLGElement verbElement) { object passiveNumber = null; object passivePerson = null; NLGElement currentElement = null; NLGElement splitVerb = null; NLGElement verbPhrase = phrase.getFeatureAsElement(InternalFeature.VERB_PHRASE); // count complements to set plural feature if more than one int numComps = 0; bool coordSubj = false; if (phrase.getFeatureAsBoolean(Feature.PASSIVE) && verbPhrase != null && !InterrogativeType.WHAT_OBJECT.Equals(phrase.getFeature(Feature.INTERROGATIVE_TYPE))) { // complements of a clause are stored in the VPPhraseSpec foreach (NLGElement subject in verbPhrase.getFeatureAsElementList(InternalFeature.COMPLEMENTS)) { // AG: complement needn't be an NP // subject.isA(PhraseCategory.NOUN_PHRASE) && if (DiscourseFunction.OBJECT.Equals(subject.getFeature(InternalFeature.DISCOURSE_FUNCTION))) { subject.setFeature(Feature.PASSIVE, true); numComps++; currentElement = parent.realise(subject); if (currentElement != null) { currentElement.setFeature(InternalFeature.DISCOURSE_FUNCTION, DiscourseFunction.OBJECT); if (phrase.hasFeature(Feature.INTERROGATIVE_TYPE)) { splitVerb = currentElement; } else { realisedElement.addComponent(currentElement); } } // flag if passive subject is coordinated with an "and" if (!coordSubj && subject is CoordinatedPhraseElement) { string conj = ((CoordinatedPhraseElement)subject).Conjunction; coordSubj = (!ReferenceEquals(conj, null) && conj.Equals("and")); } if (passiveNumber == null) { passiveNumber = subject.getFeature(Feature.NUMBER); } else { passiveNumber = NumberAgreement.PLURAL; } if (Person.FIRST.Equals(subject.getFeature(Feature.PERSON))) { passivePerson = Person.FIRST; } else if (Person.SECOND.Equals(subject.getFeature(Feature.PERSON)) && !Person.FIRST.Equals(passivePerson)) { passivePerson = Person.SECOND; } else if (passivePerson == null) { passivePerson = Person.THIRD; } if (Form.GERUND.Equals(phrase.getFeature(Feature.FORM)) && !phrase.getFeatureAsBoolean(Feature.SUPPRESS_GENITIVE_IN_GERUND)) { subject.setFeature(Feature.POSSESSIVE, true); } } } } if (verbElement != null) { if (passivePerson != null) { verbElement.setFeature(Feature.PERSON, passivePerson); // below commented out. for non-passive, number and person set // by checkSubjectNumberPerson // } else { // verbElement.setFeature(Feature.PERSON, phrase // .getFeature(Feature.PERSON)); } if (numComps > 1 || coordSubj) { verbElement.setFeature(Feature.NUMBER, NumberAgreement.PLURAL); } else if (passiveNumber != null) { verbElement.setFeature(Feature.NUMBER, passiveNumber); } } return(splitVerb); }