slopless 0.2.23 → 0.2.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/rules/semantic-thinness/patterns/abstract-metaphor-claim.json +83 -1
- package/dist/rules/semantic-thinness/patterns/deictic-summary.json +31 -2
- package/dist/rules/semantic-thinness/patterns/empty-quantification.json +33 -0
- package/dist/rules/semantic-thinness/patterns/empty-scene-transition.json +2 -1
- package/dist/rules/semantic-thinness/private/concrete-guards.js +2 -0
- package/dist/rules/semantic-thinness/private/pattern-data-e.js +2 -0
- package/dist/rules/semantic-thinness/private/pattern-matcher.js +28 -7
- package/dist/rules/syntactic-patterns/closers/affirmation-closers.js +13 -3
- package/dist/rules/syntactic-patterns/contrast/contrastive-aphorism.js +2 -0
- package/dist/rules/syntactic-patterns/contrast/negation-reframe.js +1 -1
- package/dist/rules/syntactic-patterns/contrast/private/action-reframe-vocabulary.js +47 -0
- package/dist/rules/syntactic-patterns/contrast/private/audience-replacement.js +267 -0
- package/dist/rules/syntactic-patterns/contrast/private/copular-reframe.js +79 -0
- package/dist/rules/syntactic-patterns/contrast/private/evidence-limitation-pair.js +307 -0
- package/dist/rules/syntactic-patterns/contrast/private/inline-semicolon-reframe.js +50 -0
- package/dist/rules/syntactic-patterns/contrast/private/inline-short-negation.js +1 -0
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-matcher.js +78 -73
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-parts.js +99 -31
- package/dist/rules/syntactic-patterns/contrast/private/negation-vocabulary.js +27 -0
- package/dist/rules/syntactic-patterns/contrast/private/negative-consequence.js +301 -0
- package/dist/rules/syntactic-patterns/contrast/private/negative-slop-frames.js +155 -39
- package/dist/rules/syntactic-patterns/contrast/private/policy-object.js +55 -0
- package/dist/rules/syntactic-patterns/contrast/private/reframe-classification.js +214 -0
- package/dist/rules/syntactic-patterns/contrast/private/sequence-reframes.js +9 -0
- package/dist/rules/syntactic-patterns/contrast/private/temporal-reframe.js +318 -0
- package/dist/rules/syntactic-patterns/lead-ins/generic-signposting.js +96 -102
- package/dist/rules/syntactic-patterns/lead-ins/private/component-assignment-frame.js +239 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/discourse-evaluation.js +150 -4
- package/dist/rules/syntactic-patterns/lead-ins/private/evaluative-colon-frame.js +166 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/reaction-frame.js +29 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/relative-discourse-frame.js +119 -0
- package/package.json +1 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { wordTokens } from "../../../../shared/text/tokens.js";
|
|
2
|
+
const OMISSION_VERBS = new Set(["drop", "leave", "omit", "remove", "skip"]);
|
|
3
|
+
const INFORMATION_ARTIFACTS = new Set([
|
|
4
|
+
"attribute",
|
|
5
|
+
"catalog",
|
|
6
|
+
"content",
|
|
7
|
+
"description",
|
|
8
|
+
"document",
|
|
9
|
+
"evidence",
|
|
10
|
+
"feed",
|
|
11
|
+
"field",
|
|
12
|
+
"listing",
|
|
13
|
+
"metadata",
|
|
14
|
+
"page",
|
|
15
|
+
"profile",
|
|
16
|
+
"record",
|
|
17
|
+
"report"
|
|
18
|
+
]);
|
|
19
|
+
const CONSEQUENCE_VERBS = new Set([
|
|
20
|
+
"fail",
|
|
21
|
+
"fails",
|
|
22
|
+
"failed",
|
|
23
|
+
"lose",
|
|
24
|
+
"loses",
|
|
25
|
+
"lost",
|
|
26
|
+
"miss",
|
|
27
|
+
"misses",
|
|
28
|
+
"missed"
|
|
29
|
+
]);
|
|
30
|
+
const NEGATIVE_AUXILIARIES = new Set([
|
|
31
|
+
"aren't",
|
|
32
|
+
"cannot",
|
|
33
|
+
"can't",
|
|
34
|
+
"didn't",
|
|
35
|
+
"doesn't",
|
|
36
|
+
"don't",
|
|
37
|
+
"hadn't",
|
|
38
|
+
"hasn't",
|
|
39
|
+
"haven't",
|
|
40
|
+
"isn't",
|
|
41
|
+
"not",
|
|
42
|
+
"wasn't",
|
|
43
|
+
"weren't",
|
|
44
|
+
"won't",
|
|
45
|
+
"wouldn't"
|
|
46
|
+
]);
|
|
47
|
+
const ABSTRACT_OUTCOMES = new Set([
|
|
48
|
+
"comparison",
|
|
49
|
+
"consideration",
|
|
50
|
+
"decision",
|
|
51
|
+
"discoverability",
|
|
52
|
+
"distribution",
|
|
53
|
+
"market",
|
|
54
|
+
"ranking",
|
|
55
|
+
"recommendation",
|
|
56
|
+
"results",
|
|
57
|
+
"selection",
|
|
58
|
+
"visibility"
|
|
59
|
+
]);
|
|
60
|
+
const ENTRY_VERBS = new Set([
|
|
61
|
+
"appear",
|
|
62
|
+
"appears",
|
|
63
|
+
"compare",
|
|
64
|
+
"compares",
|
|
65
|
+
"enter",
|
|
66
|
+
"enters",
|
|
67
|
+
"include",
|
|
68
|
+
"includes",
|
|
69
|
+
"qualify",
|
|
70
|
+
"qualifies",
|
|
71
|
+
"rank",
|
|
72
|
+
"ranks",
|
|
73
|
+
"reach",
|
|
74
|
+
"reaches",
|
|
75
|
+
"recommend",
|
|
76
|
+
"recommends",
|
|
77
|
+
"select",
|
|
78
|
+
"selects"
|
|
79
|
+
]);
|
|
80
|
+
const INFORMATION_VERBS = new Set([
|
|
81
|
+
"describe",
|
|
82
|
+
"described",
|
|
83
|
+
"describes",
|
|
84
|
+
"explain",
|
|
85
|
+
"explained",
|
|
86
|
+
"explains",
|
|
87
|
+
"include",
|
|
88
|
+
"included",
|
|
89
|
+
"includes",
|
|
90
|
+
"list",
|
|
91
|
+
"listed",
|
|
92
|
+
"lists",
|
|
93
|
+
"mention",
|
|
94
|
+
"mentioned",
|
|
95
|
+
"mentions",
|
|
96
|
+
"say",
|
|
97
|
+
"said",
|
|
98
|
+
"says",
|
|
99
|
+
"show",
|
|
100
|
+
"showed",
|
|
101
|
+
"shown",
|
|
102
|
+
"shows",
|
|
103
|
+
"state",
|
|
104
|
+
"stated",
|
|
105
|
+
"states"
|
|
106
|
+
]);
|
|
107
|
+
const SELECTION_PREDICATES = new Map([
|
|
108
|
+
["appeared", "appear"],
|
|
109
|
+
["compared", "compare"],
|
|
110
|
+
["considered", "consider"],
|
|
111
|
+
["included", "include"],
|
|
112
|
+
["qualified", "qualify"],
|
|
113
|
+
["ranked", "rank"],
|
|
114
|
+
["reached", "reach"],
|
|
115
|
+
["recommended", "recommend"],
|
|
116
|
+
["rejected", "reject"],
|
|
117
|
+
["selected", "select"],
|
|
118
|
+
["shown", "show"]
|
|
119
|
+
]);
|
|
120
|
+
const CAUSAL_CONNECTORS = new Set([
|
|
121
|
+
"after",
|
|
122
|
+
"because",
|
|
123
|
+
"if",
|
|
124
|
+
"since",
|
|
125
|
+
"therefore",
|
|
126
|
+
"until",
|
|
127
|
+
"when",
|
|
128
|
+
"while"
|
|
129
|
+
]);
|
|
130
|
+
const TECHNICAL_OR_SAFETY_WORDS = new Set([
|
|
131
|
+
"backup",
|
|
132
|
+
"bytes",
|
|
133
|
+
"checksum",
|
|
134
|
+
"citation",
|
|
135
|
+
"citations",
|
|
136
|
+
"code",
|
|
137
|
+
"database",
|
|
138
|
+
"debug",
|
|
139
|
+
"debugging",
|
|
140
|
+
"disk",
|
|
141
|
+
"error",
|
|
142
|
+
"measurement",
|
|
143
|
+
"measurements",
|
|
144
|
+
"parser",
|
|
145
|
+
"pressure",
|
|
146
|
+
"psi",
|
|
147
|
+
"records",
|
|
148
|
+
"schema",
|
|
149
|
+
"semicolon",
|
|
150
|
+
"stack",
|
|
151
|
+
"tank",
|
|
152
|
+
"trace",
|
|
153
|
+
"valve",
|
|
154
|
+
"voltage"
|
|
155
|
+
]);
|
|
156
|
+
function words(text) {
|
|
157
|
+
return wordTokens(text).map((token) => token.normalized);
|
|
158
|
+
}
|
|
159
|
+
function hasQuotedText(text) {
|
|
160
|
+
return [...text].some((character) => character === '"' ||
|
|
161
|
+
character === "\u201c" ||
|
|
162
|
+
character === "\u201d" ||
|
|
163
|
+
character === "`");
|
|
164
|
+
}
|
|
165
|
+
function hasDigit(word) {
|
|
166
|
+
return [...word].some((character) => character >= "0" && character <= "9");
|
|
167
|
+
}
|
|
168
|
+
function hasDash(text) {
|
|
169
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
170
|
+
const character = text[index];
|
|
171
|
+
if (character === "\u2013" || character === "\u2014") {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
if (character === "-" &&
|
|
175
|
+
(text[index - 1]?.trim() === "" || text[index + 1]?.trim() === "")) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
function hasRejectedContext(text, sentenceWords) {
|
|
182
|
+
return (hasQuotedText(text) ||
|
|
183
|
+
sentenceWords.some((word) => CAUSAL_CONNECTORS.has(word) ||
|
|
184
|
+
TECHNICAL_OR_SAFETY_WORDS.has(word) ||
|
|
185
|
+
hasDigit(word)));
|
|
186
|
+
}
|
|
187
|
+
function containsAny(sentenceWords, candidates) {
|
|
188
|
+
return sentenceWords.some((word) => candidates.has(word));
|
|
189
|
+
}
|
|
190
|
+
function omissionConsequence(first, second) {
|
|
191
|
+
const firstWords = words(first);
|
|
192
|
+
const secondWords = words(second);
|
|
193
|
+
const comma = first.indexOf(",");
|
|
194
|
+
const startsWithOmission = OMISSION_VERBS.has(firstWords[0] ?? "") &&
|
|
195
|
+
containsAny(words(first.slice(0, comma < 0 ? first.length : comma)), INFORMATION_ARTIFACTS);
|
|
196
|
+
const namesMissingInformation = firstWords.some((word, index) => word === "no" &&
|
|
197
|
+
firstWords
|
|
198
|
+
.slice(index + 1, index + 4)
|
|
199
|
+
.some((candidate) => INFORMATION_ARTIFACTS.has(candidate)));
|
|
200
|
+
if (firstWords.length > 32 ||
|
|
201
|
+
secondWords.length > 16 ||
|
|
202
|
+
(!startsWithOmission && !namesMissingInformation) ||
|
|
203
|
+
hasRejectedContext(first, firstWords) ||
|
|
204
|
+
hasRejectedContext(second, secondWords)) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
const consequenceStart = firstWords.findIndex((word, index) => index > 0 && CONSEQUENCE_VERBS.has(word));
|
|
208
|
+
const hasNegativeConsequence = consequenceStart > 0 &&
|
|
209
|
+
firstWords
|
|
210
|
+
.slice(Math.max(0, consequenceStart - 3), consequenceStart)
|
|
211
|
+
.some((word) => NEGATIVE_AUXILIARIES.has(word));
|
|
212
|
+
const neverIndex = secondWords.indexOf("never");
|
|
213
|
+
const entryVerb = neverIndex < 0
|
|
214
|
+
? undefined
|
|
215
|
+
: secondWords.slice(neverIndex + 1).find((word) => ENTRY_VERBS.has(word));
|
|
216
|
+
const combined = [...firstWords, ...secondWords];
|
|
217
|
+
return (hasNegativeConsequence &&
|
|
218
|
+
neverIndex > 0 &&
|
|
219
|
+
entryVerb !== undefined &&
|
|
220
|
+
containsAny(combined, ABSTRACT_OUTCOMES));
|
|
221
|
+
}
|
|
222
|
+
function selectionOccurrences(sentenceWords) {
|
|
223
|
+
const occurrences = [];
|
|
224
|
+
sentenceWords.forEach((word, index) => {
|
|
225
|
+
const canonical = SELECTION_PREDICATES.get(word);
|
|
226
|
+
if (canonical !== undefined) {
|
|
227
|
+
occurrences.push({ canonical, index });
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
return occurrences;
|
|
231
|
+
}
|
|
232
|
+
function hasNegativeMarkerBefore(sentenceWords, index, marker) {
|
|
233
|
+
const previous = sentenceWords[index - 1];
|
|
234
|
+
if (previous === marker) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
const clauseStart = sentenceWords.lastIndexOf(marker, index - 1);
|
|
238
|
+
return clauseStart >= 0 && index - clauseStart <= 3;
|
|
239
|
+
}
|
|
240
|
+
function inlineSelectionClaim(text, allowStackedNever) {
|
|
241
|
+
const sentenceWords = words(text);
|
|
242
|
+
if (sentenceWords.length > 14 || hasRejectedContext(text, sentenceWords)) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
const occurrences = selectionOccurrences(sentenceWords);
|
|
246
|
+
if (occurrences.length < 2) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
const repeatedAcrossNegation = occurrences.some((firstOccurrence, index) => occurrences
|
|
250
|
+
.slice(index + 1)
|
|
251
|
+
.some((secondOccurrence) => firstOccurrence.canonical === secondOccurrence.canonical &&
|
|
252
|
+
hasNegativeMarkerBefore(sentenceWords, firstOccurrence.index, "not") &&
|
|
253
|
+
hasNegativeMarkerBefore(sentenceWords, secondOccurrence.index, "never")));
|
|
254
|
+
const stackedNeverPredicates = occurrences.filter((occurrence) => hasNegativeMarkerBefore(sentenceWords, occurrence.index, "never")).length >= 2;
|
|
255
|
+
return ((hasDash(text) && repeatedAcrossNegation) ||
|
|
256
|
+
(allowStackedNever && stackedNeverPredicates));
|
|
257
|
+
}
|
|
258
|
+
function artifactInformationClaim(text) {
|
|
259
|
+
const sentenceWords = words(text);
|
|
260
|
+
if (sentenceWords.length > 18 || hasRejectedContext(text, sentenceWords)) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
const neverIndex = sentenceWords.indexOf("never");
|
|
264
|
+
if (neverIndex < 1 || neverIndex > 5) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
const subject = sentenceWords.slice(0, neverIndex);
|
|
268
|
+
return (containsAny(subject, INFORMATION_ARTIFACTS) &&
|
|
269
|
+
INFORMATION_VERBS.has(sentenceWords[neverIndex + 1] ?? "") &&
|
|
270
|
+
sentenceWords.length > neverIndex + 2);
|
|
271
|
+
}
|
|
272
|
+
function shortOutcomeFragment(text) {
|
|
273
|
+
const sentenceWords = words(text);
|
|
274
|
+
return (sentenceWords.length > 0 &&
|
|
275
|
+
sentenceWords.length <= 3 &&
|
|
276
|
+
!hasRejectedContext(text, sentenceWords) &&
|
|
277
|
+
!sentenceWords.includes("never"));
|
|
278
|
+
}
|
|
279
|
+
function artifactSelectionSequence(first, second, third) {
|
|
280
|
+
if (!artifactInformationClaim(first)) {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
if (inlineSelectionClaim(second, true)) {
|
|
284
|
+
return `${first} ${second}`;
|
|
285
|
+
}
|
|
286
|
+
return third !== undefined &&
|
|
287
|
+
shortOutcomeFragment(second) &&
|
|
288
|
+
inlineSelectionClaim(third, true)
|
|
289
|
+
? `${first} ${second} ${third}`
|
|
290
|
+
: undefined;
|
|
291
|
+
}
|
|
292
|
+
export function matchNegativeConsequence(first, second, third) {
|
|
293
|
+
if (second.length === 0) {
|
|
294
|
+
return inlineSelectionClaim(first, false) ? first : undefined;
|
|
295
|
+
}
|
|
296
|
+
if (omissionConsequence(first, second)) {
|
|
297
|
+
return `${first} ${second}`;
|
|
298
|
+
}
|
|
299
|
+
return artifactSelectionSequence(first, second, third);
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=negative-consequence.js.map
|
|
@@ -1,31 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
1
|
+
import { hasFactualConnectorAfterNegation } from "./negation-context-gates.js";
|
|
2
|
+
import { hasAbstractPolicyDirectObject } from "./policy-object.js";
|
|
3
|
+
import { negatedProgressiveNeverPayoff } from "./copular-reframe.js";
|
|
4
|
+
import { GENERIC_ACTION_VERBS } from "./action-reframe-vocabulary.js";
|
|
5
|
+
export { shouldReportCopularReframe } from "./reframe-classification.js";
|
|
6
|
+
export { progressiveVerbMirror, pronounCopularReframe, sameSubjectCopularReframe, startsWithNegatedPronounCopula } from "./copular-reframe.js";
|
|
7
|
+
export { matchSequenceReframe } from "./sequence-reframes.js";
|
|
8
|
+
import { ACTION_NEGATIONS, EXPLICIT_DO_AUXILIARIES, FACTUAL_NEGATION_CONNECTORS, PRONOUN_REFRAME_STARTS, findCopularNegation, pronounCopulaStart, skipOptionalAdverbs, startsWithAny, startsWithSubjectOrPronoun, startsWithWords, stripLeadingPairPivot, validSubject, words } from "./negation-reframe-parts.js";
|
|
9
|
+
const NEGATED_ACTION_REFRAME_VERBS = new Set([
|
|
10
|
+
"avoid",
|
|
11
|
+
"change",
|
|
12
|
+
"create",
|
|
13
|
+
"end",
|
|
14
|
+
"erase",
|
|
15
|
+
"fix",
|
|
16
|
+
"guarantee",
|
|
17
|
+
"make",
|
|
18
|
+
"mean",
|
|
19
|
+
"remove",
|
|
20
|
+
"replace",
|
|
21
|
+
"require",
|
|
22
|
+
"skip",
|
|
23
|
+
"solve"
|
|
24
|
+
]);
|
|
25
|
+
const REPLACEMENT_SUBJECT_PRONOUNS = new Set(["he", "she"]);
|
|
26
|
+
const EMBEDDED_CLAUSE_VERBS = new Set([
|
|
27
|
+
"believed",
|
|
28
|
+
"explained",
|
|
29
|
+
"reckoned",
|
|
30
|
+
"reported",
|
|
19
31
|
"said",
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
32
|
+
"thought"
|
|
33
|
+
]);
|
|
34
|
+
const PRONOUN_PAYOFF_VERBS = new Set([
|
|
35
|
+
"becomes",
|
|
36
|
+
"creates",
|
|
37
|
+
"depends",
|
|
38
|
+
"exposes",
|
|
39
|
+
"lands",
|
|
40
|
+
"means",
|
|
41
|
+
"moves",
|
|
42
|
+
"needs",
|
|
43
|
+
"points",
|
|
44
|
+
"requires",
|
|
45
|
+
"reveals",
|
|
46
|
+
"shifts",
|
|
47
|
+
"shows",
|
|
48
|
+
"turns"
|
|
49
|
+
]);
|
|
50
|
+
const PRONOUN_SUBJECTS = new Set(["it", "this", "that", "they", "we", "you"]);
|
|
51
|
+
const ACTION_REPLACEMENT_CONNECTORS = new Set([
|
|
52
|
+
...FACTUAL_NEGATION_CONNECTORS,
|
|
53
|
+
"after"
|
|
29
54
|
]);
|
|
30
55
|
function startsWithPassiveCopula(tokens) {
|
|
31
56
|
const tokenWords = words(tokens);
|
|
@@ -36,6 +61,13 @@ function startsWithPassiveCopula(tokens) {
|
|
|
36
61
|
}
|
|
37
62
|
function noLongerCopularReframe(aTokens, bTokens) {
|
|
38
63
|
const tokenWords = words(aTokens);
|
|
64
|
+
const contractedStart = pronounCopulaStart(aTokens);
|
|
65
|
+
if (contractedStart !== undefined &&
|
|
66
|
+
tokenWords[contractedStart.predicateStart] === "no" &&
|
|
67
|
+
tokenWords[contractedStart.predicateStart + 1] === "longer") {
|
|
68
|
+
return (startsWithSubjectOrPronoun(bTokens, contractedStart.subject) &&
|
|
69
|
+
!startsWithPassiveCopula(bTokens));
|
|
70
|
+
}
|
|
39
71
|
for (let index = 0; index < tokenWords.length - 2; index += 1) {
|
|
40
72
|
const current = tokenWords[index];
|
|
41
73
|
const subject = tokenWords.slice(0, index);
|
|
@@ -65,23 +97,48 @@ function fragmentDefinitionReframe(aTokens, bTokens) {
|
|
|
65
97
|
}
|
|
66
98
|
function negatedActionSubject(tokens) {
|
|
67
99
|
const tokenWords = words(tokens);
|
|
100
|
+
const copularNegation = findCopularNegation(tokens);
|
|
101
|
+
if (copularNegation !== undefined &&
|
|
102
|
+
validSubject(copularNegation.subject) &&
|
|
103
|
+
tokenWords[copularNegation.negatedPredicateStart]?.endsWith("ing") === true) {
|
|
104
|
+
return copularNegation.subject;
|
|
105
|
+
}
|
|
68
106
|
for (let index = 0; index < tokenWords.length; index += 1) {
|
|
69
107
|
const current = tokenWords[index];
|
|
70
108
|
const next = tokenWords[index + 1];
|
|
71
109
|
const subject = tokenWords.slice(0, index);
|
|
72
|
-
if (!validSubject(subject)
|
|
110
|
+
if (!validSubject(subject) ||
|
|
111
|
+
subject.some((word) => EMBEDDED_CLAUSE_VERBS.has(word))) {
|
|
73
112
|
continue;
|
|
74
113
|
}
|
|
75
|
-
if (
|
|
76
|
-
return
|
|
114
|
+
if (ACTION_NEGATIONS.has(current ?? "")) {
|
|
115
|
+
return tokenWords[index + 1] !== undefined &&
|
|
116
|
+
!tokenWords.slice(index + 1).includes("and")
|
|
117
|
+
? subject
|
|
118
|
+
: undefined;
|
|
77
119
|
}
|
|
78
120
|
if (EXPLICIT_DO_AUXILIARIES.has(current ?? "") && next === "not") {
|
|
79
|
-
return
|
|
121
|
+
return tokenWords[index + 2] !== undefined &&
|
|
122
|
+
!tokenWords.slice(index + 2).includes("and")
|
|
123
|
+
? subject
|
|
124
|
+
: undefined;
|
|
80
125
|
}
|
|
81
126
|
}
|
|
82
127
|
return undefined;
|
|
83
128
|
}
|
|
84
|
-
function
|
|
129
|
+
function constrainedSetSubjectLength(tokens, subject) {
|
|
130
|
+
if (startsWithWords(tokens, subject)) {
|
|
131
|
+
return subject.length;
|
|
132
|
+
}
|
|
133
|
+
if (startsWithSubjectOrPronoun(tokens, subject)) {
|
|
134
|
+
return 1;
|
|
135
|
+
}
|
|
136
|
+
return subject.length > 1 &&
|
|
137
|
+
REPLACEMENT_SUBJECT_PRONOUNS.has(tokens[0]?.normalized ?? "")
|
|
138
|
+
? 1
|
|
139
|
+
: undefined;
|
|
140
|
+
}
|
|
141
|
+
export function negatedActionReplacement(aTokens, bTokens) {
|
|
85
142
|
const tokenWords = words(aTokens);
|
|
86
143
|
const subject = negatedActionSubject(aTokens);
|
|
87
144
|
if (subject === undefined) {
|
|
@@ -89,13 +146,34 @@ function negativeActionReplacement(aTokens, bTokens) {
|
|
|
89
146
|
}
|
|
90
147
|
const bContentTokens = stripLeadingPairPivot(bTokens);
|
|
91
148
|
const bWords = words(bContentTokens);
|
|
92
|
-
const
|
|
93
|
-
const
|
|
149
|
+
const subjectLength = constrainedSetSubjectLength(bContentTokens, subject);
|
|
150
|
+
const genericVerbIndex = subjectLength === undefined
|
|
151
|
+
? undefined
|
|
152
|
+
: skipOptionalAdverbs(bWords, subjectLength);
|
|
94
153
|
return (tokenWords.length <= 14 &&
|
|
95
|
-
!
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
154
|
+
!tokenWords.some((word) => FACTUAL_NEGATION_CONNECTORS.has(word)) &&
|
|
155
|
+
!bWords.some((word) => ACTION_REPLACEMENT_CONNECTORS.has(word)) &&
|
|
156
|
+
((genericVerbIndex !== undefined &&
|
|
157
|
+
GENERIC_ACTION_VERBS.has(bWords[genericVerbIndex] ?? "")) ||
|
|
158
|
+
negatedActionSetReplacement(aTokens, bTokens)));
|
|
159
|
+
}
|
|
160
|
+
export function negatedActionSetReplacement(aTokens, bTokens) {
|
|
161
|
+
const tokenWords = words(aTokens);
|
|
162
|
+
const subject = negatedActionSubject(aTokens);
|
|
163
|
+
if (subject === undefined) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
const bContentTokens = stripLeadingPairPivot(bTokens);
|
|
167
|
+
const bWords = words(bContentTokens);
|
|
168
|
+
const subjectLength = constrainedSetSubjectLength(bContentTokens, subject);
|
|
169
|
+
const verbIndex = subjectLength === undefined
|
|
170
|
+
? undefined
|
|
171
|
+
: skipOptionalAdverbs(bWords, subjectLength);
|
|
172
|
+
return (tokenWords.length <= 14 &&
|
|
173
|
+
!tokenWords.some((word) => FACTUAL_NEGATION_CONNECTORS.has(word)) &&
|
|
174
|
+
!bWords.some((word) => ACTION_REPLACEMENT_CONNECTORS.has(word)) &&
|
|
175
|
+
verbIndex !== undefined &&
|
|
176
|
+
hasAbstractPolicyDirectObject(bWords, verbIndex));
|
|
99
177
|
}
|
|
100
178
|
function notBecauseReframe(aTokens, bTokens) {
|
|
101
179
|
return (startsWithWords(aTokens, ["not", "because"]) &&
|
|
@@ -130,10 +208,48 @@ export function hasNegativeSlopPairSignal(tokens) {
|
|
|
130
208
|
hasTrailingProblemFrame(tokenWords) ||
|
|
131
209
|
hasLeadingProblemFrame(tokenWords));
|
|
132
210
|
}
|
|
211
|
+
export function negatedActionPronounPayoff(aTokens, bTokens) {
|
|
212
|
+
const aWords = words(aTokens);
|
|
213
|
+
const bWords = words(stripLeadingPairPivot(bTokens));
|
|
214
|
+
const pronounStart = PRONOUN_SUBJECTS.has(bWords[0] ?? "") ? 1 : undefined;
|
|
215
|
+
if (pronounStart === undefined) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
const payoffVerbIndex = skipOptionalAdverbs(bWords, pronounStart);
|
|
219
|
+
if (!PRONOUN_PAYOFF_VERBS.has(bWords[payoffVerbIndex] ?? "")) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
for (let index = 0; index < aWords.length; index += 1) {
|
|
223
|
+
if (hasNegatedReframeVerb(aTokens, aWords, index)) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
function hasNegatedReframeVerb(tokens, tokenWords, index) {
|
|
230
|
+
const current = tokenWords[index];
|
|
231
|
+
const next = tokenWords[index + 1];
|
|
232
|
+
const subject = tokenWords.slice(0, index);
|
|
233
|
+
if (!validSubject(subject)) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
const negationIndex = ACTION_NEGATIONS.has(current ?? "")
|
|
237
|
+
? index
|
|
238
|
+
: EXPLICIT_DO_AUXILIARIES.has(current ?? "") && next === "not"
|
|
239
|
+
? index + 1
|
|
240
|
+
: undefined;
|
|
241
|
+
if (negationIndex === undefined ||
|
|
242
|
+
hasFactualConnectorAfterNegation(tokens, negationIndex)) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
const verbIndex = skipOptionalAdverbs(tokenWords, negationIndex + 1);
|
|
246
|
+
return NEGATED_ACTION_REFRAME_VERBS.has(tokenWords[verbIndex] ?? "");
|
|
247
|
+
}
|
|
133
248
|
export function negativeSlopReframe(aTokens, bTokens) {
|
|
134
249
|
return (noLongerCopularReframe(aTokens, bTokens) ||
|
|
250
|
+
negatedProgressiveNeverPayoff(aTokens, bTokens) ||
|
|
135
251
|
fragmentDefinitionReframe(aTokens, bTokens) ||
|
|
136
|
-
|
|
252
|
+
negatedActionReplacement(aTokens, bTokens) ||
|
|
137
253
|
notBecauseReframe(aTokens, bTokens) ||
|
|
138
254
|
notProblemReframe(aTokens, bTokens));
|
|
139
255
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const ABSTRACT_POLICY_OBJECTS = new Set([
|
|
2
|
+
"condition",
|
|
3
|
+
"criterion",
|
|
4
|
+
"policy",
|
|
5
|
+
"principle",
|
|
6
|
+
"requirement",
|
|
7
|
+
"rule",
|
|
8
|
+
"standard",
|
|
9
|
+
"threshold"
|
|
10
|
+
]);
|
|
11
|
+
const DIRECT_OBJECT_DETERMINERS = new Set([
|
|
12
|
+
"a",
|
|
13
|
+
"an",
|
|
14
|
+
"one",
|
|
15
|
+
"that",
|
|
16
|
+
"the",
|
|
17
|
+
"this"
|
|
18
|
+
]);
|
|
19
|
+
const POLICY_OBJECT_MODIFIERS = new Set([
|
|
20
|
+
"access",
|
|
21
|
+
"approval",
|
|
22
|
+
"business",
|
|
23
|
+
"content",
|
|
24
|
+
"deployment",
|
|
25
|
+
"editorial",
|
|
26
|
+
"governance",
|
|
27
|
+
"launch",
|
|
28
|
+
"operating",
|
|
29
|
+
"pricing",
|
|
30
|
+
"quality",
|
|
31
|
+
"release",
|
|
32
|
+
"review",
|
|
33
|
+
"safety",
|
|
34
|
+
"security",
|
|
35
|
+
"service",
|
|
36
|
+
"spending",
|
|
37
|
+
"technical",
|
|
38
|
+
"testing",
|
|
39
|
+
"usage"
|
|
40
|
+
]);
|
|
41
|
+
export function hasAbstractPolicyDirectObject(tokenWords, verbIndex) {
|
|
42
|
+
if (!["set", "sets"].includes(tokenWords[verbIndex] ?? "")) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const objectTokens = tokenWords.slice(verbIndex + 1);
|
|
46
|
+
const directObject = DIRECT_OBJECT_DETERMINERS.has(objectTokens[0] ?? "")
|
|
47
|
+
? objectTokens.slice(1)
|
|
48
|
+
: objectTokens;
|
|
49
|
+
const [first, second] = directObject;
|
|
50
|
+
return ((directObject.length === 1 && ABSTRACT_POLICY_OBJECTS.has(first ?? "")) ||
|
|
51
|
+
(directObject.length === 2 &&
|
|
52
|
+
POLICY_OBJECT_MODIFIERS.has(first ?? "") &&
|
|
53
|
+
ABSTRACT_POLICY_OBJECTS.has(second ?? "")));
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=policy-object.js.map
|