Skip to content

Commit 14e5505

Browse files
committed
partial implementation of verb negation
1 parent 2e5cf1f commit 14e5505

File tree

12 files changed

+257
-117
lines changed

12 files changed

+257
-117
lines changed

src/translator/adjective.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as Dictionary from "../../dictionary/type.ts";
2-
import { nullableAsArray } from "../../misc/misc.ts";
2+
import { mapNullable, nullableAsArray } from "../../misc/misc.ts";
33
import { IterableResult } from "../compound.ts";
44
import * as TokiPona from "../parser/ast.ts";
5+
import { extractNegativeFromAdverbs } from "./adverb.ts";
56
import * as English from "./ast.ts";
67
import { UntranslatableError } from "./error.ts";
78
import { noEmphasis, word } from "./word.ts";
@@ -110,3 +111,22 @@ export function fixAdjective(
110111
})
111112
.sort((a, b) => rankAdjective(a.kind) - rankAdjective(b.kind));
112113
}
114+
export function extractNegativeFromAdjective(
115+
adjective: English.AdjectivePhrase,
116+
): null | English.AdjectivePhrase {
117+
switch (adjective.type) {
118+
case "simple":
119+
return mapNullable(
120+
extractNegativeFromAdverbs(adjective.adverb),
121+
(adverb) => ({ ...adjective, adverb }),
122+
);
123+
case "compound": {
124+
const adjectives = adjective.adjective.map(extractNegativeFromAdjective);
125+
if (adjectives.every((adjective) => adjective != null)) {
126+
return { ...adjective, adjective: adjectives };
127+
} else {
128+
return null;
129+
}
130+
}
131+
}
132+
}

src/translator/adverb.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,13 @@ export function fixAdverb(
1010
return adverb;
1111
}
1212
}
13+
export function extractNegativeFromAdverbs(
14+
adverb: ReadonlyArray<English.Adverb>,
15+
): null | ReadonlyArray<English.Adverb> {
16+
const index = adverb.findIndex(({ negative }) => negative);
17+
if (index === -1) {
18+
return null;
19+
} else {
20+
return [...adverb].splice(index, 1);
21+
}
22+
}

src/translator/ast.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ export type Adverb = Readonly<{
5151
negative: boolean;
5252
}>;
5353
export type AdverbVerb = {
54-
adverb: ReadonlyArray<Adverb>;
54+
preAdverb: ReadonlyArray<Adverb>;
5555
verb: Word;
56+
postAdverb: ReadonlyArray<Adverb>;
5657
};
5758
export type Verb = Readonly<{
5859
modal: null | AdverbVerb;

src/translator/clause.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,14 @@ function oClause(clause: TokiPona.Clause & { type: "o clause" }) {
152152
return IterableResult.concat(
153153
verb(predicate, subjectPerspective, subject.quantity)
154154
.map((verb) => iWish(subject, verb)),
155-
IterableResult.from(() =>
156-
verb(
157-
addModalToAll(
158-
noAdverbs(noEmphasis("should")),
159-
predicate,
160-
),
155+
IterableResult.from(() => {
156+
const takeNegative = true;
157+
return verb(
158+
addModalToAll("should", predicate, takeNegative),
161159
subjectPerspective,
162160
subject.quantity,
163-
)
164-
)
161+
);
162+
})
165163
.map((verb) => ({
166164
type: "default",
167165
subject,

src/translator/composer.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,13 @@ function complement(complement: English.Complement) {
7272
}
7373
}
7474
export function adverbVerb(verbAdverb: English.AdverbVerb): string {
75-
const { adverb, verb } = verbAdverb;
76-
return [...adverb.map(({ adverb }) => adverb), verb].map(word).join(" ");
75+
const { preAdverb, verb, postAdverb } = verbAdverb;
76+
return [
77+
...preAdverb.map(({ adverb }) => adverb),
78+
verb,
79+
...postAdverb.map(({ adverb }) => adverb),
80+
]
81+
.map(word).join(" ");
7782
}
7883
export function verb(phrase: English.VerbPhrase, depth: number): string {
7984
let text: string;

src/translator/determiner.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ export function fixDeterminer(
133133
);
134134
}
135135
}
136+
export function extractNegativeFromDeterminers(
137+
determiner: ReadonlyArray<English.Determiner>,
138+
): null | ReadonlyArray<English.Determiner> {
139+
const index = determiner.findIndex(({ kind }) => kind === "negative");
140+
if (index === -1) {
141+
return null;
142+
} else {
143+
return [...determiner].splice(index, 1);
144+
}
145+
}
136146
function prettyPrintDeterminers(
137147
determiners: ReadonlyArray<English.Determiner>,
138148
) {

src/translator/noun.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import * as Dictionary from "../../dictionary/type.ts";
2-
import { nullableAsArray } from "../../misc/misc.ts";
2+
import { mapNullable, nullableAsArray } from "../../misc/misc.ts";
33
import { IterableResult } from "../compound.ts";
44
import { settings } from "../settings.ts";
55
import { adjective } from "./adjective.ts";
66
import * as English from "./ast.ts";
77
import * as EnglishComposer from "./composer.ts";
8-
import { determiner } from "./determiner.ts";
8+
import { determiner, extractNegativeFromDeterminers } from "./determiner.ts";
99
import { condense } from "./misc.ts";
1010
import { word } from "./word.ts";
1111

@@ -138,3 +138,22 @@ export function perspective(noun: English.NounPhrase): Dictionary.Perspective {
138138
return "third";
139139
}
140140
}
141+
export function extractNegativeFromNoun(
142+
noun: English.NounPhrase,
143+
): null | English.NounPhrase {
144+
switch (noun.type) {
145+
case "simple":
146+
return mapNullable(
147+
extractNegativeFromDeterminers(noun.determiner),
148+
(determiner) => ({ ...noun, determiner }),
149+
);
150+
case "compound": {
151+
const nouns = noun.nouns.map(extractNegativeFromNoun);
152+
if (nouns.every((noun) => noun != null)) {
153+
return { ...noun, nouns };
154+
} else {
155+
return null;
156+
}
157+
}
158+
}
159+
}

src/translator/phrase.ts

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { mapNullable, nullableAsArray } from "../../misc/misc.ts";
22
import { IterableResult } from "../compound.ts";
33
import * as TokiPona from "../parser/ast.ts";
44
import * as Composer from "../parser/composer.ts";
5-
import { AdjectiveWithInWay, fixAdjective } from "./adjective.ts";
5+
import {
6+
AdjectiveWithInWay,
7+
extractNegativeFromAdjective,
8+
fixAdjective,
9+
} from "./adjective.ts";
610
import { fixAdverb } from "./adverb.ts";
711
import * as English from "./ast.ts";
812
import { fixDeterminer, getNumber } from "./determiner.ts";
@@ -18,8 +22,12 @@ import {
1822
AdverbialModifier,
1923
multipleModifiers,
2024
} from "./modifier.ts";
21-
import { fromNounForms, PartialNoun } from "./noun.ts";
22-
import { nounAsPreposition, preposition } from "./preposition.ts";
25+
import { extractNegativeFromNoun, fromNounForms, PartialNoun } from "./noun.ts";
26+
import {
27+
extractNegativeFromPreposition,
28+
nounAsPreposition,
29+
preposition,
30+
} from "./preposition.ts";
2331
import { Place } from "./pronoun.ts";
2432
import { PartialCompoundVerb, PartialVerb } from "./verb.ts";
2533
import { word } from "./word.ts";
@@ -138,6 +146,7 @@ function adjectivePhrase(
138146
}
139147
}
140148
}
149+
// TODO: extract "not"
141150
function verbPhrase(
142151
options: Readonly<{
143152
emphasis: boolean;
@@ -165,11 +174,11 @@ function verbPhrase(
165174
return {
166175
...verb,
167176
modal: {
168-
adverb: fixAdverb([
177+
...verb.modal,
178+
preAdverb: fixAdverb([
169179
...[...modifier.adverb].reverse(),
170-
...verb.modal.adverb,
180+
...verb.modal.preAdverb,
171181
]),
172-
verb: verb.modal.verb,
173182
},
174183
phraseEmphasis: emphasis,
175184
preposition,
@@ -229,21 +238,23 @@ function defaultPhrase(
229238
.addErrorWhenNone(() => new ExhaustedError(Composer.phrase(phrase)));
230239
}
231240
function prepositionAsVerb(preposition: English.Preposition) {
241+
const extracted = extractNegativeFromPreposition(preposition);
232242
return {
233243
modal: null,
234244
adverb: [],
235245
first: {
236246
presentPlural: "are",
237247
presentSingular: "is",
238248
past: "were",
249+
negated: extracted != null,
239250
},
240251
reduplicationCount: 1,
241252
wordEmphasis: false,
242253
rest: [],
243254
subjectComplement: null,
244255
object: null,
245256
objectComplement: null,
246-
preposition: [preposition],
257+
preposition: [extracted ?? preposition],
247258
forObject: false,
248259
predicateType: null,
249260
phraseEmphasis: false,
@@ -336,20 +347,27 @@ export function phraseAsVerb(
336347
switch (phrase.type) {
337348
case "noun":
338349
case "adjective": {
350+
let negated: boolean;
339351
let subjectComplement: English.Complement;
340352
switch (phrase.type) {
341-
case "noun":
353+
case "noun": {
354+
const extract = extractNegativeFromNoun(phrase.noun);
355+
negated = extract != null;
342356
subjectComplement = {
343357
type: "noun",
344-
noun: phrase.noun,
358+
noun: extract ?? phrase.noun,
345359
};
346360
break;
347-
case "adjective":
361+
}
362+
case "adjective": {
363+
const extract = extractNegativeFromAdjective(phrase.adjective);
364+
negated = extract != null;
348365
subjectComplement = {
349366
type: "adjective",
350-
adjective: phrase.adjective,
367+
adjective: extract ?? phrase.adjective,
351368
};
352369
break;
370+
}
353371
}
354372
return {
355373
type: "simple",
@@ -359,6 +377,7 @@ export function phraseAsVerb(
359377
presentPlural: "are",
360378
presentSingular: "is",
361379
past: "were",
380+
negated,
362381
},
363382
wordEmphasis: false,
364383
reduplicationCount: 1,

0 commit comments

Comments
 (0)