@@ -24,7 +24,19 @@ import {
24
24
withPosition ,
25
25
withSource ,
26
26
} from "../src/parser/parser_lib.ts" ;
27
- import { Definition , Dictionary , Noun , PartialVerb } from "./type.ts" ;
27
+ import {
28
+ Adjective ,
29
+ Adverb ,
30
+ Definition ,
31
+ Determiner ,
32
+ Dictionary ,
33
+ Entry ,
34
+ IndirectObject ,
35
+ Noun ,
36
+ NounForms ,
37
+ PartialVerb ,
38
+ PostAdjective ,
39
+ } from "./type.ts" ;
28
40
29
41
const RESERVED_SYMBOLS = "#()*+/:;<=>@[\\]^`{|}~" ;
30
42
@@ -51,7 +63,7 @@ const ignore = allWithCheck(
51
63
choiceWithCheck ( spaces , comment ) ,
52
64
) ,
53
65
) ;
54
- function lex < const T > ( parser : Parser < T > ) {
66
+ function lex < T > ( parser : Parser < T > ) {
55
67
return parser . skip ( ignore ) ;
56
68
}
57
69
const wordWithPosition = lex (
@@ -65,7 +77,7 @@ const comma = lex(matchString(",", "comma"));
65
77
const semicolon = lex ( matchString ( ";" , "semicolon" ) ) ;
66
78
const slash = lex ( matchString ( "/" , "slash" ) ) ;
67
79
68
- const keyword = memoize ( < const T extends string > ( keyword : T ) =>
80
+ const keyword = memoize ( < T extends string > ( keyword : T ) =>
69
81
lex ( withPosition ( match ( / [ a - z \- ] + / , `"${ keyword } "` ) ) )
70
82
. map ( ( positioned ) =>
71
83
positioned . value === keyword ? positioned . value : throwError (
@@ -100,10 +112,10 @@ const perspective = choiceOnlyOne(
100
112
keyword ( "second" ) ,
101
113
keyword ( "third" ) ,
102
114
) ;
103
- function tag < const T > ( parser : Parser < T > ) {
115
+ function tag < T > ( parser : Parser < T > ) {
104
116
return openParenthesis . with ( parser ) . skip ( closeParenthesis ) ;
105
117
}
106
- function template < const T > ( parser : Parser < T > ) {
118
+ function template < T > ( parser : Parser < T > ) {
107
119
return openBracket . with ( parser ) . skip ( closeBracket ) ;
108
120
}
109
121
const simpleUnit = memoize ( ( kind : string ) => word . skip ( tag ( keyword ( kind ) ) ) ) ;
@@ -120,60 +132,64 @@ const nounOnly = checkedSequence(
120
132
sequence ( optionalAll ( keyword ( "gerund" ) ) , optionalNumber )
121
133
. skip ( closeParenthesis ) ,
122
134
)
123
- . mapWithPositionedError ( ( [ [ noun , plural ] , [ gerund , number ] ] ) => {
124
- if ( plural == null ) {
125
- if ( number == null ) {
126
- const sentence = nlp ( noun ) ;
127
- sentence . tag ( "Noun" ) ;
128
- const singular = sentence
129
- . nouns ( )
130
- . toSingular ( )
131
- . text ( ) ;
132
- const plural = sentence
133
- . nouns ( )
134
- . toPlural ( )
135
- . text ( ) ;
136
- if ( singular === "" || plural === "" ) {
137
- throw `no singular or plural form found for "${ noun } ". consider ` +
138
- "providing both singular and plural forms instead" ;
135
+ . mapWithPositionedError (
136
+ (
137
+ [ [ noun , plural ] , [ gerund , number ] ] ,
138
+ ) : NounForms & Readonly < { gerund : boolean } > => {
139
+ if ( plural == null ) {
140
+ if ( number == null ) {
141
+ const sentence = nlp ( noun ) ;
142
+ sentence . tag ( "Noun" ) ;
143
+ const singular = sentence
144
+ . nouns ( )
145
+ . toSingular ( )
146
+ . text ( ) ;
147
+ const plural = sentence
148
+ . nouns ( )
149
+ . toPlural ( )
150
+ . text ( ) ;
151
+ if ( singular === "" || plural === "" ) {
152
+ throw `no singular or plural form found for "${ noun } ". consider ` +
153
+ "providing both singular and plural forms instead" ;
154
+ }
155
+ if ( noun !== singular ) {
156
+ throw `conjugation error: "${ noun } " is not "${ singular } ". ` +
157
+ "consider providing both singular and plural forms instead" ;
158
+ }
159
+ return {
160
+ singular : escapeHtml ( singular ) ,
161
+ plural : escapeHtml ( plural ) ,
162
+ gerund : gerund != null ,
163
+ } ;
164
+ } else {
165
+ const escaped = escapeHtml ( noun ) ;
166
+ let singular : null | string ;
167
+ let plural : null | string ;
168
+ switch ( number ) {
169
+ case "singular" :
170
+ singular = escaped ;
171
+ plural = null ;
172
+ break ;
173
+ case "plural" :
174
+ singular = null ;
175
+ plural = escaped ;
176
+ break ;
177
+ }
178
+ return { singular, plural, gerund : gerund != null } ;
139
179
}
140
- if ( noun !== singular ) {
141
- throw `conjugation error: "${ noun } " is not "${ singular } ". ` +
142
- "consider providing both singular and plural forms instead" ;
180
+ } else {
181
+ if ( number != null ) {
182
+ throw "plural or singular keyword within tag " +
183
+ "must not be provided when singular and plural forms are defined" ;
143
184
}
144
185
return {
145
- singular : escapeHtml ( singular ) ,
146
- plural : escapeHtml ( plural ) ,
186
+ singular : escapeHtml ( noun ) ,
187
+ plural,
147
188
gerund : gerund != null ,
148
189
} ;
149
- } else {
150
- const escaped = escapeHtml ( noun ) ;
151
- let singular : null | string ;
152
- let plural : null | string ;
153
- switch ( number ) {
154
- case "singular" :
155
- singular = escaped ;
156
- plural = null ;
157
- break ;
158
- case "plural" :
159
- singular = null ;
160
- plural = escaped ;
161
- break ;
162
- }
163
- return { singular, plural, gerund : gerund != null } ;
164
190
}
165
- } else {
166
- if ( number != null ) {
167
- throw "plural or singular keyword within tag " +
168
- "must not be provided when singular and plural forms are defined" ;
169
- }
170
- return {
171
- singular : escapeHtml ( noun ) ,
172
- plural,
173
- gerund : gerund != null ,
174
- } ;
175
- }
176
- } ) ;
191
+ } ,
192
+ ) ;
177
193
const determinerType = choiceOnlyOne (
178
194
keyword ( "article" ) ,
179
195
keyword ( "demonstrative" ) ,
@@ -193,7 +209,7 @@ const determiner = checkedSequence(
193
209
) ,
194
210
sequence ( determinerType , optionalNumber . skip ( closeParenthesis ) ) ,
195
211
)
196
- . map ( ( [ [ determiner , plural ] , [ kind , quantity ] ] ) => ( {
212
+ . map ( ( [ [ determiner , plural ] , [ kind , quantity ] ] ) : Determiner => ( {
197
213
determiner,
198
214
plural,
199
215
kind,
@@ -218,7 +234,7 @@ const adverb = checkedSequence(
218
234
word . skip ( openParenthesis ) . skip ( keyword ( "adv" ) ) ,
219
235
optionalAll ( keyword ( "negative" ) ) . skip ( closeParenthesis ) ,
220
236
)
221
- . map ( ( [ adverb , negative ] ) => ( {
237
+ . map ( ( [ adverb , negative ] ) : Adverb => ( {
222
238
adverb,
223
239
negative : negative != null ,
224
240
} ) ) ;
@@ -232,7 +248,7 @@ const adjective = checkedSequence(
232
248
optionalAll ( keyword ( "gerund-like" ) ) . skip ( closeParenthesis ) ,
233
249
) ,
234
250
)
235
- . map ( ( [ [ adverbs , adjective ] , [ kind , gerundLike ] ] ) => ( {
251
+ . map ( ( [ [ adverbs , adjective ] , [ kind , gerundLike ] ] ) : Adjective => ( {
236
252
adverbs,
237
253
adjective,
238
254
kind,
@@ -247,10 +263,10 @@ const noun = sequence(
247
263
simpleUnit ( "adj" ) ,
248
264
word . skip ( tag ( sequence ( keyword ( "n" ) , keyword ( "proper" ) ) ) ) ,
249
265
)
250
- . map ( ( [ adjective , name ] ) => ( { adjective, name } ) ) ,
266
+ . map ( ( [ adjective , name ] ) : PostAdjective => ( { adjective, name } ) ) ,
251
267
) ,
252
268
)
253
- . map ( ( [ determiners , adjectives , noun , postAdjective ] ) => ( {
269
+ . map ( ( [ determiners , adjectives , noun , postAdjective ] ) : Noun => ( {
254
270
...noun ,
255
271
determiners,
256
272
adjectives,
@@ -264,7 +280,7 @@ const checkedNoun = new CheckedParser(
264
280
) ,
265
281
noun ,
266
282
) ;
267
- function checkedSimpleUnitWith < const T > ( tag : string , after : Parser < T > ) {
283
+ function checkedSimpleUnitWith < T > ( tag : string , after : Parser < T > ) {
268
284
return checkedSequence (
269
285
word . skip ( openParenthesis ) . skip ( keyword ( tag ) ) ,
270
286
closeParenthesis . with ( after ) ,
@@ -281,19 +297,22 @@ function checkedSimpleUnitWithTemplate(
281
297
. map ( ( [ word ] ) => word ) ;
282
298
}
283
299
const interjectionDefinition = checkedSimpleUnit ( "i" )
284
- . map ( ( interjection ) => ( { type : "interjection" , interjection } ) ) ;
300
+ . map ( ( interjection ) : Definition => ( { type : "interjection" , interjection } ) ) ;
285
301
const particleDefinition = checkedSequence (
286
302
word . skip ( openParenthesis ) . skip ( keyword ( "particle" ) ) ,
287
303
sequence ( keyword ( "def" ) , closeParenthesis ) ,
288
304
)
289
- . map ( ( [ definition ] ) => ( { type : "particle definition" , definition } ) ) ;
305
+ . map ( ( [ definition ] ) : Definition => ( {
306
+ type : "particle definition" ,
307
+ definition,
308
+ } ) ) ;
290
309
const prepositionDefinition = checkedSimpleUnitWithTemplate (
291
310
"prep" ,
292
311
sequence ( keyword ( "indirect" ) , keyword ( "object" ) ) ,
293
312
)
294
- . map ( ( preposition ) => ( { type : "preposition" , preposition } ) ) ;
313
+ . map ( ( preposition ) : Definition => ( { type : "preposition" , preposition } ) ) ;
295
314
const numeralDefinition = checkedSimpleUnit ( "num" )
296
- . mapWithPositionedError ( ( num ) => {
315
+ . mapWithPositionedError ( ( num ) : Definition => {
297
316
const numeral = + num ;
298
317
if ( ! Number . isInteger ( numeral ) || numeral < 0 ) {
299
318
throw `"${ num } " is not a non-negative integer` ;
@@ -313,7 +332,7 @@ const fillerDefinition = checkedSequence(
313
332
. map ( ( [ first , rest ] ) => [ first , ...rest ] ) ,
314
333
closeParenthesis ,
315
334
)
316
- . mapWithPositionedError ( ( [ forms ] ) => {
335
+ . mapWithPositionedError ( ( [ forms ] ) : Definition => {
317
336
if ( forms . length === 1 ) {
318
337
return {
319
338
type : "filler" ,
@@ -349,7 +368,7 @@ const fourFormPersonalPronounDefinition = checkedSequence(
349
368
. map ( ( [
350
369
[ singularSubject , singularObject , pluralSubject , pluralObject ] ,
351
370
perspective ,
352
- ] ) => ( {
371
+ ] ) : Definition => ( {
353
372
type : "personal pronoun" ,
354
373
singular : { subject : singularSubject , object : singularObject } ,
355
374
plural : { subject : pluralSubject , object : pluralObject } ,
@@ -365,7 +384,7 @@ const twoFormPersonalPronounDefinition = checkedSequence(
365
384
number . skip ( closeParenthesis ) ,
366
385
) ,
367
386
)
368
- . map ( ( [ [ subject , object ] , [ perspective , number ] ] ) => ( {
387
+ . map ( ( [ [ subject , object ] , [ perspective , number ] ] ) : Definition => ( {
369
388
type : "personal pronoun" ,
370
389
singular : null ,
371
390
plural : null ,
@@ -397,7 +416,7 @@ const nounDefinition = new CheckedParser(
397
416
) ,
398
417
) ,
399
418
)
400
- . map ( ( [ noun , preposition ] ) =>
419
+ . map ( ( [ noun , preposition ] ) : Definition =>
401
420
preposition == null
402
421
? { ...noun , type : "noun" }
403
422
: { type : "noun preposition" , noun, preposition }
@@ -410,7 +429,10 @@ const compoundAdjectiveDefinition = checkedSequence(
410
429
. skip ( keyword ( "c" ) ) ,
411
430
closeParenthesis . with ( adjective . parser ) ,
412
431
)
413
- . map ( ( adjectives ) => ( { type : "compound adjective" , adjectives } ) )
432
+ . map ( ( adjectives ) : Definition & { type : "compound adjective" } => ( {
433
+ type : "compound adjective" ,
434
+ adjectives,
435
+ } ) )
414
436
. filterWithPositionedError ( ( { adjectives } ) =>
415
437
adjectives . every ( ( adjective ) => adjective . adverbs . length === 0 ) ||
416
438
throwError ( "compound adjective cannot have adverbs" )
@@ -430,11 +452,14 @@ const verbDefinition = checkedSequence(
430
452
closeBracket
431
453
. with ( optionalWithCheck (
432
454
checkedSimpleUnitWith ( "prep" , noun )
433
- . map ( ( [ preposition , object ] ) => ( { preposition, object } ) ) ,
455
+ . map ( ( [ preposition , object ] ) : IndirectObject => ( {
456
+ preposition,
457
+ object,
458
+ } ) ) ,
434
459
) )
435
460
. map ( nullableAsArray ) ,
436
461
)
437
- . map ( ( [ _ , indirectObjects ] ) => ( {
462
+ . map ( ( [ _ , indirectObjects ] ) : null | PartialVerb => ( {
438
463
directObject : null ,
439
464
indirectObjects,
440
465
forObject : true ,
@@ -444,7 +469,7 @@ const verbDefinition = checkedSequence(
444
469
sequence ( closeParenthesis , openBracket , keyword ( "predicate" ) ) ,
445
470
closeBracket ,
446
471
)
447
- . map ( ( ) => ( {
472
+ . map ( ( ) : null | PartialVerb => ( {
448
473
directObject : null ,
449
474
indirectObjects : [ ] ,
450
475
forObject : false ,
@@ -454,12 +479,12 @@ const verbDefinition = checkedSequence(
454
479
keyword ( "modal" ) ,
455
480
sequence ( closeParenthesis , template ( keyword ( "predicate" ) ) ) ,
456
481
)
457
- . map ( ( ) => null ) ,
482
+ . map ( ( ) : null | PartialVerb => null ) ,
458
483
checkedSequence (
459
484
keyword ( "linking" ) ,
460
485
sequence ( closeParenthesis , template ( keyword ( "predicate" ) ) ) ,
461
486
)
462
- . map ( ( ) => ( {
487
+ . map ( ( ) : null | PartialVerb => ( {
463
488
directObject : null ,
464
489
indirectObjects : [ ] ,
465
490
forObject : false ,
@@ -484,7 +509,7 @@ const verbDefinition = checkedSequence(
484
509
) ,
485
510
) ,
486
511
)
487
- . map < PartialVerb > ( ( [ _ , [ directObject , rawIndirectObject ] ] ) => {
512
+ . map ( ( [ _ , [ directObject , rawIndirectObject ] ] ) : PartialVerb => {
488
513
if ( rawIndirectObject == null ) {
489
514
return {
490
515
directObject,
@@ -516,7 +541,7 @@ const verbDefinition = checkedSequence(
516
541
} ) ,
517
542
) ,
518
543
)
519
- . mapWithPositionedError < Definition > ( ( [ [ verb , forms ] , rest ] ) => {
544
+ . mapWithPositionedError ( ( [ [ verb , forms ] , rest ] ) : Definition => {
520
545
if ( rest == null ) {
521
546
if ( forms != null ) {
522
547
throw "modal verbs shouldn't be conjugated" ;
@@ -561,12 +586,18 @@ const definition = choiceWithCheck(
561
586
// compound adjective parser must come before adjective parser
562
587
compoundAdjectiveDefinition ,
563
588
// adjective parser must come before adverb parser
564
- adjective . map ( ( adjective ) => ( { ...adjective , type : "adjective" } ) ) ,
589
+ adjective . map ( ( adjective ) : Definition => ( {
590
+ ...adjective ,
591
+ type : "adjective" ,
592
+ } ) ) ,
565
593
verbDefinition ,
566
- adverb . map ( ( adverb ) => ( { ...adverb , type : "adverb" } ) ) ,
594
+ adverb . map ( ( adverb ) : Definition => ( { ...adverb , type : "adverb" } ) ) ,
567
595
interjectionDefinition ,
568
596
particleDefinition ,
569
- determiner . map ( ( determiner ) => ( { ...determiner , type : "determiner" } ) ) ,
597
+ determiner . map ( ( determiner ) : Definition => ( {
598
+ ...determiner ,
599
+ type : "determiner" ,
600
+ } ) ) ,
570
601
prepositionDefinition ,
571
602
numeralDefinition ,
572
603
fillerDefinition ,
@@ -589,7 +620,10 @@ const entry = withSource(
589
620
) ,
590
621
) ,
591
622
)
592
- . map ( ( [ definitions , source ] ) => ( { definitions, source : source . trimEnd ( ) } ) ) ;
623
+ . map ( ( [ definitions , source ] ) : Entry => ( {
624
+ definitions,
625
+ source : source . trimEnd ( ) ,
626
+ } ) ) ;
593
627
export const dictionaryParser : Parser < Dictionary > = ignore
594
628
. with (
595
629
allWithCheck ( new CheckedParser ( notEnd , sequence ( positionedHead , entry ) ) ) ,
0 commit comments