Read 's before a copula as possessive, not as a contraction

This commit is contained in:
dualfroz committed 2026-09-23 12:38:33 +02:00
1 parent 6fd03e1913
commit 1b935cb309
3 files changed
+18 -1

No files matched your search

@@ -13,6 +13,8 @@ const beforePossessive = {
}
const adjLike = new Set(['too', 'also', 'enough', 'about'])
const nounLike = new Set(['is', 'are', 'did', 'were', 'could', 'should', 'must', 'had', 'have'])
// "is was" or "has was" can't happen, so a copula means the 's is possessive
const copulas = new Set(['is', 'are', 'was', 'were', 'am'])
const isPossessive = (terms, i) => {
const term = terms[i]
@@ -68,6 +70,10 @@ const isPossessive = (terms, i) => {
}
//a gerund suggests 'is walking'
if (nextTerm.tags.has('Verb')) {
// 'leonard's was closed'
if (copulas.has(nextTerm.normal)) {
return true
}
//fix 'jamie's bite'
if (nextTerm.tags.has('Infinitive')) {
return true
@@ -58,7 +58,7 @@ export default [
// became involved
{ match: '(become|became|becoming|becomes) [#Verb]', group: 0, tag: 'Adjective', reason: 'become-verb' },
// their declared intentions
{ match: '#Possessive [#PastTense] #Noun', group: 0, tag: 'Adjective', reason: 'declared-intentions' },
{ match: '#Possessive [#PastTense] #Noun', group: 0, notIf: '#Copula', tag: 'Adjective', reason: 'declared-intentions' },
// is he cool
{ match: '#Copula #Pronoun [%Adj|Present%]', group: 0, tag: 'Adjective', reason: 'is-he-cool' },
// is crowded with
@@ -141,6 +141,9 @@ test('is-has', function (t) {
["The librarian's knowledge of books was vast", '#Possessive'],
["The manager's decision was unexpected", '#Possessive'],
["The meeting's been rescheduled", 'has'],
["Leonard's was Randall", '#Possessive'],
["Toronto's was Canada", '#Possessive'],
["Leonard's was closed on Monday", '#Possessive'],
["The meeting's scheduled for 3 PM", 'is'],
["The mountain's peak is covered in snow", '#Possessive'],
["The movie's already started", 'has'],
@@ -202,3 +205,11 @@ test('is-has', function (t) {
})
t.end()
})
test('possessive before a copula keeps its whitespace', function (t) {
const doc = nlp(`Leonard's was Randall`)
t.equal(doc.match('#Noun').text(), `Leonard's Randall`, here + 'noun match')
t.ok(doc.match('was').has('#Copula'), here + 'was stays a verb')
t.notOk(doc.match('was').has('#Adjective'), here + 'was is not an adjective')
t.end()
})