@@ -13,18 +13,18 @@ import {
13
13
checkedSequence ,
14
14
choiceOnlyOne ,
15
15
choiceWithCheck ,
16
- lookAhead ,
17
16
match ,
18
17
matchString ,
19
18
notEnd ,
19
+ nothing ,
20
20
optionalAll ,
21
21
optionalWithCheck ,
22
22
Parser ,
23
23
sequence ,
24
24
UnexpectedError ,
25
25
withSource ,
26
26
} from "../src/parser/parser_lib.ts" ;
27
- import { Definition , Dictionary , VerbForms } from "./type.ts" ;
27
+ import { Definition , Dictionary , Noun , PartialVerb } from "./type.ts" ;
28
28
29
29
const RESERVED_SYMBOLS = "#()*+/:;<=>@[\\]^`{|}~" ;
30
30
@@ -249,88 +249,31 @@ const noun = sequence(
249
249
postAdjective,
250
250
} ) as const
251
251
) ;
252
- function verbOnly ( tagInside : Parser < unknown > ) : Parser < VerbForms > {
253
- return choiceWithCheck (
254
- checkedSequence (
255
- word . skip ( slash ) ,
256
- sequence (
257
- word . skip ( slash ) ,
258
- word . skip ( tag ( tagInside ) ) ,
259
- ) ,
260
- )
261
- . map ( ( [ presentPlural , [ presentSingular , past ] ] ) => ( {
262
- presentPlural,
263
- presentSingular,
264
- past,
265
- } ) )
266
- . filter ( ( { presentPlural, presentSingular, past } ) => {
267
- const [ _ , ...pluralParticles ] = presentPlural . split ( " " ) ;
268
- const [ _1 , ...singularParticles ] = presentSingular . split ( " " ) ;
269
- const [ _2 , ...pastParticles ] = past . split ( " " ) ;
270
- const allMatched =
271
- pluralParticles . length === singularParticles . length &&
272
- pluralParticles . length === pastParticles . length &&
273
- pluralParticles . every ( ( particle , i ) =>
274
- particle === singularParticles [ i ] && particle === pastParticles [ i ]
275
- ) ;
276
- if ( allMatched ) {
277
- return true ;
278
- } else {
279
- throw new ArrayResultError (
280
- "mismatched verb particles " +
281
- `"${ presentPlural } /${ presentSingular } /${ past } "` ,
282
- ) ;
283
- }
284
- } ) ,
285
- checkedAsWhole ( unescapedWord . skip ( tag ( tagInside ) ) )
286
- . map ( ( verb ) => {
287
- const sentence = nlp ( verb ) ;
288
- sentence . tag ( "Verb" ) ;
289
- const conjugations = sentence . verbs ( ) . conjugate ( ) [ 0 ] as undefined | {
290
- Infinitive : string ;
291
- PastTense : string ;
292
- PresentTense : string ;
293
- Gerund : string ;
294
- FutureTense : string ;
295
- } ;
296
- if ( conjugations == null ) {
297
- throw new ArrayResultError (
298
- `no verb conjugation found for "${ verb } ". consider providing ` +
299
- "all conjugations instead" ,
300
- ) ;
301
- }
302
- if ( verb !== conjugations . Infinitive ) {
303
- throw new ArrayResultError (
304
- `conjugation error: "${ verb } " is not ` +
305
- `"${ conjugations . Infinitive } ". consider providing all ` +
306
- "conjugations instead" ,
307
- ) ;
308
- }
309
- return {
310
- presentPlural : escapeHtml ( conjugations . Infinitive ) ,
311
- presentSingular : escapeHtml ( conjugations . PresentTense ) ,
312
- past : escapeHtml ( conjugations . PastTense ) ,
313
- } ;
314
- } ) ,
252
+ const checkedNoun = new CheckedParser (
253
+ choiceOnlyOne (
254
+ determiner . check ,
255
+ adjective . check ,
256
+ nounOnly . check ,
257
+ ) ,
258
+ noun ,
259
+ ) ;
260
+ function simpleDefinitionWith < T > (
261
+ tag : Parser < unknown > ,
262
+ after : Parser < T > ,
263
+ ) : CheckedParser < readonly [ string , T ] > {
264
+ return checkedSequence (
265
+ word . skip ( openParenthesis ) . skip ( tag ) ,
266
+ closeParenthesis . with ( after ) ,
315
267
) ;
316
268
}
317
- const verb = verbOnly ( keyword ( "v" ) ) ;
318
- const linkingVerb = verbOnly ( sequence ( keyword ( "v" ) , keyword ( "linking" ) ) ) ;
319
269
function simpleDefinition ( tag : Parser < unknown > ) : CheckedParser < string > {
320
- return checkedSequence (
321
- word . skip ( openParenthesis ) . skip ( tag ) ,
322
- closeParenthesis ,
323
- )
324
- . map ( ( [ word ] ) => word ) ;
270
+ return simpleDefinitionWith ( tag , nothing ) . map ( ( [ word ] ) => word ) ;
325
271
}
326
272
function simpleDefinitionWithTemplate (
327
273
tag : Parser < unknown > ,
328
274
templateInside : Parser < unknown > ,
329
275
) : CheckedParser < string > {
330
- return checkedSequence (
331
- word . skip ( openParenthesis ) . skip ( tag ) ,
332
- closeParenthesis . skip ( template ( templateInside ) ) ,
333
- )
276
+ return simpleDefinitionWith ( tag , template ( templateInside ) )
334
277
. map ( ( [ word ] ) => word ) ;
335
278
}
336
279
const interjectionDefinition = simpleDefinition ( keyword ( "i" ) )
@@ -463,99 +406,153 @@ const compoundAdjectiveDefinition = checkedSequence(
463
406
adjective . every ( ( adjective ) => adjective . adverb . length === 0 ) ||
464
407
throwError ( new ArrayResultError ( "compound adjective cannot have adverb" ) )
465
408
) ;
466
- // const verbDefinition_ = checkedSequence(
467
- // sequence(
468
- // unescapedWord,
469
- // optionalWithCheck(
470
- // checkedSequence(slash, sequence(word.skip(slash), word))
471
- // .map(([_, forms]) => forms),
472
- // )
473
- // .parser
474
- // .skip(sequence(openParenthesis, keyword("v"))),
475
- // ),
476
- // );
477
-
478
- // (v modal)
479
- // (v linking) [predicate]
480
- // (v) [predicate]
481
- // (v) [object] Noun?
482
- // (v) Noun? (prep)? [object]?
483
-
484
- const verbDefinition = choiceOnlyOne < Definition > (
409
+ const verbDefinition = checkedSequence (
485
410
sequence (
486
- verb ,
487
- optionalAll ( template ( keyword ( "object" ) ) ) ,
411
+ unescapedWord ,
488
412
optionalWithCheck (
489
- checkedSequence ( simpleUnit ( "prep" ) , noun )
490
- . map ( ( [ preposition , object ] ) => ( { preposition , object } ) ) ,
413
+ checkedSequence ( slash , sequence ( word . skip ( slash ) , word ) )
414
+ . map ( ( [ _ , forms ] ) => forms ) ,
491
415
)
492
- . map ( nullableAsArray ) ,
493
- )
494
- . skip ( lookAhead ( semicolon ) )
495
- . map ( ( [ verb , forObject , indirectObject ] ) => ( {
496
- ...verb ,
497
- type : "verb" ,
498
- directObject : null ,
499
- indirectObject,
500
- forObject : forObject != null ,
501
- predicateType : null ,
502
- } ) ) ,
503
- sequence (
504
- verb ,
505
- optionalWithCheck (
506
- new CheckedParser (
507
- choiceOnlyOne ( determiner . check , adjective . check , nounOnly . check ) ,
508
- noun ,
416
+ . skip ( sequence ( openParenthesis , keyword ( "v" ) ) ) ,
417
+ ) ,
418
+ choiceWithCheck < null | PartialVerb > (
419
+ checkedSequence (
420
+ keyword ( "modal" ) ,
421
+ sequence ( closeParenthesis , template ( keyword ( "predicate" ) ) ) ,
422
+ )
423
+ . map ( ( ) => null ) ,
424
+ checkedSequence (
425
+ keyword ( "linking" ) ,
426
+ sequence ( closeParenthesis , template ( keyword ( "predicate" ) ) ) ,
427
+ )
428
+ . map ( ( ) => ( {
429
+ directObject : null ,
430
+ indirectObject : [ ] ,
431
+ forObject : false ,
432
+ predicateType : "noun adjective" ,
433
+ } ) ) ,
434
+ checkedSequence (
435
+ sequence ( closeParenthesis , openBracket , keyword ( "predicate" ) ) ,
436
+ closeBracket ,
437
+ )
438
+ . map ( ( ) => ( {
439
+ directObject : null ,
440
+ indirectObject : [ ] ,
441
+ forObject : false ,
442
+ predicateType : "verb" ,
443
+ } ) ) ,
444
+ checkedSequence (
445
+ sequence ( closeParenthesis , openBracket , keyword ( "object" ) ) ,
446
+ closeBracket
447
+ . with ( optionalWithCheck (
448
+ simpleDefinitionWith ( keyword ( "prep" ) , noun )
449
+ . map ( ( [ preposition , object ] ) => ( { preposition, object } ) as const ) ,
450
+ ) )
451
+ . map ( nullableAsArray ) ,
452
+ )
453
+ . map ( ( [ _ , indirectObject ] ) => ( {
454
+ directObject : null ,
455
+ indirectObject,
456
+ forObject : true ,
457
+ predicateType : null ,
458
+ } ) ) ,
459
+ new CheckedParser (
460
+ nothing ,
461
+ sequence (
462
+ closeParenthesis
463
+ . with (
464
+ optionalWithCheck ( checkedNoun ) ,
465
+ ) ,
466
+ optionalWithCheck (
467
+ simpleDefinitionWith (
468
+ keyword ( "prep" ) ,
469
+ choiceWithCheck < "template" | Noun > (
470
+ checkedSequence (
471
+ openBracket ,
472
+ sequence ( keyword ( "object" ) , closeBracket ) ,
473
+ )
474
+ . map ( ( ) => "template" as const ) ,
475
+ checkedNoun ,
476
+ ) ,
477
+ ) ,
478
+ ) ,
509
479
) ,
510
- ) ,
511
- optionalWithCheck (
512
- checkedSequence (
513
- simpleUnit ( "prep" ) ,
514
- template ( keyword ( "object" ) ) ,
515
- )
516
- . map ( ( [ preposition ] ) => preposition ) ,
517
- ) ,
518
- )
519
- . skip ( lookAhead ( semicolon ) )
520
- . map ( ( [ verb , directObject , preposition ] ) => ( {
521
- ...verb ,
522
- type : "verb" ,
523
- directObject,
524
- indirectObject : [ ] ,
525
- forObject : preposition ?? false ,
526
- predicateType : null ,
527
- } ) ) ,
528
- verb
529
- . skip ( template ( keyword ( "predicate" ) ) )
530
- . skip ( lookAhead ( semicolon ) )
531
- . map ( ( verb ) => ( {
532
- ...verb ,
533
- type : "verb" ,
534
- directObject : null ,
535
- indirectObject : [ ] ,
536
- forObject : false ,
537
- predicateType : "verb" ,
538
- } ) ) ,
539
- word
540
- . skip ( tag ( sequence ( keyword ( "v" ) , keyword ( "modal" ) ) ) )
541
- . skip ( template ( keyword ( "predicate" ) ) )
542
- . skip ( lookAhead ( semicolon ) )
543
- . map ( ( verb ) => ( {
544
- type : "modal verb" ,
545
- verb,
546
- } ) ) ,
547
- linkingVerb
548
- . skip ( template ( keyword ( "predicate" ) ) )
549
- . skip ( lookAhead ( semicolon ) )
550
- . map ( ( verb ) => ( {
551
- ...verb ,
552
- type : "verb" ,
553
- directObject : null ,
554
- indirectObject : [ ] ,
555
- forObject : false ,
556
- predicateType : "noun adjective" ,
557
- } ) ) ,
558
- ) ;
480
+ )
481
+ . map < PartialVerb > ( ( [ directObject , rawIndirectObject ] ) => {
482
+ if ( rawIndirectObject == null ) {
483
+ return {
484
+ directObject,
485
+ indirectObject : [ ] ,
486
+ forObject : false ,
487
+ predicateType : null ,
488
+ } ;
489
+ } else {
490
+ const [ preposition , indirectObject ] = rawIndirectObject ;
491
+ if ( indirectObject === "template" ) {
492
+ return {
493
+ directObject,
494
+ indirectObject : [ ] ,
495
+ forObject : preposition ,
496
+ predicateType : null ,
497
+ } ;
498
+ } else {
499
+ return {
500
+ directObject,
501
+ indirectObject : [ {
502
+ preposition,
503
+ object : indirectObject ,
504
+ } ] ,
505
+ forObject : false ,
506
+ predicateType : null ,
507
+ } ;
508
+ }
509
+ }
510
+ } ) ,
511
+ ) ,
512
+ )
513
+ . map < Definition > ( ( [ [ verb , forms ] , rest ] ) => {
514
+ if ( rest == null ) {
515
+ if ( forms != null ) {
516
+ throw new ArrayResultError ( "modal verbs shouldn't be conjugated" ) ;
517
+ }
518
+ return { type : "modal verb" , verb : escapeHtml ( verb ) } ;
519
+ } else {
520
+ let presentPlural : string ;
521
+ let presentSingular : string ;
522
+ let past : string ;
523
+ if ( forms == null ) {
524
+ const sentence = nlp ( verb ) ;
525
+ sentence . tag ( "Verb" ) ;
526
+ const conjugations = sentence . verbs ( ) . conjugate ( ) [ 0 ] as undefined | {
527
+ Infinitive : string ;
528
+ PastTense : string ;
529
+ PresentTense : string ;
530
+ Gerund : string ;
531
+ FutureTense : string ;
532
+ } ;
533
+ if ( conjugations == null ) {
534
+ throw new ArrayResultError (
535
+ `no verb conjugation found for "${ verb } ". consider providing ` +
536
+ "all conjugations instead" ,
537
+ ) ;
538
+ }
539
+ if ( verb !== conjugations . Infinitive ) {
540
+ throw new ArrayResultError (
541
+ `conjugation error: "${ verb } " is not ` +
542
+ `"${ conjugations . Infinitive } ". consider providing all ` +
543
+ "conjugations instead" ,
544
+ ) ;
545
+ }
546
+ presentPlural = escapeHtml ( conjugations . Infinitive ) ;
547
+ presentSingular = escapeHtml ( conjugations . PresentTense ) ;
548
+ past = escapeHtml ( conjugations . PastTense ) ;
549
+ } else {
550
+ presentPlural = escapeHtml ( verb ) ;
551
+ [ presentSingular , past ] = forms ;
552
+ }
553
+ return { ...rest , type : "verb" , presentPlural, presentSingular, past } ;
554
+ }
555
+ } ) ;
559
556
const definition = choiceWithCheck < Definition > (
560
557
interjectionDefinition ,
561
558
particleDefinition ,
@@ -572,7 +569,7 @@ const definition = choiceWithCheck<Definition>(
572
569
adjective . map ( ( adjective ) => ( { ...adjective , type : "adjective" } ) ) ,
573
570
adverbDefinition ,
574
571
determiner . map ( ( determiner ) => ( { ...determiner , type : "determiner" } ) ) ,
575
- checkedAsWhole ( verbDefinition ) ,
572
+ verbDefinition ,
576
573
) ;
577
574
const head = sequence ( all ( tokiPonaWord . skip ( comma ) ) , tokiPonaWord )
578
575
. skip ( colon )
0 commit comments