Skip to content

Commit 91c586c

Browse files
committed
refactor
1 parent 302027e commit 91c586c

File tree

11 files changed

+215
-229
lines changed

11 files changed

+215
-229
lines changed

dictionary/parser.ts

Lines changed: 75 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,7 @@ import {
2020
UnexpectedError,
2121
withSource,
2222
} from "../src/parser/parser_lib.ts";
23-
import {
24-
Definition,
25-
Determiner,
26-
Dictionary,
27-
Noun,
28-
NounForms,
29-
VerbForms,
30-
} from "./type.ts";
23+
import { Definition, Dictionary, VerbForms } from "./type.ts";
3124

3225
const RESERVED_SYMBOLS = "#()*+/:;<=>@[\\]^`{|}~";
3326
const WORDS = new RegExp(`[^${escapeRegex(RESERVED_SYMBOLS)}]`);
@@ -117,66 +110,62 @@ const nounOnly = choiceOnlyOne(
117110
.with(optionalAll(keyword("gerund"))),
118111
),
119112
)
120-
.map<NounForms & { gerund: boolean }>(
121-
([noun, gerund]) => {
122-
const sentence = nlp(noun);
123-
sentence.tag("Noun");
124-
const singular = sentence
125-
.nouns()
126-
.toSingular()
127-
.text();
128-
const plural = sentence
129-
.nouns()
130-
.toPlural()
131-
.text();
132-
if (singular === "" || plural === "") {
133-
throw new ArrayResultError(
134-
`no singular or plural form found for "${noun}". consider ` +
135-
"providing both singular and plural forms instead",
136-
);
137-
}
138-
if (noun !== singular) {
139-
throw new ArrayResultError(
140-
`conjugation error: "${noun}" is not "${singular}". ` +
141-
"consider providing both singular and plural forms instead",
142-
);
143-
}
144-
return {
145-
singular: escapeHtml(singular),
146-
plural: escapeHtml(plural),
147-
gerund: gerund != null,
148-
};
149-
},
150-
),
113+
.map(([noun, gerund]) => {
114+
const sentence = nlp(noun);
115+
sentence.tag("Noun");
116+
const singular = sentence
117+
.nouns()
118+
.toSingular()
119+
.text();
120+
const plural = sentence
121+
.nouns()
122+
.toPlural()
123+
.text();
124+
if (singular === "" || plural === "") {
125+
throw new ArrayResultError(
126+
`no singular or plural form found for "${noun}". consider ` +
127+
"providing both singular and plural forms instead",
128+
);
129+
}
130+
if (noun !== singular) {
131+
throw new ArrayResultError(
132+
`conjugation error: "${noun}" is not "${singular}". ` +
133+
"consider providing both singular and plural forms instead",
134+
);
135+
}
136+
return {
137+
singular: escapeHtml(singular),
138+
plural: escapeHtml(plural),
139+
gerund: gerund != null,
140+
};
141+
}),
151142
sequence(
152143
word,
153144
tag(
154145
keyword("n")
155146
.with(sequence(optionalAll(keyword("gerund")), number)),
156147
),
157148
)
158-
.map<NounForms & { gerund: boolean }>(
159-
([noun, [gerund, number]]) => {
160-
let singular: null | string;
161-
let plural: null | string;
162-
switch (number) {
163-
case "singular":
164-
case "plural":
165-
switch (number) {
166-
case "singular":
167-
singular = noun;
168-
plural = null;
169-
break;
170-
case "plural":
171-
singular = null;
172-
plural = noun;
173-
break;
174-
}
175-
break;
176-
}
177-
return { singular, plural, gerund: gerund != null };
178-
},
179-
),
149+
.map(([noun, [gerund, number]]) => {
150+
let singular: null | string;
151+
let plural: null | string;
152+
switch (number) {
153+
case "singular":
154+
case "plural":
155+
switch (number) {
156+
case "singular":
157+
singular = noun;
158+
plural = null;
159+
break;
160+
case "plural":
161+
singular = null;
162+
plural = noun;
163+
break;
164+
}
165+
break;
166+
}
167+
return { singular, plural, gerund: gerund != null };
168+
}),
180169
sequence(
181170
word,
182171
optionalAll(slash.with(word)),
@@ -185,13 +174,11 @@ const nounOnly = choiceOnlyOne(
185174
.with(optionalAll(keyword("gerund"))),
186175
),
187176
)
188-
.map<NounForms & { gerund: boolean }>(
189-
([singular, plural, gerund]) => ({
190-
singular,
191-
plural,
192-
gerund: gerund != null,
193-
}),
194-
),
177+
.map(([singular, plural, gerund]) => ({
178+
singular,
179+
plural,
180+
gerund: gerund != null,
181+
})),
195182
);
196183
const determinerType = choiceOnlyOne(
197184
keyword("article"),
@@ -208,17 +195,19 @@ const determiner = sequence(
208195
optionalAll(slash.with(word)),
209196
tag(keyword("d").with(sequence(determinerType, optionalNumber))),
210197
)
211-
.map<Determiner>(([determiner, plural, [kind, quantity]]) => ({
212-
determiner,
213-
plural,
214-
kind,
215-
quantity: quantity ?? "both",
216-
}));
198+
.map(([determiner, plural, [kind, quantity]]) =>
199+
({
200+
determiner,
201+
plural,
202+
kind,
203+
quantity: quantity ?? "both",
204+
}) as const
205+
);
217206
const adjectiveKind = choiceOnlyOne(
218207
keyword("opinion"),
219208
keyword("size"),
220209
sequence(keyword("physical"), keyword("quality"))
221-
.map<"physical quality">(() => "physical quality"),
210+
.map(() => "physical quality" as const),
222211
keyword("age"),
223212
keyword("color"),
224213
keyword("origin"),
@@ -249,17 +238,17 @@ const noun = sequence(
249238
.skip(tag(sequence(keyword("n"), keyword("proper")))),
250239
),
251240
)
252-
.map<Noun>(([determiner, adjective, noun, post]) => {
253-
return {
241+
.map(([determiner, adjective, noun, post]) =>
242+
({
254243
...noun,
255244
determiner,
256245
adjective,
257246
postAdjective: mapNullable(
258247
post,
259248
([adjective, name]) => ({ adjective, name }),
260249
),
261-
};
262-
});
250+
}) as const
251+
);
263252
function verbOnly(tagInside: Parser<unknown>): Parser<VerbForms> {
264253
return choiceOnlyOne(
265254
sequence(
@@ -437,15 +426,13 @@ const definition = choiceOnlyOne<Definition>(
437426
),
438427
)
439428
.skip(semicolon)
440-
.map((
441-
[
442-
singularSubject,
443-
singularObject,
444-
pluralSubject,
445-
pluralObject,
446-
perspective,
447-
],
448-
) => ({
429+
.map(([
430+
singularSubject,
431+
singularObject,
432+
pluralSubject,
433+
pluralObject,
434+
perspective,
435+
]) => ({
449436
type: "personal pronoun",
450437
singular: { subject: singularSubject, object: singularObject },
451438
plural: { subject: pluralSubject, object: pluralObject },

src/parser/filter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ export function filter<T>(
370370
rules: ReadonlyArray<(value: T) => boolean>,
371371
): (value: T) => boolean {
372372
return (value) => {
373-
const result: ReadonlyArray<null | ReadonlyArray<unknown>> = rules.map(
373+
const result = rules.map(
374374
(rule) => {
375375
try {
376376
if (rule(value)) {

src/parser/lexer.ts

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ const properWords = allAtLeastOnce(
7070
match(/[A-Z][a-zA-Z]*/, "proper word").skip(spaces),
7171
)
7272
.map((array) => array.join(" "))
73-
.map<Token>((words) => ({ type: "proper word", words, kind: "latin" }));
73+
.map((words) => ({ type: "proper word", words, kind: "latin" }) as const);
7474
function specificWord(thatWord: string): Parser<string> {
7575
return word.filter((thisWord) =>
7676
thatWord === thisWord ||
@@ -79,20 +79,18 @@ function specificWord(thatWord: string): Parser<string> {
7979
}
8080
const multipleA = specificWord("a")
8181
.with(count(allAtLeastOnce(specificWord("a"))))
82-
.map<Token>((count) => ({ type: "multiple a", count: count + 1 }));
82+
.map((count) => ({ type: "multiple a", count: count + 1 }) as const);
8383
const repeatingLetter = match(/[a-zA-Z]/, "latin letter")
8484
.then((letter) =>
8585
count(all(matchString(letter)))
86-
.map<readonly [letter: string, number: number]>(
87-
(count) => [letter, count + 1],
88-
)
86+
.map((count) => [letter, count + 1] as const)
8987
);
9088
const longWord = allAtLeastOnce(repeatingLetter)
9189
.skip(spaces)
92-
.map<Token & { type: "long word" }>((letters) => {
90+
.map((letters) => {
9391
const word = letters.map(([letter]) => letter).join("");
9492
const length = sumOf(letters, ([_, count]) => count) - word.length + 1;
95-
return { type: "long word", word, length };
93+
return { type: "long word", word, length } as const;
9694
})
9795
.filter(({ word }) => /^[a-z]/.test(word))
9896
.filter(({ length }) => length > 1);
@@ -102,7 +100,7 @@ const xAlaX = lazy(() =>
102100
sequence(specificWord("ala"), specificWord(word)).map(() => word)
103101
)
104102
)
105-
.map<Token>((word) => ({ type: "x ala x", word }));
103+
.map((word) => ({ type: "x ala x", word }) as const);
106104
const punctuation = choiceOnlyOne(
107105
allAtLeastOnce(
108106
match(SENTENCE_TERMINATOR, "punctuation")
@@ -112,7 +110,7 @@ const punctuation = choiceOnlyOne(
112110
.map((punctuation) => punctuation.join("").replaceAll("...", ELLIPSIS)),
113111
newline.map(() => "."),
114112
)
115-
.map<Token>((punctuation) => ({ type: "punctuation", punctuation }));
113+
.map((punctuation) => ({ type: "punctuation", punctuation }) as const);
116114
const cartoucheElement = choiceOnlyOne(
117115
singleUcsurWord
118116
.skip(match(NSK_COLON, "full width colon").skip(spaces)),
@@ -148,11 +146,13 @@ const cartouche = specificSpecialUcsur(START_OF_CARTOUCHE)
148146
);
149147
const cartouches = allAtLeastOnce(cartouche)
150148
.map((words) => words.join(" "))
151-
.map<Token>((words) => ({
152-
type: "proper word",
153-
words,
154-
kind: "cartouche",
155-
}));
149+
.map((words) =>
150+
({
151+
type: "proper word",
152+
words,
153+
kind: "cartouche",
154+
}) as const
155+
);
156156
function longContainer<T>(
157157
left: string,
158158
right: string,
@@ -172,42 +172,47 @@ const longGlyphHead = choiceOnlyOne(
172172
combinedGlyphs,
173173
ucsur.map((word) => [word]),
174174
);
175-
const spaceLongGlyph = sequence(longGlyphHead, longSpaceContainer)
176-
.map<Token>(([words, spaceLength]) => ({
177-
type: "space long glyph",
178-
words,
179-
spaceLength,
180-
}));
175+
const spaceLongGlyph = sequence(
176+
longGlyphHead,
177+
longSpaceContainer,
178+
)
179+
.map(([words, spaceLength]) =>
180+
({
181+
type: "space long glyph",
182+
words,
183+
spaceLength,
184+
}) as const
185+
);
181186
const headedLongGlyphStart = longGlyphHead
182187
.skip(specificSpecialUcsur(START_OF_LONG_GLYPH))
183188
.skip(spaces)
184-
.map<Token>((words) => ({ type: "headed long glyph start", words }));
189+
.map((words) => ({ type: "headed long glyph start", words }) as const);
185190
const headlessLongGlyphEnd = specificSpecialUcsur(END_OF_LONG_GLYPH)
186191
.skip(spaces)
187-
.map<Token>(() => ({ type: "headless long glyph end" }));
192+
.map(() => ({ type: "headless long glyph end" }) as const);
188193
const headlessLongGlyphStart = specificSpecialUcsur(START_OF_REVERSE_LONG_GLYPH)
189194
.skip(spaces)
190-
.map<Token>(() => ({ type: "headless long glyph end" }));
195+
.map(() => ({ type: "headless long glyph end" }) as const);
191196
const headedLongGlyphEnd = specificSpecialUcsur(END_OF_REVERSE_LONG_GLYPH)
192197
.with(longGlyphHead)
193198
.skip(spaces)
194-
.map<Token>((words) => ({ type: "headed long glyph start", words }));
199+
.map((words) => ({ type: "headed long glyph start", words }) as const);
195200
const insideLongGlyph = specificSpecialUcsur(END_OF_REVERSE_LONG_GLYPH)
196201
.with(longGlyphHead)
197202
.skip(specificSpecialUcsur(START_OF_LONG_GLYPH))
198203
.skip(spaces)
199-
.map<Token>((words) => ({ type: "inside long glyph", words }));
204+
.map((words) => ({ type: "inside long glyph", words }) as const);
200205
const combinedGlyphsToken = combinedGlyphs
201206
.skip(spaces)
202-
.map<Token>((words) => ({ type: "combined glyphs", words }));
203-
const wordToken = word.map<Token>((word) => ({ type: "word", word }));
207+
.map((words) => ({ type: "combined glyphs", words }) as const);
208+
const wordToken = word.map((word) => ({ type: "word", word }) as const);
204209

205210
Parser.startCache(cache);
206211

207-
export const token = choiceOnlyOne(
212+
export const token = choiceOnlyOne<Token>(
208213
xAlaX,
209214
multipleA,
210-
choice(longWord, wordToken),
215+
choice<Token>(longWord, wordToken),
211216
properWords,
212217
// UCSUR only
213218
spaceLongGlyph,

0 commit comments

Comments
 (0)