def testSection11(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory( lexicon ) realiser = Realiser( lexicon ) pA = nlgFactory.createClause( "Mary", "chase", "the monkey" ) pA.addComplement( "in the park" ) outputA = realiser.realiseSentence( pA ) self.assertEqual( "Mary chases the monkey in the park.", outputA ) # alternative build paradigm place = nlgFactory.createNounPhrase( "park" ) pB = nlgFactory.createClause( "Mary", "chase", "the monkey" ) # next line is depreciated ~ may be corrected in the API place.setDeterminer( "the" ) pp = nlgFactory.createPrepositionPhrase() pp.addComplement( place ) pp.setPreposition( "in" ) pB.addComplement( pp ) outputB = realiser.realiseSentence( pB ) self.assertEqual( "Mary chases the monkey in the park.", outputB ) place.addPreModifier( "leafy" ) outputC = realiser.realiseSentence( pB ) self.assertEqual( "Mary chases the monkey in the leafy park.", outputC )
def testEnumeratedList(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) realiser = Realiser(lexicon) realiser.setFormatter(HTMLFormatter()) document = nlgFactory.createDocument("Document") paragraph = nlgFactory.createParagraph() list_1 = nlgFactory.createEnumeratedList() item1 = nlgFactory.createListItem() item2 = nlgFactory.createListItem() # NB: a list item employs orthographical operations only until sentence level; # nest clauses within a sentence to generate more than 1 clause per list item. sentence1 = nlgFactory.createSentence("this", "be", "the first sentence") sentence2 = nlgFactory.createSentence("this", "be", "the second sentence") item1.addComponent(sentence1) item2.addComponent(sentence2) list_1.addComponent(item1) list_1.addComponent(item2) paragraph.addComponent(list_1) document.addComponent(paragraph) expectedOutput = "<h1>Document</h1>" + "<p>" + "<ol>" + "This is the first sentence." \ + "This is the second sentence." + "</ol>" + "</p>" realisedOutput = realiser.realise(document).getRealisation() self.assertEqual(expectedOutput, realisedOutput)
def testSection10(self): lexicon = Lexicon.getDefaultLexicon() # default simplenlg lexicon nlgFactory = NLGFactory( lexicon ) # factory based on lexicon realiser = Realiser( lexicon ) subject1 = nlgFactory.createNounPhrase( "Mary" ) subject2 = nlgFactory.createNounPhrase( "your", "giraffe" ) # next line is not correct ~ should be nlgFactory.createCoordinatedPhrase ~ may be corrected in the API subj = nlgFactory.createCoordinatedPhrase( subject1, subject2 ) verb = nlgFactory.createVerbPhrase( "chase" ) p = nlgFactory.createClause() p.setSubject( subj ) p.setVerb( verb ) p.setObject( "the monkey" ) outputA = realiser.realiseSentence( p ) self.assertEqual( "Mary and your giraffe chase the monkey.", outputA ) object1 = nlgFactory.createNounPhrase( "the monkey" ) object2 = nlgFactory.createNounPhrase( "George" ) # next line is not correct ~ should be nlgFactory.createCoordinatedPhrase ~ may be corrected in the API obj = nlgFactory.createCoordinatedPhrase( object1, object2 ) obj.addCoordinate( "Martha" ) p.setObject( obj ) outputB = realiser.realiseSentence( p ) self.assertEqual( "Mary and your giraffe chase the monkey, George and Martha.", outputB ) obj.setFeature( Feature.CONJUNCTION, "or" ) outputC = realiser.realiseSentence( p ) self.assertEqual( "Mary and your giraffe chase the monkey, George or Martha.", outputC )
def testSection3(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) s1 = nlgFactory.createSentence("my dog is happy") r = Realiser(lexicon) output = r.realiseSentence(s1) self.assertEqual("My dog is happy.", output)
def testSection5(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) realiser = Realiser(lexicon) p = nlgFactory.createClause() p.setSubject("my dog") p.setVerb("chase") p.setObject("George") output = realiser.realiseSentence(p) self.assertEqual("My dog chases George.", output)
def testSection5A(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory( lexicon ) realiser = Realiser( lexicon ) p = nlgFactory.createClause() p.setSubject( "Mary" ) p.setVerb( "chase" ) p.setObject( "the monkey" ) output = realiser.realiseSentence( p ) self.assertEqual( "Mary chases the monkey.", output )
def __init__(self): verb2noun, noun2verb, verb2actor, actor2verb = utils.noun_verb( prop.morph_verb) self.verb2noun = verb2noun self.verb2actor = verb2actor sub2word = utils.subgraph_word(prop.verbalization) self.sub2word = sub2word lexicon = Lexicon.getDefaultLexicon() self.nlgFactory = NLGFactory(lexicon) self.realiser = Realiser(lexicon)
class StandAloneExample(unittest.TestCase): def setUp(self): self.lexicon = XMLLexicon() self.nlgFactory = NLGFactory(self.lexicon) self.realiser = Realiser(self.lexicon) def testSentenceCreation(self): # create sentences thePark = self.nlgFactory.createNounPhrase("the", "park") bigp = self.nlgFactory.createAdjectivePhrase("big") bigp.setFeature(Feature.IS_COMPARATIVE, True) thePark.addModifier(bigp) # above relies on default placement rules. You can force placement as a premodifier # (before head) by using addPreModifier toThePark = self.nlgFactory.createPrepositionPhrase("to") toThePark.setObject(thePark) # could also just say self.nlgFactory.createPrepositionPhrase("to", the Park) johnGoToThePark = self.nlgFactory.createClause("John", "go", toThePark) johnGoToThePark.setFeature(Feature.TENSE, Tense.PAST) johnGoToThePark.setFeature(Feature.NEGATED, True) # note that constituents (such as subject and object) are set with setXXX methods # while features are set with setFeature sentence = self.nlgFactory.createSentence(johnGoToThePark) # below creates a sentence DocumentElement by concatenating strings hePlayed = StringElement("he played") there = StringElement("there") football = WordElement("football") sentence2 = self.nlgFactory.createSentence() sentence2.addComponent(hePlayed) sentence2.addComponent(football) sentence2.addComponent(there) # now create a paragraph which contains these sentences paragraph = self.nlgFactory.createParagraph() paragraph.addComponent(sentence) paragraph.addComponent(sentence2) realised = self.realiser.realise(paragraph).getRealisation() # Test self.assertEqual( "John did not go to the bigger park. He played football there.\n\n", realised) def testMorphology(self): # second example - using simplenlg just for morphology word = self.nlgFactory.createWord("child", LexicalCategory.NOUN) # create InflectedWordElement from word element inflectedWord = InflectedWordElement(word) # set the inflected word to plural inflectedWord.setPlural(True) # realise the inflected word realised = self.realiser.realise(inflectedWord).getRealisation() # Test self.assertEqual('children', realised)
def testSection7(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory( lexicon ) realiser = Realiser( lexicon ) p = nlgFactory.createClause() p.setSubject( "Mary" ) p.setVerb( "chase" ) p.setObject( "the monkey" ) p.addComplement( "very quickly" ) p.addComplement( "despite her exhaustion" ) output = realiser.realiseSentence( p ) self.assertEqual( "Mary chases the monkey very quickly despite her exhaustion.", output )
def testEnumeratedList(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) realiser = Realiser(lexicon) realiser.setFormatter(TextFormatter()) document = nlgFactory.createDocument("Document") paragraph = nlgFactory.createParagraph() subListItem1 = nlgFactory.createListItem() subListSentence1 = nlgFactory.createSentence("this", "be", "sub-list sentence 1") subListItem1.addComponent(subListSentence1) subListItem2 = nlgFactory.createListItem() subListSentence2 = nlgFactory.createSentence("this", "be", "sub-list sentence 2") subListItem2.addComponent(subListSentence2) subList = nlgFactory.createEnumeratedList() subList.addComponent(subListItem1) subList.addComponent(subListItem2) item1 = nlgFactory.createListItem() sentence1 = nlgFactory.createSentence("this", "be", "the first sentence") item1.addComponent(sentence1) item2 = nlgFactory.createListItem() sentence2 = nlgFactory.createSentence("this", "be", "the second sentence") item2.addComponent(sentence2) list_1 = nlgFactory.createEnumeratedList() list_1.addComponent(subList) list_1.addComponent(item1) list_1.addComponent(item2) paragraph.addComponent(list_1) document.addComponent(paragraph) expectedOutput = "Document\n" + \ "\n" + \ "1.1 - This is sub-list sentence 1.\n" + \ "1.2 - This is sub-list sentence 2.\n"+ \ "2 - This is the first sentence.\n" + \ "3 - This is the second sentence.\n" + \ "\n\n" # for the end of a paragraph realisedOutput = realiser.realise(document).getRealisation() self.assertEquals(expectedOutput, realisedOutput)
def replace_plural_head(head): print(head.text) if (head.text == "'re"): return "'s" regex = re.compile('[a-z]+') lex = Lexicon.getDefaultLexicon() realiser = Realiser(lex) nlgFactory = NLGFactory(lex) p = nlgFactory.createClause() p.setVerb(head.text) p.setSubject("she") verb_match = regex.match(realiser.realiseSentence(p).split(" ")[1]) if (verb_match): return verb_match.group() else: return head.text
class PremodifierTest(unittest.TestCase): # @Before def setUp(self): self.lexicon = Lexicon.getDefaultLexicon() self.phraseFactory = NLGFactory(self.lexicon) self.realiser = Realiser(self.lexicon) # Test change from "a" to "an" in the presence of a premodifier with a vowel def testIndefiniteWithPremodifier(self): s = self.phraseFactory.createClause("there", "be") s.setFeature(Feature.TENSE, Tense.PRESENT) np = self.phraseFactory.createNounPhrase("a", "stenosis") s.setObject(np) # check without modifiers -- article should be "a" self.assertEqual("there is a stenosis", self.realiser.realise(s).getRealisation()) # add a single modifier -- should turn article to "an" np.addPreModifier( self.phraseFactory.createAdjectivePhrase("eccentric")) self.assertEqual("there is an eccentric stenosis", self.realiser.realise(s).getRealisation()) # Test for comma separation between premodifers def testMultipleAdjPremodifiers(self): np = self.phraseFactory.createNounPhrase("a", "stenosis") np.addPreModifier( self.phraseFactory.createAdjectivePhrase("eccentric")) np.addPreModifier(self.phraseFactory.createAdjectivePhrase("discrete")) self.assertEqual("an eccentric, discrete stenosis", self.realiser.realise(np).getRealisation()) # Test for comma separation between verb premodifiers def testMultipleAdvPremodifiers(self): adv1 = self.phraseFactory.createAdverbPhrase("slowly") adv2 = self.phraseFactory.createAdverbPhrase("discretely") # case 1: concatenated premods: should have comma vp = self.phraseFactory.createVerbPhrase("run") vp.addPreModifier(adv1) vp.addPreModifier(adv2) self.assertEqual("slowly, discretely runs", self.realiser.realise(vp).getRealisation()) # case 2: coordinated premods: no comma vp2 = self.phraseFactory.createVerbPhrase("eat") vp2.addPreModifier( self.phraseFactory.createCoordinatedPhrase(adv1, adv2)) self.assertEqual("slowly and discretely eats", self.realiser.realise(vp2).getRealisation())
def testSection8(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory( lexicon ) realiser = Realiser( lexicon ) subject = nlgFactory.createNounPhrase( "Mary" ) object = nlgFactory.createNounPhrase( "the monkey" ) verb = nlgFactory.createVerbPhrase( "chase" ) subject.addModifier( "fast" ) p = nlgFactory.createClause() p.setSubject( subject ) p.setVerb( verb ) p.setObject( object ) outputA = realiser.realiseSentence( p ) self.assertEqual( "Fast Mary chases the monkey.", outputA ) verb.addModifier( "quickly" ) outputB = realiser.realiseSentence( p ) self.assertEqual( "Fast Mary quickly chases the monkey.", outputB )
def testSection14(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory( lexicon ) realiser = Realiser( lexicon ) p1 = nlgFactory.createClause( "Mary", "chase", "the monkey" ) p2 = nlgFactory.createClause( "The monkey", "fight back" ) p3 = nlgFactory.createClause( "Mary", "be", "nervous" ) s1 = nlgFactory.createSentence( p1 ) s2 = nlgFactory.createSentence( p2 ) s3 = nlgFactory.createSentence( p3 ) par1 = nlgFactory.createParagraph( [s1, s2, s3] ) output14a = realiser.realise( par1 ).getRealisation() correct = "Mary chases the monkey. The monkey fights back. Mary is nervous.\n\n" self.assertEqual(correct, output14a ) section = nlgFactory.createSection( "The Trials and Tribulation of Mary and the Monkey" ) section.addComponent( par1 ) output14b = realiser.realise( section ).getRealisation() correct = "The Trials and Tribulation of Mary and the Monkey\nMary chases the monkey. " + \ "The monkey fights back. Mary is nervous.\n\n" self.assertEqual(correct, output14b )
def testSection13(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory( lexicon ) realiser = Realiser( lexicon ) s1 = nlgFactory.createClause( "my cat", "like", "fish" ) s2 = nlgFactory.createClause( "my dog", "like", "big bones" ) s3 = nlgFactory.createClause( "my horse", "like", "grass" ) c = nlgFactory.createCoordinatedPhrase() c.addCoordinate( s1 ) c.addCoordinate( s2 ) c.addCoordinate( s3 ) outputA = realiser.realiseSentence( c ) correct = "My cat likes fish, my dog likes big bones and my horse likes grass." self.assertEqual(correct, outputA ) p = nlgFactory.createClause( "I", "be", "happy" ) q = nlgFactory.createClause( "I", "eat", "fish" ) q.setFeature( Feature.COMPLEMENTISER, "because" ) q.setFeature( Feature.TENSE, Tense.PAST ) p.addComplement( q ) outputB = realiser.realiseSentence( p ) self.assertEqual( "I am happy because I ate fish.", outputB )
def testSection6(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) realiser = Realiser(lexicon) p = nlgFactory.createClause() p.setSubject("Mary") p.setVerb("chase") p.setObject("George") p.setFeature(Feature.TENSE, Tense.PAST) output = realiser.realiseSentence(p) self.assertEqual("Mary chased George.", output) p.setFeature(Feature.TENSE, Tense.FUTURE) output = realiser.realiseSentence(p) self.assertEqual("Mary will chase George.", output) p.setFeature(Feature.NEGATED, True) output = realiser.realiseSentence(p) self.assertEqual("Mary will not chase George.", output) p = nlgFactory.createClause() p.setSubject("Mary") p.setVerb("chase") p.setObject("George") p.setFeature(Feature.INTERROGATIVE_TYPE, InterrogativeType.YES_NO) output = realiser.realiseSentence(p) self.assertEqual("Does Mary chase George?", output) p.setSubject("Mary") p.setVerb("chase") p.setFeature(Feature.INTERROGATIVE_TYPE, InterrogativeType.WHO_OBJECT) output = realiser.realiseSentence(p) self.assertEqual("Who does Mary chase?", output) p = nlgFactory.createClause() p.setSubject("the dog") p.setVerb("wake up") output = realiser.realiseSentence(p) self.assertEqual("The dog wakes up.", output)
def setUp(self): self.lexicon = XMLLexicon() self.phraseFactory = NLGFactory(self.lexicon) self.realiser = Realiser(self.lexicon) self.man = self.phraseFactory.createNounPhrase("the", "man") self.woman = self.phraseFactory.createNounPhrase("the", "woman") self.dog = self.phraseFactory.createNounPhrase("the", "dog") self.boy = self.phraseFactory.createNounPhrase("the", "boy") self.beautiful = self.phraseFactory.createAdjectivePhrase("beautiful") self.stunning = self.phraseFactory.createAdjectivePhrase("stunning") self.salacious = self.phraseFactory.createAdjectivePhrase("salacious") self.onTheRock = self.phraseFactory.createPrepositionPhrase("on") self.np4 = self.phraseFactory.createNounPhrase("the", "rock") self.onTheRock.addComplement(self.np4) self.behindTheCurtain = self.phraseFactory.createPrepositionPhrase("behind") self.np5 = self.phraseFactory.createNounPhrase("the", "curtain") self.behindTheCurtain.addComplement(self.np5) self.inTheRoom = self.phraseFactory.createPrepositionPhrase("in") self.np6 = self.phraseFactory.createNounPhrase("the", "room") self.inTheRoom.addComplement(self.np6) self.underTheTable = self.phraseFactory.createPrepositionPhrase("under") self.underTheTable.addComplement(self.phraseFactory.createNounPhrase("the", "table")) self.proTest1 = self.phraseFactory.createNounPhrase("the", "singer") self.proTest2 = self.phraseFactory.createNounPhrase("some", "person") self.kick = self.phraseFactory.createVerbPhrase("kick") self.kiss = self.phraseFactory.createVerbPhrase("kiss") self.walk = self.phraseFactory.createVerbPhrase("walk") self.talk = self.phraseFactory.createVerbPhrase("talk") self.getUp = self.phraseFactory.createVerbPhrase("get up") self.fallDown = self.phraseFactory.createVerbPhrase("fall down") self.give = self.phraseFactory.createVerbPhrase("give") self.say = self.phraseFactory.createVerbPhrase("say")
def testVariants(self): lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) realiser = Realiser(lexicon) p = nlgFactory.createClause() p.setSubject("my dog") p.setVerb("is") # variant of be p.setObject("George") output = realiser.realiseSentence(p) self.assertEqual("My dog is George.", output) p = nlgFactory.createClause() p.setSubject("my dog") p.setVerb("chases") # variant of chase p.setObject("George") output = realiser.realiseSentence(p) self.assertEqual("My dog chases George.", output) p = nlgFactory.createClause() p.setSubject(nlgFactory.createNounPhrase("the", "dogs")) # variant of "dog" p.setVerb("is") # variant of be p.setObject("happy") # variant of happy output = realiser.realiseSentence(p) self.assertEqual("The dog is happy.", output) p = nlgFactory.createClause() p.setSubject(nlgFactory.createNounPhrase("the", "children")) # variant of "child" p.setVerb("is") # variant of be p.setObject("happy") # variant of happy output = realiser.realiseSentence(p) self.assertEqual("The child is happy.", output) # following functionality is enabled p = nlgFactory.createClause() p.setSubject(nlgFactory.createNounPhrase("the", "dogs")) # variant of "dog" p.setVerb("is") # variant of be p.setObject("happy") # variant of happy output = realiser.realiseSentence(p) self.assertEqual("The dog is happy.", output) #corrected automatically
# Bottle will handle the HTTP side of things from bottle import route, run, request, response # SimpleNLG will do the NLG generation from simplenlg.framework import NLGFactory, CoordinatedPhraseElement, ListElement, PhraseElement from simplenlg.lexicon import Lexicon from simplenlg.realiser.english import Realiser from simplenlg.features import Feature, Tense, NumberAgreement from simplenlg.phrasespec import NPPhraseSpec from java.lang import Boolean # We only need one instance of these, so we'll create them globally. lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) realiser = Realiser(lexicon) # Process the request to http://host:port/generateSentence @route('/generateSentence', method="POST") def process_generate_sentence_request(): try: # Generate the sentence from the JSON payload. return realiser.realiseSentence(generate_sentence(request.json)) except Exception, e: print e response.status = 400 # If any exceptions are thrown, set status to 400, and return the error string return str(e)
def __init__(self, process_proper_nouns=False): self.lexicon = Lexicon.getDefaultLexicon() self.realiser = Realiser(self.lexicon) self.process_proper_nouns = process_proper_nouns
class AbstractNLPProcessor: def __init__(self, process_proper_nouns=False): self.lexicon = Lexicon.getDefaultLexicon() self.realiser = Realiser(self.lexicon) self.process_proper_nouns = process_proper_nouns def grammar(self): NP = '<ADV|ADJ>*<NOUN|PROPN|PRP|PRP$>+<PART>?<NUM>?' if self.process_proper_nouns is True: return """ NP: {{(<ADV|ADJ>*<NOUN>+<PART>?<NUM>?)+(<ADP>*<DET>?{NP})*}} VP: {{<VERB>+<ADP>?}} PNP: {{<PROPN>+}} """.format(NP=NP) else: return """ NP: {{({NP})+(<ADP>*<DET>?{NP})*}} VP: {{<VERB>+<ADP>?}} PNP: {{<PROPN>+}} """.format(NP=NP) @abstractmethod def extract_named_entities(self, token): pass def get_named_entity(self, token, index=0): if token is None: return token entities = self.extract_named_entities(token) if entities is None or len(entities) == 0 or len(entities) + 1 < index: return None return entities[index] @abstractmethod def get_named_entity_types(self, token): pass def get_named_entity_type(self, token, index=0): if token is None: return token types = self.get_named_entity_types(token) if types is None or len(types) == 0 or len(types) + 1 < index: return None return types[index] def _extract_phrase(self, tagged, chunk_label): cp = nltk.RegexpParser(self.grammar()) tree = cp.parse(tagged) return [ ' '.join(s for s, t in subtree).replace(" '", "'") for subtree in tree.subtrees() if subtree.label() == chunk_label ] @abstractmethod def extract_phrase_by_type(self, token, type): pass def extract_noun_phrases(self, token): if token is None: return None return self.extract_phrase_by_type(token, "NP") def extract_proper_nouns(self, token): if token is None: return None return self.extract_phrase_by_type(token, "PNP") def extract_verb_phrases(self, token): if token is None: return None return self.extract_phrase_by_type(token, "VP") def extract_verb_phrase(self, token): verbs = self.extract_verb_phrases(token) if verbs is not None and len(verbs) > 0: return verbs[0] return None def normalize_verb(self, verb): if verb is None: return verb def normalize(vb): word = self.lexicon.getWord(self.lemma(vb, pos=wordnet.VERB), LexicalCategory.VERB) infl = InflectedWordElement(word) infl.setFeature(Feature.TENSE, Tense.PRESENT) return self.realiser.realise(infl).getRealisation() return ' '.join( normalize(t) if ind == 0 else t for ind, t in enumerate(verb.split())) def lemma(self, token, pos=wordnet.NOUN): if token is None: return token lemmatizer = WordNetLemmatizer() return lemmatizer.lemmatize(token, pos) def is_synonym(self, first, second): synonyms = [[l.name() for l in sn.lemmas()] for sn in wn.synsets(second.replace(' ', '_'), 'n')] synonyms = list(itertools.chain.from_iterable(synonyms)) synonyms = [s for s in synonyms if s != second] synonyms = [s.replace('_', ' ') for s in synonyms] return first in synonyms def is_meronym(self, first, second): meronyms = [ list( itertools.chain.from_iterable( [s.lemma_names('eng') for s in sn.part_meronyms()])) for sn in wn.synsets(second.replace(' ', '_'), 'n') ] meronyms = list(itertools.chain.from_iterable(meronyms)) meronyms = [s.replace('_', ' ') for s in meronyms] return first in meronyms def is_holonym(self, first, second): holonyms = [ list( itertools.chain.from_iterable( [s.lemma_names('eng') for s in sn.part_holonyms()])) for sn in wn.synsets(second.replace(' ', '_'), 'n') ] holonyms = list(itertools.chain.from_iterable(holonyms)) holonyms = [s.replace('_', ' ') for s in holonyms] return first in holonyms def is_hyponym(self, first, second): hyponyms = [ list( itertools.chain.from_iterable( [s.lemma_names('eng') for s in sn.hyponyms()])) for sn in wn.synsets(second.replace(' ', '_'), 'n') ] hyponyms = list(itertools.chain.from_iterable(hyponyms)) hyponyms = [s.replace('_', ' ') for s in hyponyms] return first in hyponyms def is_hypernym(self, first, second, full_hierarchy=False): if full_hierarchy is False: hypernyms = [ list( itertools.chain.from_iterable( [s.lemma_names('eng') for s in sn.hypernyms()])) for sn in wn.synsets(second.replace(' ', '_'), 'n') ] hypernyms = list(itertools.chain.from_iterable(hypernyms)) else: hypernyms = self._hypernyms_full(second) hypernyms = set(hypernyms) hypernyms = [s.replace('_', ' ') for s in hypernyms] return first in hypernyms def _flatten(self, list_): for el in list_: if isinstance(el, Iterable) and not isinstance(el, (str, bytes)): yield from self._flatten(el) else: yield el def _hypernyms_full(self, word): # Collect full hierarchy of possible hypernyms def collect_hypernyms(sn): def add_hypernyms(hypernyms, synsets): if synsets is None: return hypernyms hypernyms.extend([s.lemma_names('eng') for s in synsets]) for p in synsets: add_hypernyms(hypernyms, p.hypernyms()) return hypernyms hyplist = list() return add_hypernyms(hyplist, sn) hypernyms = list( map(lambda x: collect_hypernyms(x.hypernyms()), wn.synsets(word.replace(' ', '_'), 'n'))) return list(self._flatten(hypernyms))
class Realizer(object): def __init__(self): verb2noun, noun2verb, verb2actor, actor2verb = utils.noun_verb( prop.morph_verb) self.verb2noun = verb2noun self.verb2actor = verb2actor sub2word = utils.subgraph_word(prop.verbalization) self.sub2word = sub2word lexicon = Lexicon.getDefaultLexicon() self.nlgFactory = NLGFactory(lexicon) self.realiser = Realiser(lexicon) def create_clause(self, subject, vp, _object, frontmodifiers, complements): phrase = self.nlgFactory.createClause() phrase.setSubject(subject) phrase.setVerbPhrase(vp) if _object != None: phrase.setObject(_object) for frontmodifier in frontmodifiers: phrase = self.add_frontmodifier(phrase, frontmodifier) for complement in complements: phrase = self.add_complement(phrase, complement) return phrase def create_np(self, determiner, head, number, premodifiers, postmodifiers): np = self.nlgFactory.createNounPhrase() np.setNoun(head) if determiner != '': np.setDeterminer(determiner) if number == 'singular': np.setFeature(Feature.NUMBER, NumberAgreement.SINGULAR) elif number == 'plural': np.setFeature(Feature.NUMBER, NumberAgreement.PLURAL) for premodifier in premodifiers: np = self.add_premodifier(np, premodifier) for postmodifier in postmodifiers: np = self.add_postmodifier(np, postmodifier) return np def create_vp(self, sentence): verb = sentence['verb'] voice = sentence['voice'] tense = sentence['tense'] perfect = sentence['perfect'] form = sentence['form'] modal = sentence['modal'] vp = self.nlgFactory.createVerbPhrase() vp.setVerb(verb) if tense == "past": vp.setFeature(Feature.TENSE, Tense.PAST) elif tense == "present": vp.setFeature(Feature.TENSE, Tense.PRESENT) elif tense == "future": vp.setFeature(Feature.TENSE, Tense.FUTURE) if voice == "active": vp.setFeature(Feature.PASSIVE, Boolean(False)) else: vp.setFeature(Feature.PASSIVE, Boolean(True)) if perfect: vp.setFeature(Feature.PERFECT, Boolean(True)) else: vp.setFeature(Feature.PERFECT, Boolean(False)) if form == 'negative': vp.setFeature(Feature.NEGATED, Boolean(True)) elif form == 'infinitive': vp.setFeature(Feature.FORM, Form.INFINITIVE) if modal == 'possible': vp.setFeature(Feature.MODAL, "can") elif modal == 'obligate': vp.setFeature(Feature.MODAL, "must") elif modal == 'permit': vp.setFeature(Feature.MODAL, "may") elif modal == 'recommend': vp.setFeature(Feature.MODAL, "should") return vp def create_pp(self, preposition, np): pp = self.nlgFactory.createPrepositionPhrase() pp.addComplement(np) pp.setPreposition(preposition) return pp def create_adjp(self, adjective): adjp = self.nlgFactory.createAdjectivePhrase(adjective) return adjp def create_advp(self, adverb): advp = self.nlgFactory.createAdverbPhrase(adverb) return advp def create_possessive(self): np = self.nlgFactory.createNounPhrase() np.setFeature(Feature.PRONOMINAL, Boolean(True)) np.setFeature(Feature.POSSESSIVE, Boolean(True)) return np def add_complement(self, phrase, complement): phrase.addComplement(complement) return phrase def add_premodifier(self, phrase, premodifier): phrase.addPreModifier(premodifier) return phrase def add_postmodifier(self, phrase, postmodifier): phrase.addPostModifier(postmodifier) return phrase def add_frontmodifier(self, phrase, frontmodifier): phrase.addFrontModifier(frontmodifier) return phrase def add_complementiser(self, phrase, complement): phrase.setFeature(Feature.COMPLEMENTISER, complement) return phrase def process_np(self, root): determiner, premodifiers, head, postmodifiers = '', [], '', [] for node in self.tree.edges[root]: if self.tree.nodes[node].type == 'terminal': if self.tree.nodes[node].name == 'DT': determiner = self.tree.nodes[node].lexicon elif self.tree.nodes[node].label > -1 and self.tree.nodes[ node].rule_id == self.tree.nodes[root].rule_id: head = self.tree.nodes[node].lexicon elif self.tree.nodes[node].name == 'PRP$': mod = self.create_possessive() premodifiers.append(mod) else: mod = self.tree.nodes[node].lexicon if head == '': premodifiers.append(mod) else: postmodifiers.append(mod) else: mod = self.process(node) if mod != None: if head == '': premodifiers.append(mod) else: postmodifiers.append(mod) if head == '': head = copy.copy(determiner) determiner = '' p = self.create_np(determiner=determiner, head=head, number='singular', premodifiers=premodifiers, postmodifiers=postmodifiers) return p def process_vp(self, root, sentence): for node in self.tree.edges[root]: if self.tree.nodes[node].type == 'terminal': # treat modals if self.tree.nodes[node].name == 'MD': sentence['modal'] = self.tree.nodes[node].lexicon # treat infinitive elif self.tree.nodes[node].name == 'TO': sentence['form'] = 'infinitive' # treat negative elif self.tree.nodes[node].lexicon == 'not': sentence['form'] = 'negative' elif self.tree.nodes[node].name == 'VB': sentence['verb'] = self.tree.nodes[node].lexicon # if self.tree.nodes[node].label > -1 and self.tree.nodes[node].rule_id == self.tree.nodes[root].rule_id: # sentence['verb'] = self.tree.nodes[node].lexicon else: if self.tree.nodes[node].name == 'VP': sentence = self.process_vp(node, sentence) else: p = self.process(node) if p != None: rule_id = self.tree.nodes[node].rule_id rule = self.synchg.rules[rule_id] edge = rule.name.split('/')[0] pos = self.tree.nodes[node].name if 'NP' in pos: if edge == ':ARG1' and sentence[ 'voice'] == 'active': sentence['object'] = p else: sentence['complements'].append(p) elif pos == 'PP': if edge == ':ARG0' and sentence[ 'voice'] == 'passive': p = p.getChildren()[1] sentence['subject'] = p else: sentence['complements'].append(p) else: sentence['complements'].append(p) return sentence def process_pp(self, root): preposition, np = '', None for node in self.tree.edges[root]: if self.tree.nodes[node].type == 'terminal': preposition = self.tree.nodes[node].lexicon else: np = self.process(node) p = self.create_pp(preposition, np) return p def process_adjvp(self, root): premodifiers, head, postmodifiers = [], '', [] for node in self.tree.edges[root]: if self.tree.nodes[node].type == 'terminal': if self.tree.nodes[node].label > -1 and self.tree.nodes[ node].rule_id == self.tree.nodes[root].rule_id: head = self.tree.nodes[node].lexicon else: mod = self.tree.nodes[node].lexicon if head == '': premodifiers.append(mod) else: postmodifiers.append(mod) else: mod = self.process(node) if head == '': premodifiers.append(mod) else: postmodifiers.append(mod) if self.tree.nodes[root].name == 'ADJP': p = self.create_adjp(head) else: p = self.create_advp(head) for premodifier in premodifiers: self.add_premodifier(p, premodifier) for postmodifier in postmodifiers: self.add_postmodifier(p, postmodifier) return p def process_s(self, root): # get voice rule_id = self.tree.nodes[root].rule_id rule = self.synchg.rules[rule_id] voice = rule.features.voice sentence = { 'subject': None, 'object': None, 'verb': '', 'tense': 'present', 'modal': '', 'voice': voice, 'perfect': False, 'form': 'affirmative', 'frontmodifiers': [], 'complements': [] } for node in self.tree.edges[root]: if self.tree.nodes[node].name not in ['.', ':']: rule_id = self.tree.nodes[node].rule_id rule = self.synchg.rules[rule_id] edge = rule.name.split('/')[0] pos = self.tree.nodes[node].name if pos == 'VP': sentence = self.process_vp(node, sentence) else: p = self.process(node) if 'NP' in pos: if edge == ':ARG0': sentence['subject'] = p elif edge == ':ARG1': if voice == 'active': sentence['subject'] = p else: sentence['object'] = p else: if sentence['verb'] == '': sentence['frontmodifiers'].append(p) else: sentence['complements'].append(p) elif pos == 'PP': if edge == ':ARG0' and self.voice == 'passive': p = p.getChildren()[1] sentence['subject'] = p else: if sentence['verb'] == '': sentence['frontmodifiers'].append(p) else: sentence['complements'].append(p) vp = self.create_vp(sentence) subject = sentence['subject'] object = sentence['object'] frontmodifiers = sentence['frontmodifiers'] complements = sentence['complements'] p = self.create_clause(subject=subject, vp=vp, _object=object, frontmodifiers=frontmodifiers, complements=complements) return p def process_sbar(self, root): p, complement = None, 'that' for node in self.tree.edges[root]: if self.tree.nodes[node].name == 'S': p = self.process_s(node) elif self.tree.nodes[node].name[0] == 'W': child = self.tree.edges[node][0] complement = self.tree.nodes[child].lexicon if p != None: p = self.add_complementiser(p, complement) return p def check_coordination(self, root): pass def process(self, root): if self.tree.nodes[root].name == 'S': p = self.process_s(root) # SUBORDINATE CLAUSE elif self.tree.nodes[root].name == 'SBAR': p = self.process_sbar(root) # NOUN PHRASE elif 'NP' in self.tree.nodes[root].name: p = self.process_np(root) # PREPOSITIONAL PHRASES elif self.tree.nodes[root].name == 'PP': p = self.process_pp(root) # ADJECTIVE AND ADVERBIAL PHRASES elif self.tree.nodes[root].name in ['ADJP', 'ADVP']: p = self.process_adjvp(root) elif self.tree.nodes[root].name == 'FRAG': p = self.process(self.tree.edges[root][0]) else: p = None return p def run(self, tree, synchg): self.tree = tree self.synchg = synchg root = tree.root # TO DO: treat multi sentences if self.tree.nodes[root].name == 'MULTI-SENTENCE': p = None else: root = self.tree.edges[self.tree.root][0] self.subject, self.vp, self.object = None, None, None self.complements, self.frontmodifiers = [], [] p = self.process(root) if p != None: return self.realiser.realise(p) else: return '-'
from simplenlg.framework.LexicalCategory import * from simplenlg.framework.NLGFactory import * from simplenlg.realiser.english.Realiser import * lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(self.lexicon) realiser = Realiser(self.lexicon) nlgFactory.createSentence()
def setUp(self): self.lexicon = XMLLexicon() self.nlgFactory = NLGFactory(self.lexicon) self.realiser = Realiser(self.lexicon)
import sys, os sys.path.append(os.path.join(os.path.dirname(__file__), "SimpleNLG-4.4.8.jar")) from simplenlg.framework import NLGFactory, CoordinatedPhraseElement, ListElement, PhraseElement from simplenlg.lexicon import Lexicon from simplenlg.realiser.english import Realiser from simplenlg.features import Feature, Tense, NumberAgreement from simplenlg.phrasespec import NPPhraseSpec from java.lang import Boolean lexicon = Lexicon.getDefaultLexicon() nlgFactory = NLGFactory(lexicon) realiser = Realiser(lexicon) print("hello world") p = nlgFactory.createSentence("my dog is happy") sentence = realiser.realiseSentence(p) print(sentence) p = nlgFactory.createClause() p.setSubject("Mary") p.setVerb("chase") p.setObject("the monkey") sentence2 = realiser.realiseSentence(p) print(sentence2)
# from simplenlg.phrasespec.NPPhraseSpec import * # from simplenlg.phrasespec.PPPhraseSpec import * # from simplenlg.phrasespec.SPhraseSpec import * # from simplenlg.phrasespec.VPPhraseSpec import * from simplenlg.realiser.english.Realiser import * from simplenlg.phrasespec import * # The hot resources : # https://pypi.org/project/simplenlg/ # https://github.com/bjascob/pySimpleNLG # https://github.com/simplenlg/simplenlg/wiki lexicon = Lexicon.getDefaultLexicon() factory = NLGFactory(lexicon) realiser = Realiser(lexicon) sentence1 = factory.createSentence() subject1 = factory.createNounPhrase('the', 'cat') sentence1.addComponent(subject1) # use addComponent not setSubject verb1 = factory.createVerbPhrase('jump') sentence1.addComponent(verb1) print(realiser.realise(sentence1)) # sentence1.setFeature(Feature.TENSE, Tense.PAST) # print(realiser.realise(sentence1)) -- don't work :( # Look - using a clause instead of a sentence made tense switching work : # the reason is because you can use setSubject on clauses, not sentences clause2 = factory.createClause() subject1 = factory.createNounPhrase('the', 'cat') clause2.setSubject(subject1)
class StringElementTest(unittest.TestCase): def setUp(self): self.lexicon = Lexicon.getDefaultLexicon() self.phraseFactory = NLGFactory(self.lexicon) self.realiser = Realiser(self.lexicon) # Test that string elements can be used as heads of NP def testStringElementAsHead(self): np = self.phraseFactory.createNounPhrase() np.setHead(self.phraseFactory.createStringElement("dogs and cats")) np.setSpecifier( self.phraseFactory.createWord("the", LexicalCategory.DETERMINER)) self.assertEqual("the dogs and cats", self.realiser.realise(np).getRealisation()) # Sentences whose VP is a canned string def testStringElementAsVP(self): s = self.phraseFactory.createClause() s.setVerbPhrase( self.phraseFactory.createStringElement("eats and drinks")) s.setSubject(self.phraseFactory.createStringElement("the big fat man")) self.assertEqual("the big fat man eats and drinks", self.realiser.realise(s).getRealisation()) # Test for when the SPhraseSpec has a NPSpec added directly after it: # "Mary loves NP[the cow]." def testTailNPStringElement(self): senSpec = self.phraseFactory.createClause() senSpec.addComplement( (self.phraseFactory.createStringElement("mary loves"))) np = self.phraseFactory.createNounPhrase() np.setHead("cow") np.setDeterminer("the") senSpec.addComplement(np) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("Mary loves the cow.", self.realiser.realise(completeSen).getRealisation()) # Test for a NP followed by a canned text: "NP[A cat] loves a dog". def testFrontNPStringElement(self): senSpec = self.phraseFactory.createClause() np = self.phraseFactory.createNounPhrase() np.setHead("cat") np.setDeterminer("the") senSpec.addComplement(np) senSpec.addComplement( self.phraseFactory.createStringElement("loves a dog")) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("The cat loves a dog.", \ self.realiser.realise(completeSen).getRealisation()) # Test for a StringElement followed by a NP followed by a StringElement # "The world loves NP[ABBA] but not a sore loser." def testMulitpleStringElements(self): senSpec = self.phraseFactory.createClause() senSpec.addComplement( self.phraseFactory.createStringElement("the world loves")) np = self.phraseFactory.createNounPhrase() np.setHead("ABBA") senSpec.addComplement(np) senSpec.addComplement( self.phraseFactory.createStringElement("but not a sore loser")) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("The world loves ABBA but not a sore loser.", \ self.realiser.realise(completeSen).getRealisation()) # Test for multiple NP phrases with a single StringElement phrase: # "NP[John is] a trier NP[for cheese]." def testMulitpleNPElements(self): senSpec = self.phraseFactory.createClause() frontNoun = self.phraseFactory.createNounPhrase() frontNoun.setHead("john") senSpec.addComplement(frontNoun) senSpec.addComplement( self.phraseFactory.createStringElement("is a trier")) backNoun = self.phraseFactory.createNounPhrase() backNoun.setDeterminer("for") backNoun.setNoun("cheese") senSpec.addComplement(backNoun) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("John is a trier for cheese.", \ self.realiser.realise(completeSen).getRealisation()) # White space check: Test to see how SNLG deals with additional whitespaces: # NP[The Nasdaq] rose steadily during NP[early trading], however it plummeted due to NP[a shock] after NP[IBM] announced poor # NP[first quarter results]. def testWhiteSpaceNP(self): senSpec = self.phraseFactory.createClause() firstNoun = self.phraseFactory.createNounPhrase() firstNoun.setDeterminer("the") firstNoun.setNoun("Nasdaq") senSpec.addComplement(firstNoun) senSpec.addComplement( self.phraseFactory.createStringElement(" rose steadily during ")) secondNoun = self.phraseFactory.createNounPhrase() secondNoun.setSpecifier("early") secondNoun.setNoun("trading") senSpec.addComplement(secondNoun) senSpec.addComplement( self.phraseFactory.createStringElement( " , however it plummeted due to")) thirdNoun = self.phraseFactory.createNounPhrase() thirdNoun.setSpecifier("a") thirdNoun.setNoun("shock") senSpec.addComplement(thirdNoun) senSpec.addComplement( self.phraseFactory.createStringElement(" after ")) fourthNoun = self.phraseFactory.createNounPhrase() fourthNoun.setNoun("IBM") senSpec.addComplement(fourthNoun) senSpec.addComplement( self.phraseFactory.createStringElement("announced poor ")) fifthNoun = self.phraseFactory.createNounPhrase() fifthNoun.setSpecifier("first quarter") fifthNoun.setNoun("results") fifthNoun.setPlural(True) senSpec.addComplement(fifthNoun) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) correct = "The Nasdaq rose steadily during early trading, however it plummeted " \ + "due to a shock after IBM announced poor first quarter results." self.assertEqual(correct, self.realiser.realise(completeSen).getRealisation()) # Point absorption test: Check to see if SNLG respects abbreviations at the end of a sentence. # "NP[Yahya] was sleeping his own and dreaming etc." def testPointAbsorption(self): senSpec = self.phraseFactory.createClause() firstNoun = self.phraseFactory.createNounPhrase() firstNoun.setNoun("yaha") senSpec.addComplement(firstNoun) senSpec.addComplement("was sleeping on his own and dreaming etc.") completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("Yaha was sleeping on his own and dreaming etc.", \ self.realiser.realise(completeSen).getRealisation()) # Point absorption test: As above, but with trailing white space. # "NP[Yaha] was sleeping his own and dreaming etc. " def testPointAbsorptionTrailingWhiteSpace(self): senSpec = self.phraseFactory.createClause() firstNoun = self.phraseFactory.createNounPhrase() firstNoun.setNoun("yaha") senSpec.addComplement(firstNoun) senSpec.addComplement( "was sleeping on his own and dreaming etc. ") completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("Yaha was sleeping on his own and dreaming etc.", \ self.realiser.realise(completeSen).getRealisation()) # Abbreviation test: Check to see how SNLG deals with abbreviations in the middle of a sentence. # "NP[Yahya] and friends etc. went to NP[the park] to play." def testMiddleAbbreviation(self): senSpec = self.phraseFactory.createClause() firstNoun = self.phraseFactory.createNounPhrase() firstNoun.setNoun("yahya") senSpec.addComplement(firstNoun) senSpec.addComplement( self.phraseFactory.createStringElement("and friends etc. went to")) secondNoun = self.phraseFactory.createNounPhrase() secondNoun.setDeterminer("the") secondNoun.setNoun("park") senSpec.addComplement(secondNoun) senSpec.addComplement("to play") completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("Yahya and friends etc. went to the park to play.", \ self.realiser.realise(completeSen).getRealisation()) # Indefinite Article Inflection: StringElement to test how SNLG handles a/an situations. # "I see an NP[elephant]" def testStringIndefiniteArticleInflectionVowel(self): senSpec = self.phraseFactory.createClause() senSpec.addComplement( self.phraseFactory.createStringElement("I see a")) firstNoun = self.phraseFactory.createNounPhrase("elephant") senSpec.addComplement(firstNoun) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("I see an elephant.", self.realiser.realise(completeSen).getRealisation()) # Indefinite Article Inflection: StringElement to test how SNLG handles a/an situations. # "I see NP[a elephant]" --> def testNPIndefiniteArticleInflectionVowel(self): senSpec = self.phraseFactory.createClause() senSpec.addComplement(self.phraseFactory.createStringElement("I see")) firstNoun = self.phraseFactory.createNounPhrase("elephant") firstNoun.setDeterminer("a") senSpec.addComplement(firstNoun) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) self.assertEqual("I see an elephant.", self.realiser.realise(completeSen).getRealisation()) ''' # Not useful in python. Java code returns "I see an cow." (ie.. it doesn't change the article) # assertNotSame simply verifies that two objects do not refer to the same object. # Indefinite Article Inflection: StringElement to test how SNLG handles a/an situations. # "I see an NP[cow]" def testStringIndefiniteArticleInflectionConsonant(self): senSpec = self.phraseFactory.createClause() senSpec.addComplement(self.phraseFactory.createStringElement("I see an")) firstNoun = self.phraseFactory.createNounPhrase("cow") senSpec.addComplement(firstNoun) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) # Do not attempt "an" -> "a" self.assertNotSame("I see an cow.", self.realiser.realise(completeSen).getRealisation()) ''' # Indefinite Article Inflection: StringElement to test how SNLG handles a/an situations. # "I see NP[an cow]" --> def testNPIndefiniteArticleInflectionConsonant(self): senSpec = self.phraseFactory.createClause() senSpec.addComplement(self.phraseFactory.createStringElement("I see")) firstNoun = self.phraseFactory.createNounPhrase("cow") firstNoun.setDeterminer("an") senSpec.addComplement(firstNoun) completeSen = self.phraseFactory.createSentence() completeSen.addComponent(senSpec) # Do not attempt "an" -> "a" self.assertEqual("I see an cow.", self.realiser.realise(completeSen).getRealisation()) # aggregationStringElementTest: Test to see if we can aggregate two StringElements # in a CoordinatedPhraseElement. def testAggregationStringElement(self): coordinate = self.phraseFactory.createCoordinatedPhrase( \ StringElement("John is going to Tesco"), StringElement("Mary is going to Sainsburys")) sentence = self.phraseFactory.createClause() sentence.addComplement(coordinate) self.assertEqual("John is going to Tesco and Mary is going to Sainsburys.", \ self.realiser.realiseSentence(sentence)) # Tests that no empty space is added when a StringElement is instantiated with an empty string # or None object. def testNullAndEmptyStringElement(self): NoneStringElement = self.phraseFactory.createStringElement(None) emptyStringElement = self.phraseFactory.createStringElement("") beautiful = self.phraseFactory.createStringElement("beautiful") horseLike = self.phraseFactory.createStringElement("horse-like") creature = self.phraseFactory.createStringElement("creature") # Test1: None or empty at beginning test1 = self.phraseFactory.createClause("a unicorn", "be", "regarded as a") test1.addPostModifier(emptyStringElement) test1.addPostModifier(beautiful) test1.addPostModifier(horseLike) test1.addPostModifier(creature) self.assertEqual("A unicorn is regarded as a beautiful horse-like creature.", \ self.realiser.realiseSentence(test1)) # Test2: empty or None at end test2 = self.phraseFactory.createClause("a unicorn", "be", "regarded as a") test2.addPostModifier(beautiful) test2.addPostModifier(horseLike) test2.addPostModifier(creature) test2.addPostModifier(NoneStringElement) self.assertEqual("A unicorn is regarded as a beautiful horse-like creature.", \ self.realiser.realiseSentence(test2)) # Test3: empty or None in the middle test3 = self.phraseFactory.createClause("a unicorn", "be", "regarded as a") test3.addPostModifier("beautiful") test3.addPostModifier("horse-like") test3.addPostModifier("") test3.addPostModifier("creature") self.assertEqual("A unicorn is regarded as a beautiful horse-like creature.", \ self.realiser.realiseSentence(test3)) # Test4: empty or None in the middle with empty or None at beginning test4 = self.phraseFactory.createClause("a unicorn", "be", "regarded as a") test4.addPostModifier("") test4.addPostModifier("beautiful") test4.addPostModifier("horse-like") test4.addPostModifier(NoneStringElement) test4.addPostModifier("creature") self.assertEqual("A unicorn is regarded as a beautiful horse-like creature.", \ self.realiser.realiseSentence(test4))