ezmedicationinput 0.1.14 → 0.1.15
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/parser.js +142 -0
- package/package.json +1 -1
package/dist/parser.js
CHANGED
|
@@ -186,6 +186,33 @@ const COUNT_CONNECTOR_WORDS = new Set([
|
|
|
186
186
|
"additional",
|
|
187
187
|
"extra"
|
|
188
188
|
]);
|
|
189
|
+
const FREQUENCY_SIMPLE_WORDS = {
|
|
190
|
+
once: 1,
|
|
191
|
+
twice: 2,
|
|
192
|
+
thrice: 3
|
|
193
|
+
};
|
|
194
|
+
const FREQUENCY_NUMBER_WORDS = {
|
|
195
|
+
one: 1,
|
|
196
|
+
two: 2,
|
|
197
|
+
three: 3,
|
|
198
|
+
four: 4,
|
|
199
|
+
five: 5,
|
|
200
|
+
six: 6,
|
|
201
|
+
seven: 7,
|
|
202
|
+
eight: 8,
|
|
203
|
+
nine: 9,
|
|
204
|
+
ten: 10,
|
|
205
|
+
eleven: 11,
|
|
206
|
+
twelve: 12
|
|
207
|
+
};
|
|
208
|
+
const FREQUENCY_TIMES_WORDS = new Set(["time", "times", "x"]);
|
|
209
|
+
const FREQUENCY_CONNECTOR_WORDS = new Set(["per", "a", "an", "each", "every"]);
|
|
210
|
+
const FREQUENCY_ADVERB_UNITS = {
|
|
211
|
+
daily: types_1.FhirPeriodUnit.Day,
|
|
212
|
+
weekly: types_1.FhirPeriodUnit.Week,
|
|
213
|
+
monthly: types_1.FhirPeriodUnit.Month,
|
|
214
|
+
hourly: types_1.FhirPeriodUnit.Hour
|
|
215
|
+
};
|
|
189
216
|
const ROUTE_DESCRIPTOR_FILLER_WORDS = new Set([
|
|
190
217
|
"per",
|
|
191
218
|
"by",
|
|
@@ -580,6 +607,115 @@ function tryParseNumericCadence(internal, tokens, index) {
|
|
|
580
607
|
mark(internal.consumed, unitToken);
|
|
581
608
|
return true;
|
|
582
609
|
}
|
|
610
|
+
function tryParseCountBasedFrequency(internal, tokens, index, options) {
|
|
611
|
+
const token = tokens[index];
|
|
612
|
+
if (internal.consumed.has(token.index)) {
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
615
|
+
if (internal.frequency !== undefined ||
|
|
616
|
+
internal.frequencyMax !== undefined ||
|
|
617
|
+
internal.period !== undefined ||
|
|
618
|
+
internal.periodMax !== undefined) {
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
const normalized = normalizeTokenLower(token);
|
|
622
|
+
let value;
|
|
623
|
+
let requiresPeriod = true;
|
|
624
|
+
let requiresCue = true;
|
|
625
|
+
if (/^[0-9]+(?:\.[0-9]+)?$/.test(normalized)) {
|
|
626
|
+
value = parseFloat(token.original);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
const simple = FREQUENCY_SIMPLE_WORDS[normalized];
|
|
630
|
+
if (simple !== undefined) {
|
|
631
|
+
value = simple;
|
|
632
|
+
requiresPeriod = false;
|
|
633
|
+
requiresCue = false;
|
|
634
|
+
}
|
|
635
|
+
else {
|
|
636
|
+
const wordValue = FREQUENCY_NUMBER_WORDS[normalized];
|
|
637
|
+
if (wordValue === undefined) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
value = wordValue;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (!Number.isFinite(value) || value === undefined || value <= 0) {
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
const nextToken = tokens[index + 1];
|
|
647
|
+
if (nextToken &&
|
|
648
|
+
!internal.consumed.has(nextToken.index) &&
|
|
649
|
+
normalizeUnit(normalizeTokenLower(nextToken), options)) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
const partsToConsume = [];
|
|
653
|
+
let nextIndex = index + 1;
|
|
654
|
+
let periodUnit;
|
|
655
|
+
let sawCue = !requiresCue;
|
|
656
|
+
let sawTimesWord = false;
|
|
657
|
+
let sawConnectorWord = false;
|
|
658
|
+
while (true) {
|
|
659
|
+
const candidate = tokens[nextIndex];
|
|
660
|
+
if (!candidate || internal.consumed.has(candidate.index)) {
|
|
661
|
+
break;
|
|
662
|
+
}
|
|
663
|
+
const lower = normalizeTokenLower(candidate);
|
|
664
|
+
if (FREQUENCY_TIMES_WORDS.has(lower)) {
|
|
665
|
+
partsToConsume.push(candidate);
|
|
666
|
+
sawCue = true;
|
|
667
|
+
sawTimesWord = true;
|
|
668
|
+
nextIndex += 1;
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
if (FREQUENCY_CONNECTOR_WORDS.has(lower)) {
|
|
672
|
+
partsToConsume.push(candidate);
|
|
673
|
+
sawCue = true;
|
|
674
|
+
sawConnectorWord = true;
|
|
675
|
+
nextIndex += 1;
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
const adverbUnit = mapFrequencyAdverb(lower);
|
|
679
|
+
if (adverbUnit) {
|
|
680
|
+
periodUnit = adverbUnit;
|
|
681
|
+
partsToConsume.push(candidate);
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
const mappedUnit = mapIntervalUnit(lower);
|
|
685
|
+
if (mappedUnit) {
|
|
686
|
+
periodUnit = mappedUnit;
|
|
687
|
+
partsToConsume.push(candidate);
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
if (!periodUnit) {
|
|
693
|
+
if (requiresPeriod) {
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
periodUnit = types_1.FhirPeriodUnit.Day;
|
|
697
|
+
}
|
|
698
|
+
if (requiresCue && !sawCue) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
internal.frequency = value;
|
|
702
|
+
internal.period = 1;
|
|
703
|
+
internal.periodUnit = periodUnit;
|
|
704
|
+
if (value === 1 && periodUnit === types_1.FhirPeriodUnit.Day && !internal.timingCode) {
|
|
705
|
+
internal.timingCode = "QD";
|
|
706
|
+
}
|
|
707
|
+
let consumeCurrentToken = true;
|
|
708
|
+
if (value === 1 && !sawConnectorWord && sawTimesWord && periodUnit !== types_1.FhirPeriodUnit.Day) {
|
|
709
|
+
consumeCurrentToken = false;
|
|
710
|
+
}
|
|
711
|
+
if (consumeCurrentToken) {
|
|
712
|
+
mark(internal.consumed, token);
|
|
713
|
+
}
|
|
714
|
+
for (const part of partsToConsume) {
|
|
715
|
+
mark(internal.consumed, part);
|
|
716
|
+
}
|
|
717
|
+
return consumeCurrentToken;
|
|
718
|
+
}
|
|
583
719
|
const SITE_UNIT_ROUTE_HINTS = [
|
|
584
720
|
{ pattern: /\beye(s)?\b/i, route: types_1.RouteCode["Ophthalmic route"] },
|
|
585
721
|
{ pattern: /\beyelid(s)?\b/i, route: types_1.RouteCode["Ophthalmic route"] },
|
|
@@ -1244,6 +1380,9 @@ function mapIntervalUnit(token) {
|
|
|
1244
1380
|
}
|
|
1245
1381
|
return undefined;
|
|
1246
1382
|
}
|
|
1383
|
+
function mapFrequencyAdverb(token) {
|
|
1384
|
+
return FREQUENCY_ADVERB_UNITS[token];
|
|
1385
|
+
}
|
|
1247
1386
|
function parseNumericRange(token) {
|
|
1248
1387
|
const rangeMatch = token.match(/^([0-9]+(?:\.[0-9]+)?)-([0-9]+(?:\.[0-9]+)?)$/);
|
|
1249
1388
|
if (!rangeMatch) {
|
|
@@ -1620,6 +1759,9 @@ function parseInternal(input, options) {
|
|
|
1620
1759
|
}
|
|
1621
1760
|
}
|
|
1622
1761
|
// Numeric dose
|
|
1762
|
+
if (tryParseCountBasedFrequency(internal, tokens, i, options)) {
|
|
1763
|
+
continue;
|
|
1764
|
+
}
|
|
1623
1765
|
const rangeValue = parseNumericRange(token.lower);
|
|
1624
1766
|
if (rangeValue) {
|
|
1625
1767
|
if (!internal.doseRange) {
|