diff --git a/README.md b/README.md index 906d4e6..e2efe74 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Build status](https://ci.appveyor.com/api/projects/status/yu970w2evwwkx0vt?svg=true)](https://ci.appveyor.com/project/Arash-Sabet/sharpsimplenlg) # SharpSimpleNLG SharpSimpleNLG is a C# port of the [University of Aberdeen *simplenlg* project](https://github.com/simplenlg/simplenlg). All thanks and acknowledgement for hard work goes to this team. @@ -10,6 +11,8 @@ Install-Package SharpSimpleNLG ``` ## Version News +Version 1.2.0 +* Now supports .net standard 1.6 and full .net 4.6.2. Added to Nuget package. Version 1.1.1: * Thanks to [PR from Andriy Svyrd](https://github.com/nickhodge/SharpSimpleNLG/pull/2) now supports .NET Standard 1.3. Added to NuGet package (I hope my packaging is OK!) diff --git a/SharpSimpleNLG.sln b/SharpSimpleNLG.sln index 66eb67a..13ab00e 100644 --- a/SharpSimpleNLG.sln +++ b/SharpSimpleNLG.sln @@ -18,7 +18,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpSimpleNLGDotNet45", "S EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpSimpleNLG", "SharpSimpleNLG\SharpSimpleNLG.csproj", "{16F344A8-B688-4D95-8DA6-2E207D47AECB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpSimpleNLGConsoleNetCore", "SharpSimpleNLGConsoleNetCore\SharpSimpleNLGConsoleNetCore.csproj", "{3E619416-20EC-429F-A467-9F7BFE8BACB1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpSimpleNLGConsoleNetCore", "SharpSimpleNLGConsoleNetCore\SharpSimpleNLGConsoleNetCore.csproj", "{3E619416-20EC-429F-A467-9F7BFE8BACB1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/SharpSimpleNLG/Properties/AssemblyInfo.cs b/SharpSimpleNLG/Properties/AssemblyInfo.cs index 4fbd895..7884eb6 100644 --- a/SharpSimpleNLG/Properties/AssemblyInfo.cs +++ b/SharpSimpleNLG/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SharpSimpleNLG")] -[assembly: AssemblyCopyright("Copyright © 2016 Various Parties")] +[assembly: AssemblyCopyright("Copyright © 2017 Various Parties")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/SharpSimpleNLG/SharpSimpleNLG.csproj b/SharpSimpleNLG/SharpSimpleNLG.csproj index 4cf49e9..d287997 100644 --- a/SharpSimpleNLG/SharpSimpleNLG.csproj +++ b/SharpSimpleNLG/SharpSimpleNLG.csproj @@ -13,6 +13,11 @@ false false false + 1.2.0 + https://github.com/nickhodge/SharpSimpleNLG/blob/master/LICENSE.md + + https://github.com/nickhodge/SharpSimpleNLG + git bin\$(Configuration)\$(Framework) diff --git a/SharpSimpleNLGTests/SharpSimpleNLGTests.csproj b/SharpSimpleNLGTests/SharpSimpleNLGTests.csproj index f1369ac..febe16b 100644 --- a/SharpSimpleNLGTests/SharpSimpleNLGTests.csproj +++ b/SharpSimpleNLGTests/SharpSimpleNLGTests.csproj @@ -66,6 +66,9 @@ + + + @@ -106,9 +109,9 @@ - - {fd418a41-a46e-4fd7-a6db-ff3ebb4afa29} - SharpSimpleNLGDotNet45 + + {16f344a8-b688-4d95-8da6-2e207d47aecb} + SharpSimpleNLG diff --git a/SharpSimpleNLGTests/morphology/DeterminerAgrHelper.cs b/SharpSimpleNLGTests/morphology/DeterminerAgrHelper.cs new file mode 100644 index 0000000..8ca707f --- /dev/null +++ b/SharpSimpleNLGTests/morphology/DeterminerAgrHelper.cs @@ -0,0 +1,244 @@ +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is "SharpSimpleNLG". + * + * The Initial Developer of the Original Code is Ehud Reiter, Albert Gatt and Dave Westwater. + * Portions created by Ehud Reiter, Albert Gatt and Dave Westwater are Copyright (C) 2010-11 The University of Aberdeen. All Rights Reserved. + * + * Contributor(s): Ehud Reiter, Albert Gatt, Dave Wewstwater, Roman Kutlak, Margaret Mitchell, Saad Mahamood, Nick Hodge + */ + +/* Additional Notes: + * - Original Java source is SimpleNLG from 12-Jun-2016 https://github.com/simplenlg/simplenlg + * - This is a port of the Java version to C# with no additional features + * - I have left the "Initial Developer" section to reflect this fact + * - Any questions, comments, feedback on this port can be sent to Nick Hodge + */ + +using System.Text; +using SimpleNLG.Extensions; + +namespace SharpNLG.Extensions +{ +/** + * This class is used to parse numbers that are passed as figures, to determine + * whether they should take "a" or "an" as determiner. + * + * @author bertugatt + * + */ + + public class DeterminerAgrHelper + { + /* + * An array of strings which are exceptions to the rule that "an" comes + * before vowels + */ + private static string[] AN_EXCEPTIONS = {"one", "180", "110"}; + + /* + * Start of string involving vowels, for use of "an" + */ + private static string AN_AGREEMENT = @"\A(a|e|i|o|u).*"; + + /* + * Start of string involving numbers, for use of "an" -- courtesy of Chris + * Howell, Agfa healthcare corporation + */ + // private static final string AN_NUMERAL_AGREEMENT = + // "^(((8((\\d+)|(\\d+(\\.|,)\\d+))?).*)|((11|18)(\\d{3,}|\\D)).*)$"; + + /** + * Check whether this string starts with a number that needs "an" (e.g. + * "an 18% increase") + * + * @param string + * the string + * @return true if this string starts with 11, 18, or 8, + * excluding strings that start with 180 or 110 + */ + + public static bool requiresAn(string stringa) + { + var req = false; + + var lowercaseInput = stringa.toLowerCase(); + + if (lowercaseInput.matches(AN_AGREEMENT) && !isAnException(lowercaseInput)) + { + req = true; + + } + else + { + var numPref = getNumericPrefix(lowercaseInput); + + if (numPref != null && numPref.length() > 0 + && numPref.matches(@"^(8|11|18).*$")) + { + var num = int.Parse(numPref); + req = checkNum(num); + } + } + + return req; + } + + /* + * check whether a string beginning with a vowel is an exception and doesn't + * take "an" (e.g. "a one percent change") + * + * @return + */ + + private static bool isAnException(string stringa) + { + foreach (var ex in AN_EXCEPTIONS) + { + if (stringa.matches("^" + ex + ".*")) + { + // if (string.equalsIgnoreCase(ex)) { + return true; + } + } + + return false; + } + + /* + * Returns true if the number starts with 8, 11 or 18 and is + * either less than 100 or greater than 1000, but excluding 180,000 etc. + */ + + private static bool checkNum(int num) + { + var needsAn = false; + + // eight, eleven, eighty and eighteen + if (num == 11 || num == 18 || num == 8 || (num >= 80 && num < 90)) + { + needsAn = true; + + } + else if (num > 1000) + { + // num = Math.Round(num / 1000); + num = num/1000; + needsAn = checkNum(num); + } + + return needsAn; + } + + /* + * Retrieve the numeral prefix of a string. + */ + + private static string getNumericPrefix(string stringa) + { + var numeric = new StringBuilder(); + + if (stringa != null) + { + stringa = stringa.Trim(); + + if (stringa.length() > 0) + { + + var buffer = new StringBuilder(stringa); + var first = buffer.charAt(0); + + if (first.isDigit()) + { + numeric.append(first); + + for (var i = 1; i < buffer.length(); i++) + { + var next = buffer.charAt(i); + + if (next.isDigit()) + { + numeric.append(next); + + // skip commas within numbers + } + else if (next.Equals(',')) + { + continue; + + } + else + { + break; + } + } + } + } + } + + return numeric.length() == 0 ? null : numeric.ToString(); + } + + + /** + * Check to see if a string ends with the indefinite article "a" and it agrees with {@code np}. + * @param text + * @param np + * @return an altered version of {@code text} to use "an" if it agrees with {@code np}, the original string otherwise. + */ + + public static string checkEndsWithIndefiniteArticle(string text, string np) + { + + var tokens = text.Split(' '); + + var lastToken = tokens[tokens.Length - 1]; + + if (lastToken.equalsIgnoreCase("a") && DeterminerAgrHelper.requiresAn(np)) + { + + tokens[tokens.Length - 1] = "an"; + + return stringArrayToString(tokens); + + } + + return text; + + } + + // Turns ["a","b","c"] into "a b c" + private static string stringArrayToString(string[] sArray) + { + + var buf = new StringBuilder(); + + for (var i = 0; i < sArray.Length; i++) + { + + buf.Append(sArray[i]); + + if (i != sArray.Length - 1) + { + + buf.Append(" "); + + } + + } + + return buf.ToString(); + + } + + } +} \ No newline at end of file diff --git a/SharpSimpleNLGTests/morphology/MorphologyProcessor.cs b/SharpSimpleNLGTests/morphology/MorphologyProcessor.cs new file mode 100644 index 0000000..2ccfeda --- /dev/null +++ b/SharpSimpleNLGTests/morphology/MorphologyProcessor.cs @@ -0,0 +1,302 @@ +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is "SharpSimpleNLG". + * + * The Initial Developer of the Original Code is Ehud Reiter, Albert Gatt and Dave Westwater. + * Portions created by Ehud Reiter, Albert Gatt and Dave Westwater are Copyright (C) 2010-11 The University of Aberdeen. All Rights Reserved. + * + * Contributor(s): Ehud Reiter, Albert Gatt, Dave Wewstwater, Roman Kutlak, Margaret Mitchell, Saad Mahamood, Nick Hodge + */ + +/* Additional Notes: + * - Original Java source is SimpleNLG from 12-Jun-2016 https://github.com/simplenlg/simplenlg + * - This is a port of the Java version to C# with no additional features + * - I have left the "Initial Developer" section to reflect this fact + * - Any questions, comments, feedback on this port can be sent to Nick Hodge + */ + +using System.Collections.Generic; +using SharpNLG.Extensions; +using SimpleNLG.Extensions; + +namespace SimpleNLG +{ + /** + *

+ * This is the processor for handling morphology within the SimpleNLG. The + * processor inflects words form the base form depending on the features applied + * to the word. For example, kiss is inflected to kissed for + * past tense, dog is inflected to dogs for pluralisation. + *

+ * + *

+ * As a matter of course, the processor will first use any user-defined + * inflection for the world. If no inflection is provided then the lexicon, if + * it exists, will be examined for the correct inflection. Failing this a set of + * very basic rules will be examined to inflect the word. + *

+ * + *

+ * All processing modules perform realisation on a tree of + * NLGElements. The modules can alter the tree in whichever way + * they wish. For example, the syntax processor replaces phrase elements with + * list elements consisting of inflected words while the morphology processor + * replaces inflected words with string elements. + *

+ * + *

+ * N.B. the use of module, processing module and + * processor is interchangeable. They all mean an instance of this + * class. + *

+ * + * + * @author D. Westwater, University of Aberdeen. + * @version 4.0 + */ + + public class MorphologyProcessor : NLGModule + { + + + public override void initialise() + { + // Do nothing + } + + + public override INLGElement realise(INLGElement element) + { + INLGElement realisedElement = null; + + if (element is InflectedWordElement) + { + realisedElement = doMorphology((InflectedWordElement) element); + + } + else if (element is StringElement) + { + realisedElement = element; + + } + else if (element is WordElement) + { + // AG: now retrieves the default spelling variant, not the baseform + // string baseForm = ((WordElement) element).getBaseForm(); + var defaultSpell = ((WordElement) element).getDefaultSpellingVariant(); + + if (defaultSpell != null) + { + realisedElement = new StringElement(defaultSpell); + } + + } + else if (element is DocumentElement) + { + List children = element.getChildren(); + ((DocumentElement) element).setComponents(realise(children)); + realisedElement = element; + + } + else if (element is ListElement) + { + realisedElement = new ListElement(); + ((ListElement) realisedElement).addComponents(realise(element.getChildren())); + + } + else if (element is CoordinatedPhraseElement) + { + List children = element.getChildren(); + ((CoordinatedPhraseElement) element).clearCoordinates(); + + if (children != null && children.size() > 0) + { + ((CoordinatedPhraseElement) element).addCoordinate(realise(children.get(0))); + + for (var index = 1; index < children.size(); index++) + { + ((CoordinatedPhraseElement) element).addCoordinate(realise(children.get(index))); + } + + realisedElement = element; + } + + } + else if (element != null) + { + realisedElement = element; + } + + return realisedElement; + } + + /** + * This is the main method for performing the morphology. It effectively + * examines the lexical category of the element and calls the relevant set + * of rules from MorphologyRules. + * + * @param element + * the InflectedWordElement + * @return an NLGElement reflecting the correct inflection for + * the word. + */ + + private INLGElement doMorphology(InflectedWordElement element) + { + INLGElement realisedElement = null; + if (element.getFeatureAsBoolean(InternalFeature.NON_MORPH.ToString())) + { + realisedElement = new StringElement(element.getBaseForm()); + realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), + element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString())); + + } + else + { + INLGElement baseWord = element.getFeatureAsElement(InternalFeature.BASE_WORD.ToString()); + + if (baseWord == null && this.lexicon != null) + { + baseWord = this.lexicon.lookupWord(element.getBaseForm()); + } + + var category = element.getCategory(); + + if (category is ILexicalCategory) + { + switch ((LexicalCategoryEnum)category.enumType) + { + case LexicalCategoryEnum.PRONOUN: + realisedElement = MorphologyRules.doPronounMorphology(element); + break; + + case LexicalCategoryEnum.NOUN: + realisedElement = MorphologyRules.doNounMorphology(element, (WordElement) baseWord); + break; + + case LexicalCategoryEnum.VERB: + realisedElement = MorphologyRules.doVerbMorphology(element, (WordElement) baseWord); + break; + + case LexicalCategoryEnum.ADJECTIVE: + realisedElement = MorphologyRules.doAdjectiveMorphology(element, (WordElement) baseWord); + break; + + case LexicalCategoryEnum.ADVERB: + realisedElement = MorphologyRules.doAdverbMorphology(element, (WordElement) baseWord); + break; + + default: + realisedElement = new StringElement(element.getBaseForm()); + realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), + element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString())); + break; + } + } + } + return realisedElement; + } + + + public override List realise(List elements) + { + var realisedElements = new List(); + INLGElement currentElement = null; + INLGElement determiner = null; + INLGElement prevElement = null; + + if (elements != null) + { + foreach (var eachElement in elements) + { + currentElement = realise(eachElement); + + if (currentElement != null) + { + //pass the discourse function and appositive features -- important for orth processor + currentElement.setFeature(Feature.APPOSITIVE.ToString(), + eachElement.getFeature(Feature.APPOSITIVE.ToString())); + var function = eachElement.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString()); + + if (function != null) + { + currentElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), function); + } + + if (prevElement != null && prevElement is StringElement + && eachElement is InflectedWordElement + && (eachElement.getCategory().enumType == (int)LexicalCategoryEnum.NOUN)) + { + + var prevString = prevElement.getRealisation(); + + //realisedElements.get(realisedElements.size() - 1) + + prevElement.setRealisation(DeterminerAgrHelper.checkEndsWithIndefiniteArticle(prevString, + currentElement.getRealisation())); + + } + + // realisedElements.add(realise(currentElement)); + realisedElements.add(currentElement); + + if (determiner == null && DiscourseFunction.SPECIFIER.Equals(currentElement.getFeature( + InternalFeature.DISCOURSE_FUNCTION.ToString()))) + { + determiner = currentElement; + determiner.setFeature(Feature.NUMBER.ToString(), + eachElement.getFeature(Feature.NUMBER.ToString())); + // MorphologyRules.doDeterminerMorphology(determiner, + // currentElement.getRealisation()); + + } + else if (determiner != null) + { + + if (currentElement is ListElement) + { + // list elements: ensure det matches first element + INLGElement firstChild = ((ListElement) currentElement).getChildren().get(0); + + if (firstChild != null) + { + //AG: need to check if child is a coordinate + if (firstChild is CoordinatedPhraseElement) + { + MorphologyRules.doDeterminerMorphology(determiner, + firstChild.getChildren().get(0).getRealisation()); + } + else + { + MorphologyRules.doDeterminerMorphology(determiner, firstChild.getRealisation()); + } + } + + } + else + { + // everything else: ensure det matches realisation + MorphologyRules.doDeterminerMorphology(determiner, currentElement.getRealisation()); + } + + determiner = null; + } + } + prevElement = eachElement; + } + } + + return realisedElements; + } + + } +} \ No newline at end of file diff --git a/SharpSimpleNLGTests/morphology/MorphologyRules.cs b/SharpSimpleNLGTests/morphology/MorphologyRules.cs new file mode 100644 index 0000000..70f67fc --- /dev/null +++ b/SharpSimpleNLGTests/morphology/MorphologyRules.cs @@ -0,0 +1,1148 @@ +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is "SharpSimpleNLG". + * + * The Initial Developer of the Original Code is Ehud Reiter, Albert Gatt and Dave Westwater. + * Portions created by Ehud Reiter, Albert Gatt and Dave Westwater are Copyright (C) 2010-11 The University of Aberdeen. All Rights Reserved. + * + * Contributor(s): Ehud Reiter, Albert Gatt, Dave Wewstwater, Roman Kutlak, Margaret Mitchell, Saad Mahamood, Nick Hodge + */ + +/* Additional Notes: + * - Original Java source is SimpleNLG from 12-Jun-2016 https://github.com/simplenlg/simplenlg + * - This is a port of the Java version to C# with no additional features + * - I have left the "Initial Developer" section to reflect this fact + * - Any questions, comments, feedback on this port can be sent to Nick Hodge + */ + + using System.Text; + using SharpNLG.Extensions; + using SimpleNLG.Extensions; + +namespace SimpleNLG +{ + /** + *

+ * This abstract class contains a number of rules for doing simple inflection. + *

+ * + *

+ * As a matter of course, the processor will first use any user-defined + * inflection for the world. If no inflection is provided then the lexicon, if + * it exists, will be examined for the correct inflection. Failing this a set of + * very basic rules will be examined to inflect the word. + *

+ * + *

+ * All processing modules perform realisation on a tree of + * NLGElements. The modules can alter the tree in whichever way + * they wish. For example, the syntax processor replaces phrase elements with + * list elements consisting of inflected words while the morphology processor + * replaces inflected words with string elements. + *

+ * + *

+ * N.B. the use of module, processing module and + * processor is interchangeable. They all mean an instance of this + * class. + *

+ * + * + * @author D. Westwater, University of Aberdeen. + * @version 4.0 16-Mar-2011 modified to use correct base form (ER) + */ + + public abstract class MorphologyRules : NLGModule + { + + /** + * A triple array of Pronouns organised by singular/plural, + * possessive/reflexive/subjective/objective and by gender/person. + */ + + private static string[][][] PRONOUNS = new string[][][] + { new string[][] + { + new string[] {"I", "you", "he", "she", "it"}, + new string[]{"me", "you", "him", "her", "it"}, + new string[]{"myself", "yourself", "himself", "herself", "itself"}, + new string[]{"mine", "yours", "his", "hers", "its"}, + new string[] {"my", "your", "his", "her", "its"} + }, + new string[][]{ + new string[]{"we", "you", "they", "they", "they"}, + new string[]{"us", "you", "them", "them", "them"}, + new string[]{ + "ourselves", + "yourselves", + "themselves", + "themselves", + "themselves" + }, + new string[]{"ours", "yours", "theirs", "theirs", "theirs"}, + new string[] {"our", "your", "their", "their", "their"} + } + }; + + private static string[] WH_PRONOUNS = {"who", "what", "which", "where", "why", "how", "how many"}; + + /** + * This method performs the morphology for nouns. + * + * @param element + * the InflectedWordElement. + * @param baseWord + * the WordElement as created from the lexicon + * entry. + * @return a StringElement representing the word after + * inflection. + */ + + public static StringElement doNounMorphology(InflectedWordElement element, WordElement baseWord) + { + var realised = new StringBuilder(); + + // base form from baseWord if it exists, otherwise from element + var baseForm = getBaseForm(element, baseWord); + + if (element.isPlural() && !element.getFeatureAsBoolean(LexicalFeature.PROPER)) + { + + string pluralForm = null; + + // AG changed: now check if default infl is uncount + // if (element.getFeatureAsBoolean(LexicalFeature.NON_COUNT) + // ) { + // pluralForm = baseForm; + var elementDefaultInfl = element.getFeature(LexicalFeature.DEFAULT_INFL); + + if (elementDefaultInfl != null && Inflection.UNCOUNT.Equals(elementDefaultInfl)) + { + pluralForm = baseForm; + + } + else + { + pluralForm = element.getFeatureAsString(LexicalFeature.PLURAL); + } + + if (pluralForm == null && baseWord != null) + { + // AG changed: now check if default infl is uncount + // if (baseWord.getFeatureAsBoolean(LexicalFeature.NON_COUNT) + // ) { + // pluralForm = baseForm; + var baseDefaultInfl = baseWord.getFeatureAsString(LexicalFeature.DEFAULT_INFL); + if (baseDefaultInfl != null && baseDefaultInfl.Equals("uncount")) + { + pluralForm = baseForm; + } + else + { + pluralForm = baseWord.getFeatureAsString(LexicalFeature.PLURAL); + } + } + + if (pluralForm == null) + { + var pattern = element.getFeature(LexicalFeature.DEFAULT_INFL); + if (Inflection.GRECO_LATIN_REGULAR.Equals(pattern)) + { + pluralForm = buildGrecoLatinPluralNoun(baseForm); + } + else + { + pluralForm = buildRegularPluralNoun(baseForm); + } + } + realised.append(pluralForm); + + } + else + { + realised.append(baseForm); + } + + checkPossessive(element, realised); + var realisedElement = new StringElement(realised.ToString()); + realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), + element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString())); + return realisedElement; + } + + /** + * Builds a plural for regular nouns. The rules are performed in this order: + *
    + *
  • For nouns ending -Cy, where C is any consonant, the ending + * becomes -ies. For example, fly becomes flies.
  • + *
  • For nouns ending -ch, -s, -sh, -x + * or -z the ending becomes -es. For example, box + * becomes boxes.
  • + *
  • All other nouns have -s appended the other end. For example, + * dog becomes dogs.
  • + *
+ * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildRegularPluralNoun(string baseForm) + { + string plural = null; + if (baseForm != null) + { + // .NET doesnt support character class subtraction the same was as Java + // was .*[b-z-[eiou]]y\\b + if (baseForm.matches(@".*[b-z-[eiou]]y\b")) + { + + plural = baseForm.replaceAll(@"y\b", @"ies"); + + //AG: changed regex from ".*[szx(ch)(sh)]\\b" (tip of the hat to Ian Tabolt) + } + else if (baseForm.matches(@".*([szx]|[cs]h)\b")) + { + + plural = baseForm + "es"; + + } + else + { + plural = baseForm + "s"; + } + } + return plural; + } + + /** + * Builds a plural for Greco-Latin regular nouns. The rules are performed in + * this order: + *
    + *
  • For nouns ending -us the ending becomes -i. For + * example, focus becomes foci.
  • + *
  • For nouns ending -ma the ending becomes -mata. For + * example, trauma becomes traumata.
  • + *
  • For nouns ending -a the ending becomes -ae. For + * example, larva becomes larvae.
  • + *
  • For nouns ending -um or -on the ending becomes + * -a. For example, taxon becomes taxa.
  • + *
  • For nouns ending -sis the ending becomes -ses. For + * example, analysis becomes analyses.
  • + *
  • For nouns ending -is the ending becomes -ides. For + * example, cystis becomes cystides.
  • + *
  • For nouns ending -men the ending becomes -mina. For + * example, foramen becomes foramina.
  • + *
  • For nouns ending -ex the ending becomes -ices. For + * example, index becomes indices.
  • + *
  • For nouns ending -x the ending becomes -ces. For + * example, matrix becomes matrices.
  • + *
+ * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildGrecoLatinPluralNoun(string baseForm) + { + string plural = null; + if (baseForm != null) + { + if (baseForm.endsWith("us")) + { + + plural = baseForm.replaceAll(@"us\b", "i"); + } + else if (baseForm.endsWith("ma")) + { + + plural = baseForm + "ta"; + } + else if (baseForm.endsWith("a")) + { + + plural = baseForm + "e"; + } + else if (baseForm.matches(@".*[(um)(on)]\\b")) + { + + plural = baseForm.replaceAll(@"[(um)(on)]\\b", "a"); + } + else if (baseForm.endsWith("sis")) + { + + plural = baseForm.replaceAll(@"sis\b", "ses"); + } + else if (baseForm.endsWith("is")) + { + + plural = baseForm.replaceAll(@"is\b", "ides"); + } + else if (baseForm.endsWith("men")) + { + + plural = baseForm.replaceAll(@"men\b", "mina"); + } + else if (baseForm.endsWith("ex")) + { + + plural = baseForm.replaceAll(@"ex\b", "ices"); + } + else if (baseForm.endsWith("x")) + { + + plural = baseForm.replaceAll(@"x\b", "ces"); + } + else + { + plural = baseForm; + } + } + return plural; + } + + /** + * This method performs the morphology for verbs. + * + * @param element + * the InflectedWordElement. + * @param baseWord + * the WordElement as created from the lexicon + * entry. + * @return a StringElement representing the word after + * inflection. + */ + + public static INLGElement doVerbMorphology(InflectedWordElement element, WordElement baseWord) + { + + string realised = null; + var numberValue = element.getFeature(Feature.NUMBER.ToString()); + var personValue = element.getFeature(Feature.PERSON.ToString()); + var tenseValue = element.getFeatureTense(Feature.TENSE.ToString()); + + + var formValue = element.getFeature(Feature.FORM.ToString()); + var patternValue = element.getFeature(LexicalFeature.DEFAULT_INFL); + + // base form from baseWord if it exists, otherwise from element + var baseForm = getBaseForm(element, baseWord); + + if (element.getFeatureAsBoolean(Feature.NEGATED.ToString()) || Form.BARE_INFINITIVE.Equals(formValue)) + { + realised = baseForm; + + } + else if (Form.PRESENT_PARTICIPLE.Equals(formValue)) + { + realised = element.getFeatureAsString(LexicalFeature.PRESENT_PARTICIPLE); + + if (realised == null && baseWord != null) + { + realised = baseWord.getFeatureAsString(LexicalFeature.PRESENT_PARTICIPLE); + } + + if (realised == null) + { + if (Inflection.REGULAR_DOUBLE.Equals(patternValue)) + { + realised = buildDoublePresPartVerb(baseForm); + } + else + { + realised = buildRegularPresPartVerb(baseForm); + } + } + + } + else if (Tense.PAST.Equals(tenseValue) || Form.PAST_PARTICIPLE.Equals(formValue)) + { + + if (Form.PAST_PARTICIPLE.Equals(formValue)) + { + realised = element.getFeatureAsString(LexicalFeature.PAST_PARTICIPLE); + + if (realised == null && baseWord != null) + { + realised = baseWord.getFeatureAsString(LexicalFeature.PAST_PARTICIPLE); + } + + if (realised == null) + { + if ("be".equalsIgnoreCase(baseForm)) + { + + realised = "been"; + } + else if (Inflection.REGULAR_DOUBLE.Equals(patternValue)) + { + realised = buildDoublePastVerb(baseForm); + } + else + { + realised = buildRegularPastVerb(baseForm, numberValue, personValue); + } + } + + } + else + { + realised = element.getFeatureAsString(LexicalFeature.PAST); + + if (realised == null && baseWord != null) + { + realised = baseWord.getFeatureAsString(LexicalFeature.PAST); + } + + if (realised == null) + { + if (Inflection.REGULAR_DOUBLE.Equals(patternValue)) + { + realised = buildDoublePastVerb(baseForm); + } + else + { + realised = buildRegularPastVerb(baseForm, numberValue, personValue); + } + } + } + + } + else if ((numberValue == null || NumberAgreement.SINGULAR.Equals(numberValue)) && (personValue == null + || Person.THIRD.Equals( + personValue)) && + (Tense.PRESENT.Equals(tenseValue))) + { + + realised = element.getFeatureAsString(LexicalFeature.PRESENT3S); + + if (realised == null && baseWord != null && !"be".equalsIgnoreCase(baseForm)) + { + + realised = baseWord.getFeatureAsString(LexicalFeature.PRESENT3S); + } + if (realised == null) + { + realised = buildPresent3SVerb(baseForm); + } + + } + else + { + if ("be".equalsIgnoreCase(baseForm)) + { + + if (Person.FIRST.Equals(personValue) && (NumberAgreement.SINGULAR.Equals(numberValue) + || numberValue == null)) + { + realised = "am"; + } + else + { + realised = "are"; + } + } + else + { + realised = baseForm; + } + } + var realisedElement = new StringElement(realised); + realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), + element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString())); + return realisedElement; + } + + /** + * return the base form of a word + * + * @param element + * @param baseWord + * @return + */ + + private static string getBaseForm(InflectedWordElement element, WordElement baseWord) + { + // unclear what the right behaviour should be + // for now, prefer baseWord.getBaseForm() to element.getBaseForm() for + // verbs (ie, "is" mapped to "be") + // but prefer element.getBaseForm() to baseWord.getBaseForm() for other + // words (ie, "children" not mapped to "child") + + // AG: changed this to get the default spelling variant + // needed to preserve spelling changes in the VP + + if ((int)LexicalCategoryEnum.VERB == element.getCategory().enumType) + { + if (baseWord != null && baseWord.getDefaultSpellingVariant() != null) + return baseWord.getDefaultSpellingVariant(); + else + return element.getBaseForm(); + } + else + { + if (element.getBaseForm() != null) + return element.getBaseForm(); + else if (baseWord == null) + return null; + else + return baseWord.getDefaultSpellingVariant(); + } + + // if (LexicalCategory.VERB == element.getCategory()) { + // if (baseWord != null && baseWord.getBaseForm() != null) + // return baseWord.getBaseForm(); + // else + // return element.getBaseForm(); + // } else { + // if (element.getBaseForm() != null) + // return element.getBaseForm(); + // else if (baseWord == null) + // return null; + // else + // return baseWord.getBaseForm(); + // } + } + + /** + * Checks to see if the noun is possessive. If it is then nouns in ending in + * -s become -s' while every other noun has -'s appended to + * the end. + * + * @param element + * the InflectedWordElement + * @param realised + * the realisation of the word. + */ + + private static void checkPossessive(InflectedWordElement element, StringBuilder realised) + { + + if (element.getFeatureAsBoolean(Feature.POSSESSIVE.ToString())) + { + if (realised.charAt(realised.length() - 1) == 's') + { + realised.append("\'"); + + } + else + { + realised.append("'s"); + } + } + } + + /** + * Builds the third-person singular form for regular verbs. The rules are + * performed in this order: + *
    + *
  • If the verb is be the realised form is is.
  • + *
  • For verbs ending -ch, -s, -sh, -x + * or -z the ending becomes -es. For example, + * preach becomes preaches.
  • + *
  • For verbs ending -y the ending becomes -ies. For + * example, fly becomes flies.
  • + *
  • For every other verb, -s is added to the end of the word.
  • + *
+ * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildPresent3SVerb(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + if (baseForm.equalsIgnoreCase("be")) + { + + morphology = "is"; + } + else if (baseForm.matches(@".*[szx(ch)(sh)]\\b")) + { + + morphology = baseForm + "es"; + } + else if (baseForm.matches(@".*[b-z-[eiou]]y\\b")) + { + + morphology = baseForm.replaceAll(@"y\b", "ies"); + } + else + { + morphology = baseForm + "s"; + } + } + return morphology; + } + + /** + * Builds the past-tense form for regular verbs. The rules are performed in + * this order: + *
    + *
  • If the verb is be and the number agreement is plural then + * the realised form is were.
  • + *
  • If the verb is be and the number agreement is singular then + * the realised form is was, unless the person is second, in which + * case it's were.
  • + *
  • For verbs ending -e the ending becomes -ed. For + * example, chased becomes chased.
  • + *
  • For verbs ending -Cy, where C is any consonant, the ending + * becomes -ied. For example, dry becomes dried.
  • + *
  • For every other verb, -ed is added to the end of the word.
  • + *
+ * + * @param baseForm + * the base form of the word. + * @param number + * the number agreement for the word. + * @param person + * the person + * @return the inflected word. + */ + + private static string buildRegularPastVerb(string baseForm, object number, object person) + { + string morphology = null; + if (baseForm != null) + { + if (baseForm.equalsIgnoreCase("be")) + { + + if (NumberAgreement.PLURAL.Equals(number)) + { + morphology = "were"; + + // AG - bug fix to handle second person past (courtesy of + // Minh Le) + } + else if (Person.SECOND.Equals(person)) + { + morphology = "were"; + } + else + { + morphology = "was"; + } + } + else if (baseForm.endsWith("e")) + { + + morphology = baseForm + "d"; + } + // NOTE .NET does not support character class subtraction + // ref: http://www.rexegg.com/regex-class-operations.html#intersection_workaround + // Java previous was: .*[b-z&&[^eiou]]y\\b + else if (baseForm.matches(".*[b-z-[eiou]]y\\b")) + { + + morphology = baseForm.replaceAll(@"y\b", "ied"); + } + else + { + morphology = baseForm + "ed"; + } + } + return morphology; + } + + /** + * Builds the past-tense form for verbs that follow the doubling form of the + * last consonant. -ed is added to the end after the last consonant + * is doubled. For example, tug becomes tugged. + * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildDoublePastVerb(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + morphology = baseForm + baseForm.charAt(baseForm.length() - 1) + "ed"; + } + return morphology; + } + + /** + * Builds the present participle form for regular verbs. The rules are + * performed in this order: + *
    + *
  • If the verb is be then the realised form is being.
  • + *
  • For verbs ending -ie the ending becomes -ying. For + * example, tie becomes tying.
  • + *
  • For verbs ending -ee, -oe or -ye then + * -ing is added to the end. For example, canoe becomes + * canoeing.
  • + *
  • For other verbs ending in -e the ending becomes + * -ing. For example, chase becomes chasing.
  • + *
  • For all other verbs, -ing is added to the end. For example, + * dry becomes drying.
  • + *
+ * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildRegularPresPartVerb(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + if (baseForm.equalsIgnoreCase("be")) + { + + morphology = "being"; + } + else if (baseForm.endsWith("ie")) + { + + morphology = baseForm.replaceAll(@"ie\b", "ying"); + } + else if (baseForm.matches(".*[^iyeo]e\\b")) + { + + morphology = baseForm.replaceAll(@"e\b", "ing"); + } + else + { + morphology = baseForm + "ing"; + } + } + return morphology; + } + + /** + * Builds the present participle form for verbs that follow the doubling + * form of the last consonant. -ing is added to the end after the + * last consonant is doubled. For example, tug becomes + * tugging. + * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildDoublePresPartVerb(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + morphology = baseForm + baseForm.charAt(baseForm.length() - 1) + "ing"; + } + return morphology; + } + + /** + * This method performs the morphology for adjectives. + * + * @param element + * the InflectedWordElement. + * @param baseWord + * the WordElement as created from the lexicon + * entry. + * @return a StringElement representing the word after + * inflection. + */ + + public static INLGElement doAdjectiveMorphology(InflectedWordElement element, WordElement baseWord) + { + + string realised = null; + var patternValue = element.getFeature(LexicalFeature.DEFAULT_INFL); + + // base form from baseWord if it exists, otherwise from element + var baseForm = getBaseForm(element, baseWord); + + if (element.getFeatureAsBoolean(Feature.IS_COMPARATIVE.ToString())) + { + realised = element.getFeatureAsString(LexicalFeature.COMPARATIVE); + + if (realised == null && baseWord != null) + { + realised = baseWord.getFeatureAsString(LexicalFeature.COMPARATIVE); + } + if (realised == null) + { + if (Inflection.REGULAR_DOUBLE.Equals(patternValue)) + { + realised = buildDoubleCompAdjective(baseForm); + } + else + { + realised = buildRegularComparative(baseForm); + } + } + } + else if (element.getFeatureAsBoolean(Feature.IS_SUPERLATIVE.ToString())) + { + + realised = element.getFeatureAsString(LexicalFeature.SUPERLATIVE); + + if (realised == null && baseWord != null) + { + realised = baseWord.getFeatureAsString(LexicalFeature.SUPERLATIVE); + } + if (realised == null) + { + if (Inflection.REGULAR_DOUBLE.Equals(patternValue)) + { + realised = buildDoubleSuperAdjective(baseForm); + } + else + { + realised = buildRegularSuperlative(baseForm); + } + } + } + else + { + realised = baseForm; + } + var realisedElement = new StringElement(realised); + realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), + element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString())); + return realisedElement; + } + + /** + * Builds the comparative form for adjectives that follow the doubling form + * of the last consonant. -er is added to the end after the last + * consonant is doubled. For example, fat becomes fatter. + * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildDoubleCompAdjective(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + morphology = baseForm + baseForm.charAt(baseForm.length() - 1) + "er"; + } + return morphology; + } + + /** + * Builds the comparative form for regular adjectives. The rules are + * performed in this order: + *
    + *
  • For adjectives ending -Cy, where C is any consonant, the + * ending becomes -ier. For example, brainy becomes + * brainier.
  • + *
  • For adjectives ending -e the ending becomes -er. + * For example, fine becomes finer.
  • + *
  • For all other adjectives, -er is added to the end. For + * example, clear becomes clearer.
  • + *
+ * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildRegularComparative(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + if (baseForm.matches(@".*[b-z-[eiou]]y\\b")) + { + + morphology = baseForm.replaceAll(@"y\b", "ier"); + } + else if (baseForm.endsWith("e")) + { + + morphology = baseForm + "r"; + } + else + { + morphology = baseForm + "er"; + } + } + return morphology; + } + + /** + * Builds the superlative form for adjectives that follow the doubling form + * of the last consonant. -est is added to the end after the last + * consonant is doubled. For example, fat becomes fattest. + * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildDoubleSuperAdjective(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + morphology = baseForm + baseForm.charAt(baseForm.length() - 1) + "est"; + } + return morphology; + } + + /** + * Builds the superlative form for regular adjectives. The rules are + * performed in this order: + *
    + *
  • For verbs ending -Cy, where C is any consonant, the ending + * becomes -iest. For example, brainy becomes + * brainiest.
  • + *
  • For verbs ending -e the ending becomes -est. For + * example, fine becomes finest.
  • + *
  • For all other verbs, -est is added to the end. For example, + * clear becomes clearest.
  • + *
+ * + * @param baseForm + * the base form of the word. + * @return the inflected word. + */ + + private static string buildRegularSuperlative(string baseForm) + { + string morphology = null; + if (baseForm != null) + { + if (baseForm.matches(@".*[b-z-[eiou]]y\\b")) + { + + morphology = baseForm.replaceAll(@"y\b", "iest"); + } + else if (baseForm.endsWith("e")) + { + + morphology = baseForm + "st"; + } + else + { + morphology = baseForm + "est"; + } + } + return morphology; + } + + /** + * This method performs the morphology for adverbs. + * + * @param element + * the InflectedWordElement. + * @param baseWord + * the WordElement as created from the lexicon + * entry. + * @return a StringElement representing the word after + * inflection. + */ + + public static INLGElement doAdverbMorphology(InflectedWordElement element, WordElement baseWord) + { + + string realised = null; + + // base form from baseWord if it exists, otherwise from element + var baseForm = getBaseForm(element, baseWord); + + if (element.getFeatureAsBoolean(Feature.IS_COMPARATIVE.ToString())) + { + realised = element.getFeatureAsString(LexicalFeature.COMPARATIVE); + + if (realised == null && baseWord != null) + { + realised = baseWord.getFeatureAsString(LexicalFeature.COMPARATIVE); + } + if (realised == null) + { + realised = buildRegularComparative(baseForm); + } + } + else if (element.getFeatureAsBoolean(Feature.IS_SUPERLATIVE.ToString())) + { + + realised = element.getFeatureAsString(LexicalFeature.SUPERLATIVE); + + if (realised == null && baseWord != null) + { + realised = baseWord.getFeatureAsString(LexicalFeature.SUPERLATIVE); + } + if (realised == null) + { + realised = buildRegularSuperlative(baseForm); + } + } + else + { + realised = baseForm; + } + var realisedElement = new StringElement(realised); + realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), + element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString())); + return realisedElement; + } + + /** + * This method performs the morphology for pronouns. + * + * @param element + * the InflectedWordElement. + * @return a StringElement representing the word after + * inflection. + */ + + public static INLGElement doPronounMorphology(InflectedWordElement element) + { + string realised = null; + + if (!element.getFeatureAsBoolean(InternalFeature.NON_MORPH.ToString()) && !isWHPronoun(element)) + { + var genderValue = element.getFeature(LexicalFeature.GENDER); + var personValue = element.getFeature(Feature.PERSON.ToString()); + var discourseValue = element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString()); + + var numberIndex = element.isPlural() ? 1 : 0; + var genderIndex = (genderValue is Gender) ? ((Gender) genderValue).ordinal() : 2; + + var personIndex = (personValue is Person) ? ((Person) personValue).ordinal() : 2; + + if (personIndex == 2) + { + personIndex += genderIndex; + } + + var positionIndex = 0; + + if (element.getFeatureAsBoolean(LexicalFeature.REFLEXIVE)) + { + positionIndex = 2; + } + else if (element.getFeatureAsBoolean(Feature.POSSESSIVE.ToString())) + { + positionIndex = 3; + if (DiscourseFunction.SPECIFIER.Equals(discourseValue)) + { + positionIndex++; + } + } + else + { + positionIndex = (DiscourseFunction.SUBJECT.Equals(discourseValue) && !element.getFeatureAsBoolean( + Feature.PASSIVE.ToString())) || + (DiscourseFunction.OBJECT.Equals(discourseValue) && + element.getFeatureAsBoolean(Feature.PASSIVE.ToString())) + || DiscourseFunction.SPECIFIER.Equals(discourseValue) || ( + DiscourseFunction.COMPLEMENT.Equals(discourseValue) + && element.getFeatureAsBoolean(Feature.PASSIVE.ToString())) + ? 0 + : 1; + } + realised = PRONOUNS[numberIndex][positionIndex][personIndex]; + } + else + { + realised = element.getBaseForm(); + } + var realisedElement = new StringElement(realised); + realisedElement.setFeature(InternalFeature.DISCOURSE_FUNCTION.ToString(), + element.getFeature(InternalFeature.DISCOURSE_FUNCTION.ToString())); + + return realisedElement; + } + + private static bool isWHPronoun(InflectedWordElement word) + { + var bases = word.getBaseForm(); + var wh = false; + + if (bases != null) + { + for (var i = 0; i < WH_PRONOUNS.Length && !wh; i++) + { + wh = WH_PRONOUNS[i].Equals(bases); + } + } + + return wh; + + } + + /** + * This method performs the morphology for determiners. + * + * @param determiner + * the InflectedWordElement. + * @param realisation + * the current realisation of the determiner. + */ + + public static void doDeterminerMorphology(INLGElement determiner, string realisation) + { + + if (realisation != null) + { + + if (!(determiner.getRealisation().Equals("a"))) + { + if (determiner.isPlural()) + { + // Use default inflection rules: + if ("that".Equals(determiner.getRealisation())) + { + determiner.setRealisation("those"); + } + else if ("this".Equals(determiner.getRealisation())) + { + determiner.setRealisation("these"); + } + } + else if (!determiner.isPlural()) + { + // Use default push back to base form rules: + if ("those".Equals(determiner.getRealisation())) + { + determiner.setRealisation("that"); + } + else if ("these".Equals(determiner.getRealisation())) + { + determiner.setRealisation("this"); + } + + } + } + + // Special "a" determiner and perform a/an agreement: + if (determiner.getRealisation().Equals("a")) + { + + if (determiner.isPlural()) + { + determiner.setRealisation("some"); + } + else if (DeterminerAgrHelper.requiresAn(realisation)) + { + determiner.setRealisation("an"); + } + } + + } + } + } +} \ No newline at end of file diff --git a/SharpSimpleNLGTests/syntax/ClauseAggregationTest.cs b/SharpSimpleNLGTests/syntax/ClauseAggregationTest.cs index 14e87ff..98e8388 100644 --- a/SharpSimpleNLGTests/syntax/ClauseAggregationTest.cs +++ b/SharpSimpleNLGTests/syntax/ClauseAggregationTest.cs @@ -42,7 +42,7 @@ public class ClauseAggregationTest : SimpleNLG4TestBase { // set up a few more fixtures /** The s4. */ - public SPhraseSpec s1, s2, s3, s4, s5, s6; + public SPhraseSpec s5, s6; public Aggregator aggregator = new Aggregator(); public ClauseCoordinationRule coord = new ClauseCoordinationRule(); public ForwardConjunctionReductionRule fcr = new ForwardConjunctionReductionRule(); @@ -56,7 +56,7 @@ public class ClauseAggregationTest : SimpleNLG4TestBase */ [SetUp] - protected void setUp() + protected override void setUp() { aggregator.initialise(); diff --git a/SharpSimpleNLGTests/syntax/DocumentElementTest.cs b/SharpSimpleNLGTests/syntax/DocumentElementTest.cs index 03e2945..6d526f5 100644 --- a/SharpSimpleNLGTests/syntax/DocumentElementTest.cs +++ b/SharpSimpleNLGTests/syntax/DocumentElementTest.cs @@ -50,7 +50,7 @@ public class DocumentElementTest : SimpleNLG4TestBase */ [SetUp] - protected void setUp() + protected override void setUp() { p1 = this.phraseFactory.createClause("you", "be", "happy"); p2 = this.phraseFactory.createClause("I", "be", "sad"); diff --git a/SharpSimpleNLGTests/syntax/InterrogativeTest.cs b/SharpSimpleNLGTests/syntax/InterrogativeTest.cs index 1fcdeb4..38190b2 100644 --- a/SharpSimpleNLGTests/syntax/InterrogativeTest.cs +++ b/SharpSimpleNLGTests/syntax/InterrogativeTest.cs @@ -40,11 +40,10 @@ public class InterrogativeTest : SimpleNLG4TestBase // set up a few more fixtures /** The s5. */ - SPhraseSpec s1, s2, s3, s4; [SetUp] - protected void setUp() + protected override void setUp() { // // the man gives the woman John's flower diff --git a/SharpSimpleNLGTests/syntax/OrthographyFormatTest.cs b/SharpSimpleNLGTests/syntax/OrthographyFormatTest.cs index 1b2a8cb..29df4c5 100644 --- a/SharpSimpleNLGTests/syntax/OrthographyFormatTest.cs +++ b/SharpSimpleNLGTests/syntax/OrthographyFormatTest.cs @@ -42,7 +42,7 @@ public class OrthographyFormatTest : SimpleNLG4TestBase public string list2Realisation; [SetUp] - public void setUp() + public new void setUp() { list2Realisation = new StringBuilder("* in the room").append("\n* ").append(list1Realisation).append("\n").ToString(); diff --git a/SharpSimpleNLGTests/syntax/SimpleNLG4Test.cs b/SharpSimpleNLGTests/syntax/SimpleNLG4Test.cs index f6cdee7..99f8453 100644 --- a/SharpSimpleNLGTests/syntax/SimpleNLG4Test.cs +++ b/SharpSimpleNLGTests/syntax/SimpleNLG4Test.cs @@ -68,7 +68,7 @@ public class SimpleNLG4TestBase */ [SetUp] - protected void setUp() + protected virtual void setUp() { this.lexicon = Lexicon.getDefaultLexicon(); diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..9e7d7a9 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,15 @@ +version: 1.0.{build} +image: Visual Studio 2017 +before_build: +- cmd: >- + dotnet restore + + nuget restore +build: + publish_nuget: true + publish_nuget_symbols: true + include_nuget_references: true + verbosity: minimal +before_package: +- cmd: nuget spec +test: off \ No newline at end of file