Skip to content

Commit 30e9e86

Browse files
committed
implement clause translation
1 parent 97c75c2 commit 30e9e86

3 files changed

Lines changed: 315 additions & 0 deletions

File tree

src/translator2/clause.ts

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
import { IterableResult } from "../compound.ts";
2+
import { nullableAsArray, throwError } from "../misc/misc.ts";
3+
import * as TokiPona from "../parser/ast.ts";
4+
import { nanpa } from "./nanpa.ts";
5+
import { preposition } from "./preposition.ts";
6+
import { fromSimpleDefinition } from "./word_unit.ts";
7+
import { predicate } from "./predicate.ts";
8+
import { addWay } from "./adjective.ts";
9+
import * as English from "./ast.ts";
10+
import { multiplePhrases } from "./phrase.ts";
11+
import { nounAsPreposition } from "./preposition.ts";
12+
import { FilteredError, UntranslatableError } from "./error.ts";
13+
import { addVerbBefore } from "./verb.ts";
14+
import { noEmphasis } from "./word.ts";
15+
16+
function phraseClause(phrases: TokiPona.MultiplePhrases) {
17+
return multiplePhrases(phrases)
18+
.map((phrase): English.Clause => {
19+
switch (phrase.type) {
20+
case "noun":
21+
return {
22+
type: "subject phrase",
23+
subject: phrase.noun,
24+
};
25+
case "adjective":
26+
return {
27+
type: "simple",
28+
subject: {
29+
type: "simple",
30+
determiners: [],
31+
adjectives: [],
32+
singular: { subject: "it", object: "it" },
33+
plural: null,
34+
reduplicationCount: 1,
35+
wordEmphasis: false,
36+
perspective: "third",
37+
adjectiveName: null,
38+
postCompound: null,
39+
prepositions: [],
40+
phraseEmphasis: false,
41+
gerund: false,
42+
},
43+
verb: {
44+
type: "simple",
45+
verb: [
46+
{
47+
verb: {
48+
type: "non-modal",
49+
presentPlural: "is",
50+
presentSingular: "are",
51+
past: "was",
52+
reduplicationCount: 1,
53+
emphasis: false,
54+
},
55+
preAdverbs: [],
56+
postAdverb: null,
57+
},
58+
],
59+
subjectComplement: {
60+
type: "adjective",
61+
adjective: phrase.adjective,
62+
},
63+
contentClause: null,
64+
object: null,
65+
objectComplement: null,
66+
prepositions: nullableAsArray(phrase.inWayPhrase)
67+
.map((object) =>
68+
nounAsPreposition({ ...addWay(object), type: "simple" }, "in")
69+
),
70+
hideVerb: true,
71+
forObject: false,
72+
predicateType: null,
73+
emphasis: false,
74+
},
75+
hideSubject: true,
76+
};
77+
case "verb":
78+
throw new FilteredError("verb as interjection");
79+
}
80+
});
81+
}
82+
export function subject(
83+
phrases: TokiPona.MultiplePhrases,
84+
): IterableResult<English.NounPhrase> {
85+
return multiplePhrases(phrases)
86+
.map((phrase) =>
87+
phrase.type === "noun"
88+
? phrase.noun
89+
: throwError(new FilteredError(`${phrase.type} as subject`))
90+
);
91+
}
92+
function liClause(clause: TokiPona.Clause & { type: "li clause" }) {
93+
return IterableResult.combine(
94+
subject(clause.subjects),
95+
predicate(clause.predicates, "li"),
96+
)
97+
.map(([subject, verb]): English.Clause => ({
98+
type: "simple",
99+
subject,
100+
verb,
101+
hideSubject: false,
102+
}));
103+
}
104+
function iWish(
105+
subject: English.NounPhrase,
106+
verb: English.VerbPhrase,
107+
): English.Clause {
108+
return {
109+
type: "simple",
110+
subject: {
111+
type: "simple",
112+
determiners: [],
113+
adjectives: [],
114+
singular: { subject: "I", object: "me" },
115+
plural: null,
116+
wordEmphasis: false,
117+
reduplicationCount: 1,
118+
perspective: "first",
119+
adjectiveName: null,
120+
postCompound: null,
121+
prepositions: [],
122+
phraseEmphasis: false,
123+
gerund: false,
124+
},
125+
verb: {
126+
type: "simple",
127+
verb: [
128+
{
129+
verb: {
130+
type: "non-modal",
131+
presentPlural: "wish",
132+
presentSingular: "wishes",
133+
past: "wished",
134+
reduplicationCount: 1,
135+
emphasis: false,
136+
},
137+
preAdverbs: [],
138+
postAdverb: null,
139+
},
140+
],
141+
subjectComplement: null,
142+
contentClause: {
143+
type: "simple",
144+
subject,
145+
verb,
146+
hideSubject: false,
147+
},
148+
object: null,
149+
objectComplement: null,
150+
prepositions: [],
151+
hideVerb: false,
152+
forObject: false,
153+
predicateType: null,
154+
emphasis: false,
155+
},
156+
hideSubject: false,
157+
};
158+
}
159+
160+
function oClause(clause: TokiPona.Clause & { type: "o clause" }) {
161+
const useSubject = clause.subjects != null
162+
? subject(clause.subjects)
163+
: IterableResult.single<English.NounPhrase>({
164+
type: "simple",
165+
determiners: [],
166+
adjectives: [],
167+
singular: { subject: "you", object: "you" },
168+
reduplicationCount: 1,
169+
wordEmphasis: false,
170+
plural: null,
171+
perspective: "second",
172+
adjectiveName: null,
173+
postCompound: null,
174+
prepositions: [],
175+
phraseEmphasis: false,
176+
gerund: false,
177+
});
178+
return IterableResult.combine(useSubject, predicate(clause.predicates, "o"))
179+
.flatMap(([subject, predicate]) => {
180+
return IterableResult.fromArray<English.Clause>([
181+
iWish(subject, predicate),
182+
{
183+
type: "simple",
184+
subject,
185+
verb: addVerbBefore(predicate, {
186+
verb: { type: "modal", word: "should", emphasis: false },
187+
preAdverbs: [],
188+
postAdverb: null,
189+
}),
190+
hideSubject: false,
191+
},
192+
]);
193+
});
194+
}
195+
export function clause(
196+
clause: TokiPona.Clause,
197+
): IterableResult<English.Clause> {
198+
switch (clause.type) {
199+
case "phrases":
200+
return phraseClause(clause.phrases);
201+
case "o vocative":
202+
return multiplePhrases(clause.phrases)
203+
.map((phrase) =>
204+
phrase.type === "noun"
205+
? { type: "vocative", call: "hey", addressee: phrase.noun }
206+
: throwError(
207+
new FilteredError(`${phrase.type} within o vocative`),
208+
)
209+
);
210+
case "li clause":
211+
return liClause(clause);
212+
case "o clause":
213+
return oClause(clause);
214+
}
215+
}
216+
export function contextClause(
217+
contextClause: TokiPona.ContextClause,
218+
): IterableResult<ReadonlyArray<English.Clause>> {
219+
switch (contextClause.type) {
220+
case "prepositions":
221+
return IterableResult.combine(
222+
...contextClause.prepositions.map(preposition),
223+
)
224+
.map((prepositions) =>
225+
prepositions.map((preposition): English.Clause => ({
226+
...preposition,
227+
type: "preposition",
228+
}))
229+
);
230+
case "nanpa":
231+
return nanpa(contextClause)
232+
.map((object): English.Clause => ({
233+
type: "preposition",
234+
adverbs: [],
235+
preposition: noEmphasis("at"),
236+
object: { ...object, type: "simple" },
237+
emphasis: false,
238+
}))
239+
.map((clause) => [clause]);
240+
case "anu":
241+
return IterableResult.errors([
242+
new UntranslatableError(`"anu la"`, "English clause"),
243+
]);
244+
default:
245+
return IterableResult.concat(
246+
IterableResult.fromNullable(unwrapSingleWord(contextClause))
247+
.flatMap((wordUnit) =>
248+
fromSimpleDefinition(
249+
wordUnit,
250+
(definition) =>
251+
definition.type === "adverb" ? definition.adverb : null,
252+
)
253+
)
254+
.map(
255+
(adverb): English.Clause => ({ type: "adverb", adverb }),
256+
),
257+
clause(contextClause).map((clause): English.Clause => ({
258+
type: "dependent",
259+
conjunction: noEmphasis("given"),
260+
clause,
261+
})),
262+
)
263+
.map((clause) => [clause]);
264+
}
265+
}
266+
export function unwrapSingleWord(
267+
clause: TokiPona.Clause,
268+
): null | TokiPona.WordUnit {
269+
if (clause.type === "phrases" && clause.phrases.type === "simple") {
270+
const { phrases: { phrase } } = clause;
271+
if (phrase.type === "simple" && phrase.modifiers.length === 0) {
272+
return phrase.headWord;
273+
}
274+
}
275+
return null;
276+
}

src/translator2/verb.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,17 @@ function flattenPartialVerb(
8484
return verb.verbs.flatMap(flattenPartialVerb);
8585
}
8686
}
87+
export function addVerbBefore(
88+
verb: English.VerbPhrase,
89+
verbToAdd: English.AdverbVerb,
90+
): English.VerbPhrase {
91+
switch (verb.type) {
92+
case "simple":
93+
return { ...verb, verb: [verbToAdd, ...verb.verb] };
94+
case "compound":
95+
return {
96+
...verb,
97+
verbs: verb.verbs.map((verb) => addVerbBefore(verb, verbToAdd)),
98+
};
99+
}
100+
}

src/translator2/word_unit.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IterableResult } from "../compound.ts";
22
import { dictionary } from "../dictionary/dictionary.ts";
3+
import { Definition } from "../dictionary/type.ts";
34
import * as TokiPona from "../parser/ast.ts";
45
import { adjective, compoundAdjective } from "./adjective.ts";
56
import * as English from "./ast.ts";
@@ -148,3 +149,27 @@ export function getReduplicationCount(wordUnit: TokiPona.WordUnit): number {
148149
return wordUnit.count;
149150
}
150151
}
152+
export function fromSimpleDefinition(
153+
wordUnit: TokiPona.WordUnit,
154+
mapper: (definition: Definition) => null | string,
155+
): IterableResult<English.Word> {
156+
switch (wordUnit.type) {
157+
case "simple":
158+
case "reduplication":
159+
return IterableResult.fromArray(
160+
dictionary.get(wordUnit.word)!.definitions,
161+
)
162+
.filterMap(mapper)
163+
.map((useWord) =>
164+
word({
165+
word: useWord,
166+
reduplicationCount: getReduplicationCount(wordUnit),
167+
emphasis: wordUnit.emphasis != null,
168+
})
169+
);
170+
case "number":
171+
return IterableResult.empty();
172+
case "x ala x":
173+
return IterableResult.errors([new TranslationTodoError("x ala x")]);
174+
}
175+
}

0 commit comments

Comments
 (0)