ezmedicationinput 0.1.44 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/advice.js DELETED
@@ -1,1375 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.parseAdditionalInstructions = parseAdditionalInstructions;
7
- exports.findAdditionalInstructionDefinitionByCoding = findAdditionalInstructionDefinitionByCoding;
8
- exports.buildAdditionalInstructionFramesFromCoding = buildAdditionalInstructionFramesFromCoding;
9
- const advice_terminology_json_1 = __importDefault(require("./advice-terminology.json"));
10
- const advice_rules_json_1 = __importDefault(require("./advice-rules.json"));
11
- const lex_1 = require("./lexer/lex");
12
- const types_1 = require("./types");
13
- const text_1 = require("./utils/text");
14
- const SNOMED_SYSTEM = "http://snomed.info/sct";
15
- const ADVICE_TERMINOLOGY = advice_terminology_json_1.default;
16
- const ADVICE_RULES = advice_rules_json_1.default;
17
- const DEFAULT_INSTRUCTION_CONTEXT = {
18
- defaultPredicate: "take",
19
- defaultForce: types_1.AdviceForce.Instruction,
20
- allowFreeTextFallback: false
21
- };
22
- const LEADING_NOISE_WORDS = new Set(["and", "please"]);
23
- const ADMINISTRATION_PREDICATES = new Set(["apply", "take", "use"]);
24
- const NEGATOR_WORDS = new Set(["not", "no", "dont", "don't", "mustnt", "mustn't"]);
25
- const VERB_CONNECTOR_WORDS = new Set(["and", "or"]);
26
- const SIMPLE_TIME_WORDS = new Set(["morning", "evening", "night", "bedtime"]);
27
- const DURATION_UNIT_WORDS = new Set([
28
- "second",
29
- "seconds",
30
- "sec",
31
- "secs",
32
- "minute",
33
- "minutes",
34
- "min",
35
- "mins",
36
- "hour",
37
- "hours",
38
- "hr",
39
- "hrs",
40
- "day",
41
- "days"
42
- ]);
43
- const LEXEMES_BY_SURFACE = Object.create(null);
44
- const CONCEPTS_BY_SURFACE = Object.create(null);
45
- const CONCEPT_KEYS_BY_ID = Object.create(null);
46
- const LEXEME_LIST = [];
47
- const CONCEPT_LIST = [];
48
- let MAX_LEXEME_WORDS = 1;
49
- let MAX_CONCEPT_WORDS = 1;
50
- function normalizeAdditionalInstructionKey(value) {
51
- let prepared = "";
52
- for (let index = 0; index < value.length; index += 1) {
53
- const char = value[index];
54
- const previous = index > 0 ? value[index - 1] : "";
55
- const next = index + 1 < value.length ? value[index + 1] : "";
56
- if (char === "." && /\d/.test(previous) && /\d/.test(next)) {
57
- prepared += "decimalpoint";
58
- continue;
59
- }
60
- prepared += char;
61
- }
62
- return (0, text_1.normalizeLoosePhraseKey)(prepared).replace(/decimalpoint/g, ".");
63
- }
64
- function countWords(value) {
65
- if (!value) {
66
- return 0;
67
- }
68
- let count = 0;
69
- let inWord = false;
70
- for (const char of value) {
71
- if (char === " ") {
72
- if (inWord) {
73
- count += 1;
74
- inWord = false;
75
- }
76
- continue;
77
- }
78
- inWord = true;
79
- }
80
- if (inWord) {
81
- count += 1;
82
- }
83
- return count;
84
- }
85
- function pushLexeme(surfaceKey, entry) {
86
- const bucket = LEXEMES_BY_SURFACE[surfaceKey];
87
- if (bucket) {
88
- bucket.push(entry);
89
- return;
90
- }
91
- LEXEMES_BY_SURFACE[surfaceKey] = [entry];
92
- }
93
- function pushConcept(surfaceKey, entry) {
94
- const bucket = CONCEPTS_BY_SURFACE[surfaceKey];
95
- if (bucket) {
96
- bucket.push(entry);
97
- return;
98
- }
99
- CONCEPTS_BY_SURFACE[surfaceKey] = [entry];
100
- }
101
- function pushConceptKeyById(conceptId, surfaceKey) {
102
- const bucket = CONCEPT_KEYS_BY_ID[conceptId];
103
- if (bucket) {
104
- bucket.push(surfaceKey);
105
- return;
106
- }
107
- CONCEPT_KEYS_BY_ID[conceptId] = [surfaceKey];
108
- }
109
- for (const entry of ADVICE_TERMINOLOGY.lexemes) {
110
- const surfaceKey = normalizeAdditionalInstructionKey(entry.surface);
111
- if (!surfaceKey) {
112
- continue;
113
- }
114
- LEXEME_LIST.push(entry);
115
- pushLexeme(surfaceKey, entry);
116
- const wordCount = countWords(surfaceKey);
117
- if (wordCount > MAX_LEXEME_WORDS) {
118
- MAX_LEXEME_WORDS = wordCount;
119
- }
120
- }
121
- for (const entry of ADVICE_TERMINOLOGY.concepts) {
122
- const surfaceKey = normalizeAdditionalInstructionKey(entry.surface);
123
- if (!surfaceKey) {
124
- continue;
125
- }
126
- CONCEPT_LIST.push(entry);
127
- pushConcept(surfaceKey, entry);
128
- pushConceptKeyById(entry.conceptId, surfaceKey);
129
- const wordCount = countWords(surfaceKey);
130
- if (wordCount > MAX_CONCEPT_WORDS) {
131
- MAX_CONCEPT_WORDS = wordCount;
132
- }
133
- }
134
- function collapseWhitespace(value) {
135
- return value.replace(/\s+/g, " ").trim();
136
- }
137
- function cleanFreeText(value) {
138
- let start = 0;
139
- let end = value.length;
140
- while (start < end) {
141
- const char = value[start];
142
- if (/\s/.test(char) || char === "," || char === ";" || char === ":" || char === "-" || char === ".") {
143
- start += 1;
144
- continue;
145
- }
146
- break;
147
- }
148
- while (end > start) {
149
- const char = value[end - 1];
150
- if (/\s/.test(char) || char === "," || char === ";" || char === ":" || char === "-" || char === ".") {
151
- end -= 1;
152
- continue;
153
- }
154
- break;
155
- }
156
- return collapseWhitespace(value.slice(start, end));
157
- }
158
- function createDefinitionFromSource(source) {
159
- return {
160
- coding: {
161
- system: SNOMED_SYSTEM,
162
- code: source.code,
163
- display: source.display
164
- },
165
- text: source.text,
166
- i18n: { th: source.thai }
167
- };
168
- }
169
- function mapAdviceForce(value) {
170
- switch (value) {
171
- case types_1.AdviceForce.Instruction:
172
- return types_1.AdviceForce.Instruction;
173
- case types_1.AdviceForce.Warning:
174
- return types_1.AdviceForce.Warning;
175
- case types_1.AdviceForce.Caution:
176
- return types_1.AdviceForce.Caution;
177
- case types_1.AdviceForce.Sequence:
178
- return types_1.AdviceForce.Sequence;
179
- default:
180
- throw new Error(`Unsupported advice force: ${value}`);
181
- }
182
- }
183
- function mapAdvicePolarity(value) {
184
- if (!value) {
185
- return undefined;
186
- }
187
- switch (value) {
188
- case types_1.AdvicePolarity.Affirm:
189
- return types_1.AdvicePolarity.Affirm;
190
- case types_1.AdvicePolarity.Negate:
191
- return types_1.AdvicePolarity.Negate;
192
- default:
193
- throw new Error(`Unsupported advice polarity: ${value}`);
194
- }
195
- }
196
- function mapAdviceRelation(value) {
197
- if (!value) {
198
- return undefined;
199
- }
200
- switch (value) {
201
- case types_1.AdviceRelation.With:
202
- return types_1.AdviceRelation.With;
203
- case types_1.AdviceRelation.Without:
204
- return types_1.AdviceRelation.Without;
205
- case types_1.AdviceRelation.Before:
206
- return types_1.AdviceRelation.Before;
207
- case types_1.AdviceRelation.After:
208
- return types_1.AdviceRelation.After;
209
- case types_1.AdviceRelation.During:
210
- return types_1.AdviceRelation.During;
211
- case types_1.AdviceRelation.Then:
212
- return types_1.AdviceRelation.Then;
213
- case types_1.AdviceRelation.Until:
214
- return types_1.AdviceRelation.Until;
215
- case types_1.AdviceRelation.For:
216
- return types_1.AdviceRelation.For;
217
- case types_1.AdviceRelation.In:
218
- return types_1.AdviceRelation.In;
219
- case types_1.AdviceRelation.On:
220
- return types_1.AdviceRelation.On;
221
- default:
222
- throw new Error(`Unsupported advice relation: ${value}`);
223
- }
224
- }
225
- function mapAdviceArgumentRole(value) {
226
- switch (value) {
227
- case types_1.AdviceArgumentRole.Theme:
228
- return types_1.AdviceArgumentRole.Theme;
229
- case types_1.AdviceArgumentRole.Object:
230
- return types_1.AdviceArgumentRole.Object;
231
- case types_1.AdviceArgumentRole.Substance:
232
- return types_1.AdviceArgumentRole.Substance;
233
- case types_1.AdviceArgumentRole.MealState:
234
- return types_1.AdviceArgumentRole.MealState;
235
- case types_1.AdviceArgumentRole.Activity:
236
- return types_1.AdviceArgumentRole.Activity;
237
- case types_1.AdviceArgumentRole.Material:
238
- return types_1.AdviceArgumentRole.Material;
239
- case types_1.AdviceArgumentRole.Site:
240
- return types_1.AdviceArgumentRole.Site;
241
- case types_1.AdviceArgumentRole.Amount:
242
- return types_1.AdviceArgumentRole.Amount;
243
- case types_1.AdviceArgumentRole.Duration:
244
- return types_1.AdviceArgumentRole.Duration;
245
- case types_1.AdviceArgumentRole.Time:
246
- return types_1.AdviceArgumentRole.Time;
247
- case types_1.AdviceArgumentRole.Free:
248
- return types_1.AdviceArgumentRole.Free;
249
- default:
250
- throw new Error(`Unsupported advice argument role: ${value}`);
251
- }
252
- }
253
- function buildAdviceFrameTemplateArgument(source) {
254
- return {
255
- role: mapAdviceArgumentRole(source.role),
256
- text: source.text,
257
- conceptId: source.conceptId
258
- };
259
- }
260
- function buildAdviceFrameTemplate(source) {
261
- const args = [];
262
- for (const arg of source.args) {
263
- args.push(buildAdviceFrameTemplateArgument(arg));
264
- }
265
- return {
266
- force: mapAdviceForce(source.force),
267
- polarity: mapAdvicePolarity(source.polarity),
268
- predicate: {
269
- lemma: source.predicate.lemma,
270
- semanticClass: source.predicate.semanticClass
271
- },
272
- relation: mapAdviceRelation(source.relation),
273
- args
274
- };
275
- }
276
- function buildAdviceArgConceptMatcher(source) {
277
- return {
278
- conceptIds: source.conceptIds.slice(),
279
- role: source.role ? mapAdviceArgumentRole(source.role) : undefined
280
- };
281
- }
282
- function buildAdviceFrameMatcher(source) {
283
- const argConcepts = [];
284
- if (source.argConcepts) {
285
- for (const argConcept of source.argConcepts) {
286
- argConcepts.push(buildAdviceArgConceptMatcher(argConcept));
287
- }
288
- }
289
- const relations = [];
290
- if (source.relations) {
291
- for (const relation of source.relations) {
292
- const mapped = mapAdviceRelation(relation);
293
- if (mapped) {
294
- relations.push(mapped);
295
- }
296
- }
297
- }
298
- return {
299
- predicateLemmas: source.predicateLemmas ? source.predicateLemmas.slice() : undefined,
300
- predicateSemanticClasses: source.predicateSemanticClasses
301
- ? source.predicateSemanticClasses.slice()
302
- : undefined,
303
- relations: relations.length ? relations : undefined,
304
- force: source.force ? mapAdviceForce(source.force) : undefined,
305
- polarity: mapAdvicePolarity(source.polarity),
306
- argConcepts: argConcepts.length ? argConcepts : undefined
307
- };
308
- }
309
- function buildAdviceMatcher(source) {
310
- if ("allOf" in source) {
311
- const allOf = [];
312
- for (const item of source.allOf) {
313
- allOf.push(buildAdviceMatcher(item));
314
- }
315
- return { allOf };
316
- }
317
- if ("anyOf" in source) {
318
- const anyOf = [];
319
- for (const item of source.anyOf) {
320
- anyOf.push(buildAdviceMatcher(item));
321
- }
322
- return { anyOf };
323
- }
324
- if ("not" in source) {
325
- return { not: buildAdviceMatcher(source.not) };
326
- }
327
- if ("frame" in source) {
328
- return { frame: buildAdviceFrameMatcher(source.frame) };
329
- }
330
- if ("argConcept" in source) {
331
- return { argConcept: buildAdviceArgConceptMatcher(source.argConcept) };
332
- }
333
- const normalizedTexts = [];
334
- for (const value of source.normalizedTexts) {
335
- const normalized = normalizeAdditionalInstructionKey(value);
336
- if (normalized) {
337
- normalizedTexts.push(normalized);
338
- }
339
- }
340
- return { normalizedTexts };
341
- }
342
- function buildAdviceCodingRule(source) {
343
- const frames = [];
344
- for (const frame of source.frames) {
345
- frames.push(buildAdviceFrameTemplate(frame));
346
- }
347
- return {
348
- id: source.id,
349
- definition: createDefinitionFromSource(source.definition),
350
- frames,
351
- matcher: buildAdviceMatcher(source.matcher)
352
- };
353
- }
354
- const ADDITIONAL_INSTRUCTION_RULES = [];
355
- for (const sourceRule of ADVICE_RULES.rules) {
356
- ADDITIONAL_INSTRUCTION_RULES.push(buildAdviceCodingRule(sourceRule));
357
- }
358
- function frameHasArgConcept(frame, matcher) {
359
- for (const arg of frame.args) {
360
- if (matcher.role && arg.role !== matcher.role) {
361
- continue;
362
- }
363
- for (const conceptId of matcher.conceptIds) {
364
- if (arg.conceptId === conceptId) {
365
- return true;
366
- }
367
- }
368
- }
369
- return false;
370
- }
371
- function frameMatches(frame, matcher) {
372
- if (matcher.force && frame.force !== matcher.force) {
373
- return false;
374
- }
375
- if (matcher.polarity && frame.polarity !== matcher.polarity) {
376
- return false;
377
- }
378
- if (matcher.relations) {
379
- let relationMatched = false;
380
- for (const relation of matcher.relations) {
381
- if (frame.relation === relation) {
382
- relationMatched = true;
383
- break;
384
- }
385
- }
386
- if (!relationMatched) {
387
- return false;
388
- }
389
- }
390
- if (matcher.predicateLemmas) {
391
- let predicateMatched = false;
392
- for (const lemma of matcher.predicateLemmas) {
393
- if (frame.predicate.lemma === lemma) {
394
- predicateMatched = true;
395
- break;
396
- }
397
- }
398
- if (!predicateMatched) {
399
- return false;
400
- }
401
- }
402
- if (matcher.predicateSemanticClasses) {
403
- let semanticClassMatched = false;
404
- for (const semanticClass of matcher.predicateSemanticClasses) {
405
- if (frame.predicate.semanticClass === semanticClass) {
406
- semanticClassMatched = true;
407
- break;
408
- }
409
- }
410
- if (!semanticClassMatched) {
411
- return false;
412
- }
413
- }
414
- if (matcher.argConcepts) {
415
- for (const argConcept of matcher.argConcepts) {
416
- if (!frameHasArgConcept(frame, argConcept)) {
417
- return false;
418
- }
419
- }
420
- }
421
- return true;
422
- }
423
- function matchesAdviceMatcher(frames, normalizedText, matcher) {
424
- if ("allOf" in matcher) {
425
- for (const item of matcher.allOf) {
426
- if (!matchesAdviceMatcher(frames, normalizedText, item)) {
427
- return false;
428
- }
429
- }
430
- return true;
431
- }
432
- if ("anyOf" in matcher) {
433
- for (const item of matcher.anyOf) {
434
- if (matchesAdviceMatcher(frames, normalizedText, item)) {
435
- return true;
436
- }
437
- }
438
- return false;
439
- }
440
- if ("not" in matcher) {
441
- return !matchesAdviceMatcher(frames, normalizedText, matcher.not);
442
- }
443
- if ("frame" in matcher) {
444
- for (const frame of frames) {
445
- if (frameMatches(frame, matcher.frame)) {
446
- return true;
447
- }
448
- }
449
- return false;
450
- }
451
- if ("argConcept" in matcher) {
452
- for (const frame of frames) {
453
- if (frameHasArgConcept(frame, matcher.argConcept)) {
454
- return true;
455
- }
456
- }
457
- return false;
458
- }
459
- for (const value of matcher.normalizedTexts) {
460
- if (normalizedText === value) {
461
- return true;
462
- }
463
- }
464
- return false;
465
- }
466
- function findRuleByCoding(system, code) {
467
- var _a, _b;
468
- for (const rule of ADDITIONAL_INSTRUCTION_RULES) {
469
- if (((_a = rule.definition.coding) === null || _a === void 0 ? void 0 : _a.system) !== system) {
470
- continue;
471
- }
472
- if (((_b = rule.definition.coding) === null || _b === void 0 ? void 0 : _b.code) !== code) {
473
- continue;
474
- }
475
- return rule;
476
- }
477
- return undefined;
478
- }
479
- function createArgument(role, text, normalized, conceptId) {
480
- return {
481
- role,
482
- text,
483
- normalized,
484
- conceptId
485
- };
486
- }
487
- function createFrame(sourceText, span, force, predicateLemma, predicateSemanticClass, args, sequenceIndex, relation, polarity, modality) {
488
- return {
489
- force,
490
- polarity,
491
- modality,
492
- predicate: {
493
- lemma: predicateLemma,
494
- semanticClass: predicateSemanticClass
495
- },
496
- relation,
497
- args,
498
- span,
499
- sourceText,
500
- sequenceIndex
501
- };
502
- }
503
- function instantiateTemplateFrames(templates, sourceText, span) {
504
- const frames = [];
505
- let index = 0;
506
- for (const template of templates) {
507
- const args = [];
508
- for (const templateArg of template.args) {
509
- args.push(createArgument(templateArg.role, templateArg.text, normalizeAdditionalInstructionKey(templateArg.text), templateArg.conceptId));
510
- }
511
- frames.push(createFrame(sourceText, span, template.force, template.predicate.lemma, template.predicate.semanticClass, args, index, template.relation, template.polarity));
512
- index += 1;
513
- }
514
- return frames;
515
- }
516
- function findNormalizedLexeme(surface, partOfSpeech) {
517
- const key = normalizeAdditionalInstructionKey(surface);
518
- const bucket = LEXEMES_BY_SURFACE[key];
519
- if (!bucket) {
520
- return undefined;
521
- }
522
- for (const entry of bucket) {
523
- if (partOfSpeech && entry.partOfSpeech !== partOfSpeech) {
524
- continue;
525
- }
526
- return entry;
527
- }
528
- return undefined;
529
- }
530
- function findContainedConcept(normalized) {
531
- let best;
532
- let bestLength = 0;
533
- for (const entry of CONCEPT_LIST) {
534
- const key = normalizeAdditionalInstructionKey(entry.surface);
535
- if (!key) {
536
- continue;
537
- }
538
- if (normalized !== key && !normalized.includes(key)) {
539
- continue;
540
- }
541
- if (key.length <= bestLength) {
542
- continue;
543
- }
544
- best = entry;
545
- bestLength = key.length;
546
- }
547
- return best;
548
- }
549
- function findExactConcept(normalized) {
550
- const bucket = CONCEPTS_BY_SURFACE[normalized];
551
- if (!bucket) {
552
- return undefined;
553
- }
554
- for (const entry of bucket) {
555
- return entry;
556
- }
557
- return undefined;
558
- }
559
- function findVerbLexeme(word) {
560
- return findNormalizedLexeme(word, "verb");
561
- }
562
- function findVerbLemma(word) {
563
- var _a;
564
- return (_a = findVerbLexeme(word)) === null || _a === void 0 ? void 0 : _a.lemma;
565
- }
566
- function findModalLexeme(word) {
567
- const entry = findNormalizedLexeme(word, "modifier");
568
- if (!entry || entry.semanticClass !== "modal") {
569
- return undefined;
570
- }
571
- return entry;
572
- }
573
- function mapModalLemmaToModality(lemma) {
574
- switch (lemma) {
575
- case types_1.AdviceModality.May:
576
- return types_1.AdviceModality.May;
577
- case types_1.AdviceModality.Can:
578
- return types_1.AdviceModality.Can;
579
- case types_1.AdviceModality.Might:
580
- return types_1.AdviceModality.Might;
581
- case types_1.AdviceModality.Could:
582
- return types_1.AdviceModality.Could;
583
- case types_1.AdviceModality.Should:
584
- return types_1.AdviceModality.Should;
585
- case types_1.AdviceModality.Must:
586
- return types_1.AdviceModality.Must;
587
- default:
588
- return undefined;
589
- }
590
- }
591
- function containsConceptId(normalized, conceptId) {
592
- const keys = CONCEPT_KEYS_BY_ID[conceptId];
593
- if (!keys) {
594
- return false;
595
- }
596
- for (const key of keys) {
597
- if (normalized === key || normalized.includes(key)) {
598
- return true;
599
- }
600
- }
601
- return false;
602
- }
603
- function containsVerbLemma(words, lemma) {
604
- for (const word of words) {
605
- if (findVerbLemma(word) === lemma) {
606
- return true;
607
- }
608
- }
609
- return false;
610
- }
611
- function containsVerbSequence(words, leadLemma, targetLemma) {
612
- for (let index = 0; index + 1 < words.length; index += 1) {
613
- if (findVerbLemma(words[index]) !== leadLemma) {
614
- continue;
615
- }
616
- if (findVerbLemma(words[index + 1]) === targetLemma) {
617
- return true;
618
- }
619
- }
620
- return false;
621
- }
622
- function consumeNegationPrefix(words, start) {
623
- if (start >= words.length) {
624
- return undefined;
625
- }
626
- const first = words[start];
627
- const second = start + 1 < words.length ? words[start + 1] : undefined;
628
- switch (first) {
629
- case "do":
630
- return second === "not" ? start + 2 : undefined;
631
- case "don":
632
- return second === "t" ? start + 2 : undefined;
633
- case "must":
634
- return second === "not" ? start + 2 : undefined;
635
- case "mustn":
636
- return second === "t" ? start + 2 : undefined;
637
- default:
638
- return NEGATOR_WORDS.has(first) ? start + 1 : undefined;
639
- }
640
- }
641
- function parseLeadingClauseFeatures(words) {
642
- let cursor = skipLeadingNoise(words);
643
- if (cursor >= words.length) {
644
- return undefined;
645
- }
646
- let modality;
647
- const modalLexeme = findModalLexeme(words[cursor]);
648
- if (modalLexeme) {
649
- modality = mapModalLemmaToModality(modalLexeme.lemma);
650
- cursor += 1;
651
- }
652
- if (cursor >= words.length) {
653
- return { cursor, modality };
654
- }
655
- const negationEnd = consumeNegationPrefix(words, cursor);
656
- if (negationEnd === undefined) {
657
- return {
658
- cursor,
659
- modality
660
- };
661
- }
662
- switch (words[cursor]) {
663
- case "mustn":
664
- modality = types_1.AdviceModality.Must;
665
- break;
666
- default:
667
- break;
668
- }
669
- return {
670
- cursor: negationEnd,
671
- modality,
672
- polarity: types_1.AdvicePolarity.Negate
673
- };
674
- }
675
- function deriveClauseForce(sequenceCount, context, predicateLemma, predicateSemanticClass, polarity, modality) {
676
- var _a;
677
- if (sequenceCount > 1) {
678
- return types_1.AdviceForce.Sequence;
679
- }
680
- switch (predicateSemanticClass) {
681
- case "effect":
682
- return types_1.AdviceForce.Warning;
683
- default:
684
- break;
685
- }
686
- switch (modality) {
687
- case types_1.AdviceModality.May:
688
- case types_1.AdviceModality.Can:
689
- case types_1.AdviceModality.Might:
690
- case types_1.AdviceModality.Could:
691
- return types_1.AdviceForce.Warning;
692
- case types_1.AdviceModality.Should:
693
- return types_1.AdviceForce.Caution;
694
- default:
695
- break;
696
- }
697
- switch (predicateLemma) {
698
- case "avoid":
699
- return types_1.AdviceForce.Warning;
700
- default:
701
- break;
702
- }
703
- switch (polarity) {
704
- case types_1.AdvicePolarity.Negate:
705
- return types_1.AdviceForce.Warning;
706
- default:
707
- break;
708
- }
709
- return (_a = context.defaultForce) !== null && _a !== void 0 ? _a : types_1.AdviceForce.Instruction;
710
- }
711
- function containsNegatedVerb(words, lemma) {
712
- for (let index = 0; index < words.length; index += 1) {
713
- const nextIndex = consumeNegationPrefix(words, index);
714
- if (nextIndex !== undefined && nextIndex < words.length && findVerbLemma(words[nextIndex]) === lemma) {
715
- return true;
716
- }
717
- }
718
- return false;
719
- }
720
- function mapSemanticClassToRole(semanticClass) {
721
- switch (semanticClass) {
722
- case "meal_state":
723
- return types_1.AdviceArgumentRole.MealState;
724
- case "activity":
725
- return types_1.AdviceArgumentRole.Activity;
726
- case "material":
727
- return types_1.AdviceArgumentRole.Material;
728
- case "site":
729
- return types_1.AdviceArgumentRole.Site;
730
- case "amount_style":
731
- return types_1.AdviceArgumentRole.Amount;
732
- case "manner_style":
733
- return types_1.AdviceArgumentRole.Free;
734
- case "duration":
735
- return types_1.AdviceArgumentRole.Duration;
736
- case "time":
737
- return types_1.AdviceArgumentRole.Time;
738
- case "substance":
739
- return types_1.AdviceArgumentRole.Substance;
740
- default:
741
- return types_1.AdviceArgumentRole.Object;
742
- }
743
- }
744
- function classifyArgument(text) {
745
- const cleaned = cleanFreeText(text);
746
- const normalized = normalizeAdditionalInstructionKey(cleaned);
747
- if (!normalized) {
748
- return createArgument(types_1.AdviceArgumentRole.Free, cleaned, normalized);
749
- }
750
- const concept = findContainedConcept(normalized);
751
- if (concept) {
752
- return createArgument(mapSemanticClassToRole(concept.semanticClass), cleaned, normalized, concept.conceptId);
753
- }
754
- const parts = normalized.split(" ");
755
- if (parts.length >= 2) {
756
- const first = parts[0];
757
- const second = parts[1];
758
- if (/^[0-9]+(?:\.[0-9]+)?$/.test(first) && DURATION_UNIT_WORDS.has(second)) {
759
- return createArgument(types_1.AdviceArgumentRole.Duration, cleaned, normalized);
760
- }
761
- }
762
- if (SIMPLE_TIME_WORDS.has(normalized)) {
763
- return createArgument(types_1.AdviceArgumentRole.Time, cleaned, normalized, normalized);
764
- }
765
- return createArgument(types_1.AdviceArgumentRole.Object, cleaned, normalized);
766
- }
767
- function trimSegment(text, start, end) {
768
- while (start < end) {
769
- const char = text[start];
770
- if (/\s/.test(char) || char === "," || char === ";" || char === ":" || char === "-" || char === ".") {
771
- start += 1;
772
- continue;
773
- }
774
- break;
775
- }
776
- while (end > start) {
777
- const char = text[end - 1];
778
- if (/\s/.test(char) || char === "," || char === ";" || char === ":" || char === "-" || char === ".") {
779
- end -= 1;
780
- continue;
781
- }
782
- break;
783
- }
784
- if (end <= start) {
785
- return undefined;
786
- }
787
- return {
788
- text: text.slice(start, end),
789
- range: { start, end }
790
- };
791
- }
792
- function splitInstructionSegments(sourceText, baseRange) {
793
- const segments = [];
794
- let segmentStart = 0;
795
- for (let index = 0; index < sourceText.length; index++) {
796
- const char = sourceText[index];
797
- if (char !== ";" && char !== "." && char !== "\n" && char !== "\r") {
798
- continue;
799
- }
800
- if (char === ".") {
801
- const previous = index > 0 ? sourceText[index - 1] : "";
802
- const next = index + 1 < sourceText.length ? sourceText[index + 1] : "";
803
- if (/\d/.test(previous) && /\d/.test(next)) {
804
- continue;
805
- }
806
- }
807
- const trimmed = trimSegment(sourceText, segmentStart, index);
808
- if (trimmed) {
809
- segments.push({
810
- text: trimmed.text,
811
- range: {
812
- start: baseRange.start + trimmed.range.start,
813
- end: baseRange.start + trimmed.range.end
814
- }
815
- });
816
- }
817
- segmentStart = index + 1;
818
- }
819
- const finalTrimmed = trimSegment(sourceText, segmentStart, sourceText.length);
820
- if (finalTrimmed) {
821
- segments.push({
822
- text: finalTrimmed.text,
823
- range: {
824
- start: baseRange.start + finalTrimmed.range.start,
825
- end: baseRange.start + finalTrimmed.range.end
826
- }
827
- });
828
- }
829
- if (segments.length) {
830
- return segments;
831
- }
832
- const single = trimSegment(sourceText, 0, sourceText.length);
833
- if (!single) {
834
- return [];
835
- }
836
- return [
837
- {
838
- text: single.text,
839
- range: {
840
- start: baseRange.start + single.range.start,
841
- end: baseRange.start + single.range.end
842
- }
843
- }
844
- ];
845
- }
846
- function splitSequenceSegments(sourceText, baseRange) {
847
- const tokens = (0, lex_1.lexInput)(sourceText);
848
- if (!tokens.length) {
849
- return [];
850
- }
851
- const segments = [];
852
- let segmentStart = 0;
853
- for (const token of tokens) {
854
- if (normalizeAdditionalInstructionKey(token.original) !== "then") {
855
- continue;
856
- }
857
- const trimmed = trimSegment(sourceText, segmentStart, token.sourceStart);
858
- if (trimmed) {
859
- segments.push({
860
- text: trimmed.text,
861
- range: {
862
- start: baseRange.start + trimmed.range.start,
863
- end: baseRange.start + trimmed.range.end
864
- }
865
- });
866
- }
867
- segmentStart = token.sourceEnd;
868
- }
869
- const finalTrimmed = trimSegment(sourceText, segmentStart, sourceText.length);
870
- if (finalTrimmed) {
871
- segments.push({
872
- text: finalTrimmed.text,
873
- range: {
874
- start: baseRange.start + finalTrimmed.range.start,
875
- end: baseRange.start + finalTrimmed.range.end
876
- }
877
- });
878
- }
879
- if (segments.length > 1) {
880
- return segments;
881
- }
882
- return [
883
- {
884
- text: sourceText,
885
- range: baseRange
886
- }
887
- ];
888
- }
889
- function isKnownVerb(word) {
890
- const entry = findNormalizedLexeme(word, "verb");
891
- return Boolean(entry);
892
- }
893
- function isAdministrationWord(word) {
894
- return ADMINISTRATION_PREDICATES.has(word);
895
- }
896
- function isRelationWord(word) {
897
- const entry = findNormalizedLexeme(word, "relation");
898
- if (!entry) {
899
- return undefined;
900
- }
901
- switch (entry.lemma) {
902
- case "with":
903
- return types_1.AdviceRelation.With;
904
- case "without":
905
- return types_1.AdviceRelation.Without;
906
- case "before":
907
- return types_1.AdviceRelation.Before;
908
- case "after":
909
- return types_1.AdviceRelation.After;
910
- case "during":
911
- return types_1.AdviceRelation.During;
912
- case "then":
913
- return types_1.AdviceRelation.Then;
914
- case "until":
915
- return types_1.AdviceRelation.Until;
916
- case "for":
917
- return types_1.AdviceRelation.For;
918
- case "in":
919
- return types_1.AdviceRelation.In;
920
- case "on":
921
- return types_1.AdviceRelation.On;
922
- default:
923
- return undefined;
924
- }
925
- }
926
- function parseAdviceRelation(value) {
927
- switch (value) {
928
- case types_1.AdviceRelation.With:
929
- return types_1.AdviceRelation.With;
930
- case types_1.AdviceRelation.Without:
931
- return types_1.AdviceRelation.Without;
932
- case types_1.AdviceRelation.Before:
933
- return types_1.AdviceRelation.Before;
934
- case types_1.AdviceRelation.After:
935
- return types_1.AdviceRelation.After;
936
- case types_1.AdviceRelation.During:
937
- return types_1.AdviceRelation.During;
938
- case types_1.AdviceRelation.Then:
939
- return types_1.AdviceRelation.Then;
940
- case types_1.AdviceRelation.Until:
941
- return types_1.AdviceRelation.Until;
942
- case types_1.AdviceRelation.For:
943
- return types_1.AdviceRelation.For;
944
- case types_1.AdviceRelation.In:
945
- return types_1.AdviceRelation.In;
946
- case types_1.AdviceRelation.On:
947
- return types_1.AdviceRelation.On;
948
- default:
949
- return undefined;
950
- }
951
- }
952
- function normalizeWords(text) {
953
- const normalized = normalizeAdditionalInstructionKey(text);
954
- if (!normalized) {
955
- return [];
956
- }
957
- return normalized.split(" ");
958
- }
959
- function skipLeadingNoise(words) {
960
- let cursor = 0;
961
- while (cursor < words.length && LEADING_NOISE_WORDS.has(words[cursor])) {
962
- cursor += 1;
963
- }
964
- if (cursor + 1 < words.length &&
965
- isAdministrationWord(words[cursor]) &&
966
- isRelationWord(words[cursor + 1])) {
967
- cursor += 1;
968
- }
969
- if (cursor + 2 < words.length &&
970
- /^[0-9]+(?:\.[0-9]+)?$/.test(words[cursor]) &&
971
- DURATION_UNIT_WORDS.has(words[cursor + 1]) &&
972
- isRelationWord(words[cursor + 2])) {
973
- cursor += 2;
974
- }
975
- return cursor;
976
- }
977
- function createDefaultForce(sequenceCount, sequenceIndex, context) {
978
- var _a;
979
- if (sequenceCount > 1 || sequenceIndex > 0) {
980
- return types_1.AdviceForce.Sequence;
981
- }
982
- return (_a = context.defaultForce) !== null && _a !== void 0 ? _a : types_1.AdviceForce.Instruction;
983
- }
984
- function tryParseRelationInstruction(sourceText, span, context, sequenceIndex, sequenceCount) {
985
- const words = normalizeWords(sourceText);
986
- if (!words.length) {
987
- return undefined;
988
- }
989
- let cursor = skipLeadingNoise(words);
990
- const relation = cursor < words.length ? isRelationWord(words[cursor]) : undefined;
991
- if (!relation) {
992
- return undefined;
993
- }
994
- cursor += 1;
995
- if (cursor >= words.length) {
996
- return undefined;
997
- }
998
- const objectText = words.slice(cursor).join(" ");
999
- if (!objectText) {
1000
- return undefined;
1001
- }
1002
- const force = createDefaultForce(sequenceCount, sequenceIndex, context);
1003
- const args = [classifyArgument(objectText)];
1004
- return [
1005
- createFrame(sourceText, span, force, context.defaultPredicate, "administration", args, sequenceIndex, relation)
1006
- ];
1007
- }
1008
- function tryParseImplicitConceptInstruction(sourceText, span, context, sequenceIndex, sequenceCount) {
1009
- const words = normalizeWords(sourceText);
1010
- if (!words.length) {
1011
- return undefined;
1012
- }
1013
- const cursor = skipLeadingNoise(words);
1014
- if (cursor >= words.length) {
1015
- return undefined;
1016
- }
1017
- if (isRelationWord(words[cursor]) || isKnownVerb(words[cursor])) {
1018
- return undefined;
1019
- }
1020
- const conceptText = words.slice(cursor).join(" ");
1021
- if (!conceptText) {
1022
- return undefined;
1023
- }
1024
- const concept = findExactConcept(conceptText);
1025
- if (!concept) {
1026
- return undefined;
1027
- }
1028
- const relation = parseAdviceRelation(concept.implicitRelation);
1029
- if (!relation) {
1030
- return undefined;
1031
- }
1032
- return [
1033
- createFrame(sourceText, span, createDefaultForce(sequenceCount, sequenceIndex, context), context.defaultPredicate, "administration", [
1034
- createArgument(mapSemanticClassToRole(concept.semanticClass), conceptText, conceptText, concept.conceptId)
1035
- ], sequenceIndex, relation)
1036
- ];
1037
- }
1038
- function parseEmbeddedAvoidanceFrames(words, normalized, sourceText, span, sequenceIndex, sequenceCount) {
1039
- const frames = [];
1040
- const force = sequenceCount > 1 ? types_1.AdviceForce.Sequence : types_1.AdviceForce.Warning;
1041
- if (containsConceptId(normalized, "alcohol") &&
1042
- (containsVerbLemma(words, "avoid") ||
1043
- containsNegatedVerb(words, "drink") ||
1044
- (words.length >= 2 && words[0] === "no"))) {
1045
- frames.push(createFrame(sourceText, span, force, "avoid", "avoidance", [createArgument(types_1.AdviceArgumentRole.Substance, "alcohol", "alcohol", "alcohol")], sequenceIndex));
1046
- }
1047
- if (containsVerbSequence(words, "avoid", "drive") || containsNegatedVerb(words, "drive")) {
1048
- frames.push(createFrame(sourceText, span, force, "drive", "activity", [], sequenceIndex, undefined, types_1.AdvicePolarity.Negate));
1049
- }
1050
- return frames;
1051
- }
1052
- function tryParseNoObjectInstruction(sourceText, span, sequenceIndex, sequenceCount) {
1053
- const words = normalizeWords(sourceText);
1054
- if (words.length < 2) {
1055
- return undefined;
1056
- }
1057
- const cursor = skipLeadingNoise(words);
1058
- if (cursor >= words.length || words[cursor] !== "no") {
1059
- return undefined;
1060
- }
1061
- const objectText = words.slice(cursor + 1).join(" ");
1062
- const argument = classifyArgument(objectText);
1063
- if (argument.role === types_1.AdviceArgumentRole.Substance) {
1064
- return [
1065
- createFrame(sourceText, span, sequenceCount > 1 ? types_1.AdviceForce.Sequence : types_1.AdviceForce.Warning, "drink", "ingest", [argument], sequenceIndex, undefined, types_1.AdvicePolarity.Negate)
1066
- ];
1067
- }
1068
- const objectWords = normalizeWords(objectText);
1069
- if (objectWords.length === 1) {
1070
- const verbLexeme = findVerbLexeme(objectWords[0]);
1071
- if (verbLexeme) {
1072
- return [
1073
- createFrame(sourceText, span, sequenceCount > 1 ? types_1.AdviceForce.Sequence : types_1.AdviceForce.Warning, verbLexeme.lemma, verbLexeme.semanticClass, [], sequenceIndex, undefined, types_1.AdvicePolarity.Negate)
1074
- ];
1075
- }
1076
- }
1077
- return undefined;
1078
- }
1079
- function tryParseStyleInstruction(sourceText, span, context, sequenceIndex, sequenceCount) {
1080
- const normalized = normalizeAdditionalInstructionKey(sourceText);
1081
- if (!normalized) {
1082
- return undefined;
1083
- }
1084
- let styleText = normalized;
1085
- if (normalized.startsWith("apply ")) {
1086
- styleText = normalized.slice("apply ".length);
1087
- }
1088
- const lexeme = findNormalizedLexeme(styleText);
1089
- if (!lexeme ||
1090
- (lexeme.semanticClass !== "amount_style" && lexeme.semanticClass !== "manner_style")) {
1091
- return undefined;
1092
- }
1093
- const concept = findContainedConcept(styleText);
1094
- return [
1095
- createFrame(sourceText, span, createDefaultForce(sequenceCount, sequenceIndex, context), context.defaultPredicate, "administration", [
1096
- createArgument(mapSemanticClassToRole(lexeme.semanticClass), styleText, styleText, concept === null || concept === void 0 ? void 0 : concept.conceptId)
1097
- ], sequenceIndex)
1098
- ];
1099
- }
1100
- function tryParseClauseInstruction(sourceText, span, context, sequenceIndex, sequenceCount) {
1101
- const words = normalizeWords(sourceText);
1102
- if (!words.length) {
1103
- return undefined;
1104
- }
1105
- const prefix = parseLeadingClauseFeatures(words);
1106
- if (!prefix || prefix.cursor >= words.length) {
1107
- return undefined;
1108
- }
1109
- const verbEntries = [];
1110
- let remainderStart = prefix.cursor;
1111
- while (remainderStart < words.length) {
1112
- const verbEntry = findVerbLexeme(words[remainderStart]);
1113
- if (!verbEntry) {
1114
- break;
1115
- }
1116
- verbEntries.push(verbEntry);
1117
- remainderStart += 1;
1118
- if (remainderStart < words.length &&
1119
- VERB_CONNECTOR_WORDS.has(words[remainderStart]) &&
1120
- remainderStart + 1 < words.length &&
1121
- isKnownVerb(words[remainderStart + 1])) {
1122
- remainderStart += 1;
1123
- continue;
1124
- }
1125
- break;
1126
- }
1127
- if (!verbEntries.length) {
1128
- return undefined;
1129
- }
1130
- let relation;
1131
- const args = [];
1132
- const remainderWords = words.slice(remainderStart);
1133
- const primaryVerb = verbEntries[0];
1134
- switch (primaryVerb.lemma) {
1135
- case "leave":
1136
- if (remainderWords[0] === "on") {
1137
- args.push(createArgument(types_1.AdviceArgumentRole.Theme, "on", "on"));
1138
- if (remainderWords.length > 1) {
1139
- const nextRelation = isRelationWord(remainderWords[1]);
1140
- if (nextRelation) {
1141
- relation = nextRelation;
1142
- const afterRelation = remainderWords.slice(2).join(" ");
1143
- if (afterRelation) {
1144
- args.push(classifyArgument(afterRelation));
1145
- }
1146
- }
1147
- else {
1148
- const tail = remainderWords.slice(1).join(" ");
1149
- if (tail) {
1150
- args.push(classifyArgument(tail));
1151
- }
1152
- }
1153
- }
1154
- break;
1155
- }
1156
- relation = remainderWords.length ? isRelationWord(remainderWords[0]) : undefined;
1157
- {
1158
- const objectText = remainderWords.slice(relation ? 1 : 0).join(" ");
1159
- if (objectText) {
1160
- args.push(classifyArgument(objectText));
1161
- }
1162
- }
1163
- break;
1164
- default:
1165
- relation = remainderWords.length ? isRelationWord(remainderWords[0]) : undefined;
1166
- {
1167
- const objectText = remainderWords.slice(relation ? 1 : 0).join(" ");
1168
- if (objectText) {
1169
- args.push(classifyArgument(objectText));
1170
- }
1171
- }
1172
- break;
1173
- }
1174
- if (!args.length &&
1175
- !relation &&
1176
- ADMINISTRATION_PREDICATES.has(primaryVerb.lemma)) {
1177
- return undefined;
1178
- }
1179
- const frames = [];
1180
- for (const verbEntry of verbEntries) {
1181
- frames.push(createFrame(sourceText, span, deriveClauseForce(sequenceCount, context, verbEntry.lemma, verbEntry.semanticClass, prefix.polarity, prefix.modality), verbEntry.lemma, verbEntry.semanticClass, args, sequenceIndex, relation, prefix.polarity, prefix.modality));
1182
- }
1183
- if (frames.length === 1 &&
1184
- frames[0].predicate.lemma === "cause" &&
1185
- frames[0].args.length === 1 &&
1186
- frames[0].args[0].conceptId === "drowsiness") {
1187
- const embedded = parseEmbeddedAvoidanceFrames(words, words.join(" "), sourceText, span, sequenceIndex, sequenceCount);
1188
- if (embedded.length) {
1189
- for (const frame of embedded) {
1190
- frames.push(frame);
1191
- }
1192
- }
1193
- }
1194
- return frames;
1195
- }
1196
- function parseSequenceFrames(sourceText, span, context) {
1197
- var _a, _b, _c, _d;
1198
- const sequenceSegments = splitSequenceSegments(sourceText, span);
1199
- if (!sequenceSegments.length) {
1200
- return [];
1201
- }
1202
- const frames = [];
1203
- for (let index = 0; index < sequenceSegments.length; index++) {
1204
- const segment = sequenceSegments[index];
1205
- const parsed = (_d = (_c = (_b = (_a = tryParseRelationInstruction(segment.text, segment.range, context, index, sequenceSegments.length)) !== null && _a !== void 0 ? _a : tryParseImplicitConceptInstruction(segment.text, segment.range, context, index, sequenceSegments.length)) !== null && _b !== void 0 ? _b : tryParseStyleInstruction(segment.text, segment.range, context, index, sequenceSegments.length)) !== null && _c !== void 0 ? _c : tryParseNoObjectInstruction(segment.text, segment.range, index, sequenceSegments.length)) !== null && _d !== void 0 ? _d : tryParseClauseInstruction(segment.text, segment.range, context, index, sequenceSegments.length);
1206
- if (!parsed) {
1207
- return [];
1208
- }
1209
- for (const frame of parsed) {
1210
- frames.push(frame);
1211
- }
1212
- }
1213
- return frames;
1214
- }
1215
- function matchAdviceCodingRule(frames, normalizedText) {
1216
- for (const rule of ADDITIONAL_INSTRUCTION_RULES) {
1217
- if (matchesAdviceMatcher(frames, normalizedText, rule.matcher)) {
1218
- return rule;
1219
- }
1220
- }
1221
- return undefined;
1222
- }
1223
- function cloneDefinitionCoding(coding, i18n) {
1224
- if (!(coding === null || coding === void 0 ? void 0 : coding.code) && !(coding === null || coding === void 0 ? void 0 : coding.display) && !(coding === null || coding === void 0 ? void 0 : coding.system)) {
1225
- return undefined;
1226
- }
1227
- return {
1228
- code: coding.code,
1229
- display: coding.display,
1230
- system: coding.system,
1231
- i18n
1232
- };
1233
- }
1234
- function shouldAllowFallbackText(sourceText, allowFreeTextFallback) {
1235
- return Boolean(allowFreeTextFallback && cleanFreeText(sourceText));
1236
- }
1237
- function capitalizeSentence(value) {
1238
- if (!value) {
1239
- return value;
1240
- }
1241
- return value.charAt(0).toUpperCase() + value.slice(1);
1242
- }
1243
- function realizeAdviceModality(modality) {
1244
- switch (modality) {
1245
- case types_1.AdviceModality.May:
1246
- return "May";
1247
- case types_1.AdviceModality.Can:
1248
- return "Can";
1249
- case types_1.AdviceModality.Might:
1250
- return "Might";
1251
- case types_1.AdviceModality.Could:
1252
- return "Could";
1253
- case types_1.AdviceModality.Should:
1254
- return "Should";
1255
- case types_1.AdviceModality.Must:
1256
- return "Must";
1257
- default:
1258
- return undefined;
1259
- }
1260
- }
1261
- function joinAdviceArgumentTexts(args) {
1262
- let text = "";
1263
- let added = 0;
1264
- for (const arg of args) {
1265
- const trimmed = cleanFreeText(arg.text);
1266
- if (!trimmed) {
1267
- continue;
1268
- }
1269
- if (added > 0) {
1270
- text += added === 1 ? " and " : ", ";
1271
- }
1272
- text += trimmed;
1273
- added += 1;
1274
- }
1275
- return text || undefined;
1276
- }
1277
- function realizeSingleAdviceFrame(frame) {
1278
- const argText = joinAdviceArgumentTexts(frame.args);
1279
- const modalityText = realizeAdviceModality(frame.modality);
1280
- switch (frame.polarity) {
1281
- case types_1.AdvicePolarity.Negate: {
1282
- let text = `${modalityText === "Must" ? "Must not" : "Do not"} ${frame.predicate.lemma}`;
1283
- if (frame.relation) {
1284
- text += ` ${frame.relation}`;
1285
- }
1286
- if (argText) {
1287
- text += ` ${argText}`;
1288
- }
1289
- return text;
1290
- }
1291
- default:
1292
- break;
1293
- }
1294
- switch (frame.predicate.lemma) {
1295
- case "avoid":
1296
- if (!modalityText) {
1297
- return argText ? `Avoid ${argText}` : "Avoid";
1298
- }
1299
- return argText ? `${modalityText} avoid ${argText}` : `${modalityText} avoid`;
1300
- case "cause":
1301
- if (!modalityText) {
1302
- return argText ? "May cause " + argText : "May cause";
1303
- }
1304
- return argText ? `${modalityText} cause ${argText}` : `${modalityText} cause`;
1305
- default: {
1306
- let text = modalityText ? `${modalityText} ${frame.predicate.lemma}` : capitalizeSentence(frame.predicate.lemma);
1307
- if (frame.relation) {
1308
- text += ` ${frame.relation}`;
1309
- }
1310
- if (argText) {
1311
- text += ` ${argText}`;
1312
- }
1313
- return text;
1314
- }
1315
- }
1316
- }
1317
- function realizeAdviceFramesText(frames) {
1318
- if (frames.length !== 1) {
1319
- return undefined;
1320
- }
1321
- const realized = realizeSingleAdviceFrame(frames[0]);
1322
- return realized ? capitalizeSentence(realized) : undefined;
1323
- }
1324
- function parseAdditionalInstructions(sourceText, span, context) {
1325
- var _a, _b, _c, _d, _e;
1326
- const effectiveContext = {
1327
- defaultPredicate: (_a = context === null || context === void 0 ? void 0 : context.defaultPredicate) !== null && _a !== void 0 ? _a : DEFAULT_INSTRUCTION_CONTEXT.defaultPredicate,
1328
- defaultForce: (_b = context === null || context === void 0 ? void 0 : context.defaultForce) !== null && _b !== void 0 ? _b : DEFAULT_INSTRUCTION_CONTEXT.defaultForce,
1329
- allowFreeTextFallback: (_c = context === null || context === void 0 ? void 0 : context.allowFreeTextFallback) !== null && _c !== void 0 ? _c : DEFAULT_INSTRUCTION_CONTEXT.allowFreeTextFallback
1330
- };
1331
- const instructions = [];
1332
- const segments = splitInstructionSegments(sourceText, span);
1333
- for (const segment of segments) {
1334
- const cleanedText = cleanFreeText(segment.text);
1335
- if (!cleanedText) {
1336
- continue;
1337
- }
1338
- const normalizedText = normalizeAdditionalInstructionKey(cleanedText);
1339
- const frames = parseSequenceFrames(cleanedText, segment.range, effectiveContext);
1340
- const rule = normalizedText
1341
- ? matchAdviceCodingRule(frames, normalizedText)
1342
- : undefined;
1343
- if (frames.length || rule) {
1344
- const realizedText = rule ? undefined : realizeAdviceFramesText(frames);
1345
- instructions.push({
1346
- text: (_e = (_d = rule === null || rule === void 0 ? void 0 : rule.definition.text) !== null && _d !== void 0 ? _d : realizedText) !== null && _e !== void 0 ? _e : cleanedText,
1347
- coding: cloneDefinitionCoding(rule === null || rule === void 0 ? void 0 : rule.definition.coding, rule === null || rule === void 0 ? void 0 : rule.definition.i18n),
1348
- frames
1349
- });
1350
- continue;
1351
- }
1352
- if (!shouldAllowFallbackText(cleanedText, effectiveContext.allowFreeTextFallback)) {
1353
- continue;
1354
- }
1355
- instructions.push({
1356
- text: cleanedText,
1357
- frames: []
1358
- });
1359
- }
1360
- return instructions;
1361
- }
1362
- function findAdditionalInstructionDefinitionByCoding(system, code) {
1363
- var _a;
1364
- return (_a = findRuleByCoding(system, code)) === null || _a === void 0 ? void 0 : _a.definition;
1365
- }
1366
- function buildAdditionalInstructionFramesFromCoding(system, code, sourceText, span) {
1367
- var _a, _b, _c;
1368
- const rule = findRuleByCoding(system, code);
1369
- if (!rule) {
1370
- return undefined;
1371
- }
1372
- const resolvedText = (_c = (_a = sourceText !== null && sourceText !== void 0 ? sourceText : rule.definition.text) !== null && _a !== void 0 ? _a : (_b = rule.definition.coding) === null || _b === void 0 ? void 0 : _b.display) !== null && _c !== void 0 ? _c : "";
1373
- const resolvedSpan = span !== null && span !== void 0 ? span : { start: 0, end: resolvedText.length };
1374
- return instantiateTemplateFrames(rule.frames, resolvedText, resolvedSpan);
1375
- }