ezmedicationinput 0.1.43 → 0.1.44

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.
Files changed (46) hide show
  1. package/README.md +4 -1
  2. package/dist/advice-rules.json +772 -0
  3. package/dist/advice-terminology.json +104 -0
  4. package/dist/advice.d.ts +16 -0
  5. package/dist/advice.js +1375 -0
  6. package/dist/event-trigger.d.ts +14 -0
  7. package/dist/event-trigger.js +501 -0
  8. package/dist/fhir-translations.d.ts +5 -0
  9. package/dist/fhir-translations.js +117 -0
  10. package/dist/fhir.d.ts +6 -4
  11. package/dist/fhir.js +566 -134
  12. package/dist/format.d.ts +4 -2
  13. package/dist/format.js +515 -218
  14. package/dist/i18n.d.ts +2 -2
  15. package/dist/i18n.js +641 -199
  16. package/dist/index.d.ts +0 -1
  17. package/dist/index.js +219 -168
  18. package/dist/internal-types.d.ts +5 -5
  19. package/dist/ir.d.ts +4 -0
  20. package/dist/ir.js +178 -0
  21. package/dist/lexer/lex.d.ts +2 -0
  22. package/dist/lexer/lex.js +401 -0
  23. package/dist/lexer/meaning.d.ts +71 -0
  24. package/dist/lexer/meaning.js +619 -0
  25. package/dist/lexer/surface.d.ts +2 -0
  26. package/dist/lexer/surface.js +62 -0
  27. package/dist/lexer/token-types.d.ts +36 -0
  28. package/dist/lexer/token-types.js +19 -0
  29. package/dist/maps.d.ts +6 -12
  30. package/dist/maps.js +793 -247
  31. package/dist/parser-state.d.ts +101 -0
  32. package/dist/parser-state.js +441 -0
  33. package/dist/parser.d.ts +7 -7
  34. package/dist/parser.js +3598 -1974
  35. package/dist/prn.d.ts +4 -0
  36. package/dist/prn.js +59 -0
  37. package/dist/schedule.js +230 -32
  38. package/dist/site-phrases.d.ts +35 -0
  39. package/dist/site-phrases.js +344 -0
  40. package/dist/timing-summary.d.ts +13 -3
  41. package/dist/timing-summary.js +7 -7
  42. package/dist/types.d.ts +237 -32
  43. package/dist/types.js +49 -1
  44. package/dist/utils/text.d.ts +3 -0
  45. package/dist/utils/text.js +48 -0
  46. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { FhirDosage, FormatBatchOptions, FormatOptions, LintBatchResult, ParseBatchResult, ParseOptions, ParseResult } from "./types";
2
- export { parseInternal } from "./parser";
3
2
  export { suggestSig } from "./suggest";
4
3
  export * from "./types";
5
4
  export { nextDueDoses, calculateTotalUnits } from "./schedule";
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
23
23
  });
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.KNOWN_DOSAGE_FORMS_TO_DOSE = exports.DEFAULT_UNIT_BY_ROUTE = exports.DEFAULT_ROUTE_SYNONYMS = exports.DEFAULT_BODY_SITE_SNOMED_SOURCE = exports.DEFAULT_BODY_SITE_SNOMED = exports.resolveSigTranslation = exports.resolveSigLocalization = exports.registerSigLocalization = exports.getRegisteredSigLocalizations = exports.parseStrengthIntoRatio = exports.parseStrength = exports.calculateTotalUnits = exports.nextDueDoses = exports.suggestSig = exports.parseInternal = void 0;
26
+ exports.KNOWN_DOSAGE_FORMS_TO_DOSE = exports.DEFAULT_UNIT_BY_ROUTE = exports.DEFAULT_ROUTE_SYNONYMS = exports.DEFAULT_BODY_SITE_SNOMED_SOURCE = exports.DEFAULT_BODY_SITE_SNOMED = exports.resolveSigTranslation = exports.resolveSigLocalization = exports.registerSigLocalization = exports.getRegisteredSigLocalizations = exports.parseStrengthIntoRatio = exports.parseStrength = exports.calculateTotalUnits = exports.nextDueDoses = exports.suggestSig = void 0;
27
27
  exports.parseSig = parseSig;
28
28
  exports.lintSig = lintSig;
29
29
  exports.parseSigAsync = parseSigAsync;
@@ -33,11 +33,10 @@ exports.formatParseBatch = formatParseBatch;
33
33
  exports.fromFhirDosage = fromFhirDosage;
34
34
  const format_1 = require("./format");
35
35
  const fhir_1 = require("./fhir");
36
+ const ir_1 = require("./ir");
36
37
  const i18n_1 = require("./i18n");
37
38
  const parser_1 = require("./parser");
38
39
  const segment_1 = require("./segment");
39
- var parser_2 = require("./parser");
40
- Object.defineProperty(exports, "parseInternal", { enumerable: true, get: function () { return parser_2.parseInternal; } });
41
40
  var suggest_1 = require("./suggest");
42
41
  Object.defineProperty(exports, "suggestSig", { enumerable: true, get: function () { return suggest_1.suggestSig; } });
43
42
  __exportStar(require("./types"), exports);
@@ -328,7 +327,9 @@ function mergeParseResults(base, next, options) {
328
327
  shortText,
329
328
  longText,
330
329
  warnings: uniqueStrings([...((_k = base.warnings) !== null && _k !== void 0 ? _k : []), ...((_l = next.warnings) !== null && _l !== void 0 ? _l : [])]),
331
- meta: Object.assign(Object.assign({}, base.meta), { consumedTokens: uniqueStrings([...((_m = base.meta.consumedTokens) !== null && _m !== void 0 ? _m : []), ...((_o = next.meta.consumedTokens) !== null && _o !== void 0 ? _o : [])]), leftoverText: uniqueStrings([base.meta.leftoverText, next.meta.leftoverText].filter((value) => !!value)).join(" ").trim() || undefined, siteLookups: [...((_p = base.meta.siteLookups) !== null && _p !== void 0 ? _p : []), ...((_q = next.meta.siteLookups) !== null && _q !== void 0 ? _q : [])], prnReasonLookups: [...((_r = base.meta.prnReasonLookups) !== null && _r !== void 0 ? _r : []), ...((_s = next.meta.prnReasonLookups) !== null && _s !== void 0 ? _s : [])] })
330
+ meta: Object.assign(Object.assign({}, base.meta), { consumedTokens: uniqueStrings([...((_m = base.meta.consumedTokens) !== null && _m !== void 0 ? _m : []), ...((_o = next.meta.consumedTokens) !== null && _o !== void 0 ? _o : [])]), leftoverText: uniqueStrings([base.meta.leftoverText, next.meta.leftoverText].filter((value) => !!value)).join(" ").trim() || undefined, canonical: {
331
+ clauses: [...base.meta.canonical.clauses, ...next.meta.canonical.clauses]
332
+ }, siteLookups: [...((_p = base.meta.siteLookups) !== null && _p !== void 0 ? _p : []), ...((_q = next.meta.siteLookups) !== null && _q !== void 0 ? _q : [])], prnReasonLookups: [...((_r = base.meta.prnReasonLookups) !== null && _r !== void 0 ? _r : []), ...((_s = next.meta.prnReasonLookups) !== null && _s !== void 0 ? _s : [])] })
332
333
  };
333
334
  }
334
335
  /**
@@ -347,19 +348,26 @@ function appendParseResult(items, next, options) {
347
348
  }
348
349
  items.push(next);
349
350
  }
351
+ function collectCanonicalClauses(results) {
352
+ const clauses = [];
353
+ for (const result of results) {
354
+ clauses.push(...result.meta.canonical.clauses);
355
+ }
356
+ return clauses;
357
+ }
350
358
  function parseSig(input, options) {
351
359
  const segments = expandMealDashSegments((0, segment_1.splitSigSegments)(input), options);
352
360
  const carry = {};
353
361
  const results = [];
354
362
  for (const segment of segments) {
355
- const internal = (0, parser_1.parseInternal)(segment.text, options);
356
- applyCarryForward(internal, carry);
357
- (0, parser_1.applyPrnReasonCoding)(internal, options);
358
- (0, parser_1.applySiteCoding)(internal, options);
359
- const result = buildParseResult(internal, options);
363
+ const state = (0, parser_1.parseClauseState)(segment.text, options);
364
+ applyCarryForward(state, carry);
365
+ (0, parser_1.applyPrnReasonCoding)(state, options);
366
+ (0, parser_1.applySiteCoding)(state, options);
367
+ const result = buildParseResult(state, options);
360
368
  rebaseParseResult(result, input, segment.start);
361
369
  appendParseResult(results, result, options);
362
- updateCarryForward(carry, internal);
370
+ updateCarryForward(carry, state);
363
371
  }
364
372
  const legacy = resolveLegacyParseResult(results, input, options);
365
373
  return {
@@ -370,7 +378,11 @@ function parseSig(input, options) {
370
378
  shortText: legacy.shortText,
371
379
  longText: legacy.longText,
372
380
  warnings: legacy.warnings,
373
- meta: Object.assign(Object.assign({}, legacy.meta), { segments: toSegmentMeta(segments) })
381
+ meta: Object.assign(Object.assign({}, legacy.meta), { canonical: {
382
+ clauses: results.length
383
+ ? collectCanonicalClauses(results)
384
+ : legacy.meta.canonical.clauses
385
+ }, segments: toSegmentMeta(segments) })
374
386
  };
375
387
  }
376
388
  function lintSig(input, options) {
@@ -378,13 +390,13 @@ function lintSig(input, options) {
378
390
  const carry = {};
379
391
  const results = [];
380
392
  for (const segment of segments) {
381
- const internal = (0, parser_1.parseInternal)(segment.text, options);
382
- applyCarryForward(internal, carry);
383
- (0, parser_1.applyPrnReasonCoding)(internal, options);
384
- (0, parser_1.applySiteCoding)(internal, options);
385
- const result = buildParseResult(internal, options);
393
+ const state = (0, parser_1.parseClauseState)(segment.text, options);
394
+ applyCarryForward(state, carry);
395
+ (0, parser_1.applyPrnReasonCoding)(state, options);
396
+ (0, parser_1.applySiteCoding)(state, options);
397
+ const result = buildParseResult(state, options);
386
398
  rebaseParseResult(result, input, segment.start);
387
- const groups = (0, parser_1.findUnparsedTokenGroups)(internal);
399
+ const groups = (0, parser_1.findUnparsedTokenGroups)(state);
388
400
  const issues = groups.map((group) => {
389
401
  const shiftedRange = shiftRange(group.range, segment.start);
390
402
  const text = shiftedRange
@@ -397,8 +409,12 @@ function lintSig(input, options) {
397
409
  range: shiftedRange
398
410
  };
399
411
  });
412
+ issues.push(...buildSemanticLintIssues(result, input, {
413
+ start: segment.start,
414
+ end: segment.start + segment.text.length
415
+ }));
400
416
  results.push({ result, issues });
401
- updateCarryForward(carry, internal);
417
+ updateCarryForward(carry, state);
402
418
  }
403
419
  const legacy = resolveLegacyLintResult(results, input, options);
404
420
  return {
@@ -418,14 +434,14 @@ function parseSigAsync(input, options) {
418
434
  const carry = {};
419
435
  const results = [];
420
436
  for (const segment of segments) {
421
- const internal = (0, parser_1.parseInternal)(segment.text, options);
422
- applyCarryForward(internal, carry);
423
- yield (0, parser_1.applyPrnReasonCodingAsync)(internal, options);
424
- yield (0, parser_1.applySiteCodingAsync)(internal, options);
425
- const result = buildParseResult(internal, options);
437
+ const state = (0, parser_1.parseClauseState)(segment.text, options);
438
+ applyCarryForward(state, carry);
439
+ yield (0, parser_1.applyPrnReasonCodingAsync)(state, options);
440
+ yield (0, parser_1.applySiteCodingAsync)(state, options);
441
+ const result = buildParseResult(state, options);
426
442
  rebaseParseResult(result, input, segment.start);
427
443
  appendParseResult(results, result, options);
428
- updateCarryForward(carry, internal);
444
+ updateCarryForward(carry, state);
429
445
  }
430
446
  const legacy = resolveLegacyParseResult(results, input, options);
431
447
  return {
@@ -436,14 +452,18 @@ function parseSigAsync(input, options) {
436
452
  shortText: legacy.shortText,
437
453
  longText: legacy.longText,
438
454
  warnings: legacy.warnings,
439
- meta: Object.assign(Object.assign({}, legacy.meta), { segments: toSegmentMeta(segments) })
455
+ meta: Object.assign(Object.assign({}, legacy.meta), { canonical: {
456
+ clauses: results.length
457
+ ? collectCanonicalClauses(results)
458
+ : legacy.meta.canonical.clauses
459
+ }, segments: toSegmentMeta(segments) })
440
460
  };
441
461
  });
442
462
  }
443
463
  function formatSig(dosage, style = "short", options) {
444
- const internal = (0, fhir_1.internalFromFhir)(dosage);
464
+ const clause = (0, fhir_1.canonicalFromFhir)(dosage);
445
465
  const localization = (0, i18n_1.resolveSigLocalization)(options === null || options === void 0 ? void 0 : options.locale, options === null || options === void 0 ? void 0 : options.i18n);
446
- return (0, format_1.formatInternal)(internal, style, localization, options);
466
+ return (0, format_1.formatCanonicalClause)(clause, style, localization, options);
447
467
  }
448
468
  function formatSigBatch(dosages, style = "short", options) {
449
469
  var _a;
@@ -464,162 +484,168 @@ function formatParseBatch(batch, style = "short", separator = ", ") {
464
484
  return texts.join(separator);
465
485
  }
466
486
  function fromFhirDosage(dosage, options) {
467
- var _a, _b, _c, _d, _e;
468
- const internal = (0, fhir_1.internalFromFhir)(dosage);
487
+ var _a;
488
+ const clause = (0, fhir_1.canonicalFromFhir)(dosage);
469
489
  const localization = (0, i18n_1.resolveSigLocalization)(options === null || options === void 0 ? void 0 : options.locale, options === null || options === void 0 ? void 0 : options.i18n);
470
- const shortText = (0, format_1.formatInternal)(internal, "short", localization, options);
471
- const computedLong = (0, format_1.formatInternal)(internal, "long", localization, options);
490
+ const shortText = (0, format_1.formatCanonicalClause)(clause, "short", localization, options);
491
+ const computedLong = (0, format_1.formatCanonicalClause)(clause, "long", localization, options);
472
492
  const longText = computedLong || dosage.text || "";
473
493
  dosage.text = longText;
474
494
  return {
475
495
  fhir: dosage,
476
496
  shortText,
477
497
  longText,
478
- warnings: [],
498
+ warnings: (_a = clause.warnings) !== null && _a !== void 0 ? _a : [],
479
499
  meta: {
480
500
  consumedTokens: [],
481
- normalized: {
482
- route: internal.routeCode,
483
- unit: internal.unit,
484
- site: internal.siteText || ((_a = internal.siteCoding) === null || _a === void 0 ? void 0 : _a.code)
485
- ? {
486
- text: internal.siteText,
487
- coding: ((_b = internal.siteCoding) === null || _b === void 0 ? void 0 : _b.code)
488
- ? {
489
- code: internal.siteCoding.code,
490
- display: internal.siteCoding.display,
491
- system: internal.siteCoding.system
492
- }
493
- : undefined
494
- }
495
- : undefined,
496
- prnReason: internal.asNeededReason || ((_c = internal.asNeededReasonCoding) === null || _c === void 0 ? void 0 : _c.code)
497
- ? {
498
- text: internal.asNeededReason,
499
- coding: ((_d = internal.asNeededReasonCoding) === null || _d === void 0 ? void 0 : _d.code)
500
- ? {
501
- code: internal.asNeededReasonCoding.code,
502
- display: internal.asNeededReasonCoding.display,
503
- system: internal.asNeededReasonCoding.system
504
- }
505
- : undefined
506
- }
507
- : undefined,
508
- additionalInstructions: ((_e = internal.additionalInstructions) === null || _e === void 0 ? void 0 : _e.length)
509
- ? internal.additionalInstructions.map((instruction) => {
510
- var _a;
511
- return ({
512
- text: instruction.text,
513
- coding: ((_a = instruction.coding) === null || _a === void 0 ? void 0 : _a.code)
514
- ? {
515
- code: instruction.coding.code,
516
- display: instruction.coding.display,
517
- system: instruction.coding.system
518
- }
519
- : undefined
520
- });
521
- })
522
- : undefined
501
+ normalized: buildNormalizedMetaFromClause(clause),
502
+ canonical: {
503
+ clauses: [clause]
523
504
  }
524
505
  }
525
506
  };
526
507
  }
527
- function buildParseResult(internal, options) {
528
- var _a, _b, _c;
508
+ function createEmptyCanonicalClause(rawText) {
509
+ return {
510
+ kind: "administration",
511
+ rawText,
512
+ raw: {
513
+ start: 0,
514
+ end: rawText.length,
515
+ text: rawText
516
+ },
517
+ leftovers: [],
518
+ evidence: [],
519
+ confidence: 1
520
+ };
521
+ }
522
+ function getPrimaryClause(clauses, rawText) {
523
+ var _a;
524
+ return (_a = clauses[0]) !== null && _a !== void 0 ? _a : createEmptyCanonicalClause(rawText);
525
+ }
526
+ function cloneCoding(coding) {
527
+ 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)) {
528
+ return undefined;
529
+ }
530
+ return {
531
+ code: coding.code,
532
+ display: coding.display,
533
+ system: coding.system
534
+ };
535
+ }
536
+ function cloneBodySiteCoding(coding) {
537
+ if (!(coding === null || coding === void 0 ? void 0 : coding.code)) {
538
+ return undefined;
539
+ }
540
+ return {
541
+ code: coding.code,
542
+ display: coding.display,
543
+ system: coding.system
544
+ };
545
+ }
546
+ function buildNormalizedMetaFromClause(clause) {
547
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
548
+ const additionalInstructions = ((_a = clause.additionalInstructions) === null || _a === void 0 ? void 0 : _a.length)
549
+ ? clause.additionalInstructions.map((instruction) => ({
550
+ text: instruction.text,
551
+ coding: cloneCoding(instruction.coding)
552
+ }))
553
+ : undefined;
554
+ return {
555
+ route: (_b = clause.route) === null || _b === void 0 ? void 0 : _b.code,
556
+ unit: (_c = clause.dose) === null || _c === void 0 ? void 0 : _c.unit,
557
+ site: ((_d = clause.site) === null || _d === void 0 ? void 0 : _d.text) || ((_f = (_e = clause.site) === null || _e === void 0 ? void 0 : _e.coding) === null || _f === void 0 ? void 0 : _f.code)
558
+ ? {
559
+ text: (_g = clause.site) === null || _g === void 0 ? void 0 : _g.text,
560
+ coding: cloneBodySiteCoding((_h = clause.site) === null || _h === void 0 ? void 0 : _h.coding)
561
+ }
562
+ : undefined,
563
+ method: ((_j = clause.method) === null || _j === void 0 ? void 0 : _j.text) || ((_l = (_k = clause.method) === null || _k === void 0 ? void 0 : _k.coding) === null || _l === void 0 ? void 0 : _l.code)
564
+ ? {
565
+ text: (_m = clause.method) === null || _m === void 0 ? void 0 : _m.text,
566
+ coding: cloneCoding((_o = clause.method) === null || _o === void 0 ? void 0 : _o.coding)
567
+ }
568
+ : undefined,
569
+ patientInstruction: clause.patientInstruction,
570
+ prnReason: ((_q = (_p = clause.prn) === null || _p === void 0 ? void 0 : _p.reason) === null || _q === void 0 ? void 0 : _q.text) || ((_t = (_s = (_r = clause.prn) === null || _r === void 0 ? void 0 : _r.reason) === null || _s === void 0 ? void 0 : _s.coding) === null || _t === void 0 ? void 0 : _t.code)
571
+ ? {
572
+ text: (_v = (_u = clause.prn) === null || _u === void 0 ? void 0 : _u.reason) === null || _v === void 0 ? void 0 : _v.text,
573
+ coding: cloneCoding((_x = (_w = clause.prn) === null || _w === void 0 ? void 0 : _w.reason) === null || _x === void 0 ? void 0 : _x.coding)
574
+ }
575
+ : undefined,
576
+ prnReasons: ((_z = (_y = clause.prn) === null || _y === void 0 ? void 0 : _y.reasons) === null || _z === void 0 ? void 0 : _z.length)
577
+ ? clause.prn.reasons.map((reason) => ({
578
+ text: reason.text,
579
+ coding: cloneCoding(reason.coding)
580
+ }))
581
+ : undefined,
582
+ additionalInstructions
583
+ };
584
+ }
585
+ function buildParseResult(state, options) {
586
+ const canonicalClauses = state.clauses;
587
+ const clause = getPrimaryClause(canonicalClauses, state.input);
529
588
  const localization = (0, i18n_1.resolveSigLocalization)(options === null || options === void 0 ? void 0 : options.locale, options === null || options === void 0 ? void 0 : options.i18n);
530
- const shortText = (0, format_1.formatInternal)(internal, "short", localization, options);
531
- const longText = (0, format_1.formatInternal)(internal, "long", localization, options);
532
- const fhir = (0, fhir_1.toFhir)(internal);
533
- if (longText) {
534
- fhir.text = longText;
535
- }
536
- const consumedTokens = internal.tokens
537
- .filter((token) => internal.consumed.has(token.index))
538
- .map((token) => token.original);
539
- const leftoverTokens = internal.tokens.filter((token) => !internal.consumed.has(token.index));
540
- const siteCoding = ((_a = internal.siteCoding) === null || _a === void 0 ? void 0 : _a.code)
541
- ? {
542
- code: internal.siteCoding.code,
543
- display: internal.siteCoding.display,
544
- system: internal.siteCoding.system
589
+ const shortText = (0, format_1.formatCanonicalClause)(clause, "short", localization, options);
590
+ const longText = (0, format_1.formatCanonicalClause)(clause, "long", localization, options);
591
+ const fhir = (0, fhir_1.canonicalToFhir)(clause, longText);
592
+ const consumedTokens = [];
593
+ const leftoverParts = [];
594
+ for (const token of state.tokens) {
595
+ if (state.consumed.has(token.index)) {
596
+ consumedTokens.push(token.original);
545
597
  }
546
- : undefined;
547
- const prnReasonCoding = ((_b = internal.asNeededReasonCoding) === null || _b === void 0 ? void 0 : _b.code)
548
- ? {
549
- code: internal.asNeededReasonCoding.code,
550
- display: internal.asNeededReasonCoding.display,
551
- system: internal.asNeededReasonCoding.system
598
+ else {
599
+ leftoverParts.push(token.original);
552
600
  }
553
- : undefined;
554
- const additionalInstructions = ((_c = internal.additionalInstructions) === null || _c === void 0 ? void 0 : _c.length)
555
- ? internal.additionalInstructions.map((instruction) => {
556
- var _a;
557
- return ({
558
- text: instruction.text,
559
- coding: ((_a = instruction.coding) === null || _a === void 0 ? void 0 : _a.code)
560
- ? {
561
- code: instruction.coding.code,
562
- display: instruction.coding.display,
563
- system: instruction.coding.system
564
- }
565
- : undefined
566
- });
567
- })
568
- : undefined;
569
- const siteLookups = internal.siteLookups.length
570
- ? internal.siteLookups.map((entry) => ({
571
- request: entry.request,
572
- suggestions: entry.suggestions.map((suggestion) => ({
573
- coding: {
574
- code: suggestion.coding.code,
575
- display: suggestion.coding.display,
576
- system: suggestion.coding.system
577
- },
578
- text: suggestion.text
579
- }))
580
- }))
581
- : undefined;
582
- const prnReasonLookups = internal.prnReasonLookups.length
583
- ? internal.prnReasonLookups.map((entry) => ({
584
- request: entry.request,
585
- suggestions: entry.suggestions.map((suggestion) => ({
586
- coding: suggestion.coding
587
- ? {
601
+ }
602
+ const siteLookups = state.siteLookups.length ? [] : undefined;
603
+ if (siteLookups) {
604
+ for (const entry of state.siteLookups) {
605
+ const suggestions = [];
606
+ for (const suggestion of entry.suggestions) {
607
+ suggestions.push({
608
+ coding: {
588
609
  code: suggestion.coding.code,
589
610
  display: suggestion.coding.display,
590
611
  system: suggestion.coding.system
591
- }
592
- : undefined,
593
- text: suggestion.text
594
- }))
595
- }))
596
- : undefined;
612
+ },
613
+ text: suggestion.text
614
+ });
615
+ }
616
+ siteLookups.push({
617
+ request: entry.request,
618
+ suggestions
619
+ });
620
+ }
621
+ }
622
+ const prnReasonLookups = state.prnReasonLookups.length ? [] : undefined;
623
+ if (prnReasonLookups) {
624
+ for (const entry of state.prnReasonLookups) {
625
+ const suggestions = [];
626
+ for (const suggestion of entry.suggestions) {
627
+ suggestions.push({
628
+ coding: cloneCoding(suggestion.coding),
629
+ text: suggestion.text
630
+ });
631
+ }
632
+ prnReasonLookups.push({
633
+ request: entry.request,
634
+ suggestions
635
+ });
636
+ }
637
+ }
597
638
  return {
598
639
  fhir,
599
640
  shortText,
600
641
  longText,
601
- warnings: internal.warnings,
642
+ warnings: state.warnings,
602
643
  meta: {
603
644
  consumedTokens,
604
- leftoverText: leftoverTokens.length
605
- ? leftoverTokens.map((t) => t.original).join(" ")
606
- : undefined,
607
- normalized: {
608
- route: internal.routeCode,
609
- unit: internal.unit,
610
- site: internal.siteText || siteCoding
611
- ? {
612
- text: internal.siteText,
613
- coding: siteCoding
614
- }
615
- : undefined,
616
- prnReason: internal.asNeededReason || prnReasonCoding
617
- ? {
618
- text: internal.asNeededReason,
619
- coding: prnReasonCoding
620
- }
621
- : undefined,
622
- additionalInstructions
645
+ leftoverText: leftoverParts.length ? leftoverParts.join(" ") : undefined,
646
+ normalized: buildNormalizedMetaFromClause(clause),
647
+ canonical: {
648
+ clauses: canonicalClauses
623
649
  },
624
650
  siteLookups,
625
651
  prnReasonLookups
@@ -680,6 +706,7 @@ function rebaseParseResult(result, fullInput, offset) {
680
706
  rebaseRequest(lookup.request);
681
707
  }
682
708
  }
709
+ (0, ir_1.shiftCanonicalSigClauses)(result.meta.canonical.clauses, offset);
683
710
  }
684
711
  function shiftRange(range, offset) {
685
712
  if (!range) {
@@ -694,23 +721,46 @@ function resolveLegacyParseResult(results, input, options) {
694
721
  if (results.length > 0) {
695
722
  return results[0];
696
723
  }
697
- const internal = (0, parser_1.parseInternal)(input, options);
698
- (0, parser_1.applyPrnReasonCoding)(internal, options);
699
- (0, parser_1.applySiteCoding)(internal, options);
700
- return buildParseResult(internal, options);
724
+ const state = (0, parser_1.parseClauseState)(input, options);
725
+ (0, parser_1.applyPrnReasonCoding)(state, options);
726
+ (0, parser_1.applySiteCoding)(state, options);
727
+ return buildParseResult(state, options);
728
+ }
729
+ function buildSemanticLintIssues(result, input, fallbackRange) {
730
+ var _a;
731
+ const issues = [];
732
+ const clause = result.meta.canonical.clauses[0];
733
+ const range = (_a = clause === null || clause === void 0 ? void 0 : clause.span) !== null && _a !== void 0 ? _a : fallbackRange;
734
+ const text = range
735
+ ? input.slice(range.start, range.end)
736
+ : input;
737
+ const trimmedText = text.trim() || text;
738
+ const tokens = trimmedText ? trimmedText.split(/\s+/).filter((part) => part.length > 0) : [];
739
+ for (const warning of result.warnings) {
740
+ if (!warning.startsWith("Incomplete sig:")) {
741
+ continue;
742
+ }
743
+ issues.push({
744
+ message: warning,
745
+ text: trimmedText,
746
+ tokens,
747
+ range
748
+ });
749
+ }
750
+ return issues;
701
751
  }
702
752
  function resolveLegacyLintResult(results, input, options) {
703
753
  if (results.length > 0) {
704
754
  return results[0];
705
755
  }
706
- const internal = (0, parser_1.parseInternal)(input, options);
707
- (0, parser_1.applyPrnReasonCoding)(internal, options);
708
- (0, parser_1.applySiteCoding)(internal, options);
709
- const result = buildParseResult(internal, options);
710
- const groups = (0, parser_1.findUnparsedTokenGroups)(internal);
756
+ const state = (0, parser_1.parseClauseState)(input, options);
757
+ (0, parser_1.applyPrnReasonCoding)(state, options);
758
+ (0, parser_1.applySiteCoding)(state, options);
759
+ const result = buildParseResult(state, options);
760
+ const groups = (0, parser_1.findUnparsedTokenGroups)(state);
711
761
  const issues = groups.map((group) => {
712
762
  const text = group.range
713
- ? internal.input.slice(group.range.start, group.range.end)
763
+ ? state.input.slice(group.range.start, group.range.end)
714
764
  : group.tokens.map((token) => token.original).join(" ");
715
765
  return {
716
766
  message: "Unrecognized text",
@@ -719,5 +769,6 @@ function resolveLegacyLintResult(results, input, options) {
719
769
  range: group.range
720
770
  };
721
771
  });
772
+ issues.push(...buildSemanticLintIssues(result, input));
722
773
  return { result, issues };
723
774
  }
@@ -1,4 +1,5 @@
1
- import { EventTiming, FhirCoding, FhirDayOfWeek, FhirPeriodUnit, PrnReasonLookupRequest, PrnReasonSuggestion, RouteCode, SiteCodeLookupRequest, SiteCodeSuggestion } from "./types";
1
+ import { AnnotatedLexToken } from "./lexer/meaning";
2
+ import { AdviceFrame, CanonicalSigClause, EventTiming, FhirCoding, FhirDayOfWeek, FhirPeriodUnit, PrnReasonLookupRequest, PrnReasonSuggestion, RouteCode, SiteCodeLookupRequest, SiteCodeSuggestion } from "./types";
2
3
  export interface SiteLookupDetail {
3
4
  request: SiteCodeLookupRequest;
4
5
  suggestions: SiteCodeSuggestion[];
@@ -7,10 +8,7 @@ export interface PrnReasonLookupDetail {
7
8
  request: PrnReasonLookupRequest;
8
9
  suggestions: PrnReasonSuggestion[];
9
10
  }
10
- export interface Token {
11
- original: string;
12
- lower: string;
13
- index: number;
11
+ export interface Token extends AnnotatedLexToken {
14
12
  }
15
13
  export interface ParsedSigInternal {
16
14
  input: string;
@@ -56,5 +54,7 @@ export interface ParsedSigInternal {
56
54
  coding?: FhirCoding & {
57
55
  i18n?: Record<string, string>;
58
56
  };
57
+ frames?: AdviceFrame[];
59
58
  }>;
59
+ canonicalClauses?: CanonicalSigClause[];
60
60
  }
package/dist/ir.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { ParserState } from "./parser-state";
2
+ import { CanonicalSigClause } from "./types";
3
+ export declare function buildCanonicalSigClauses(internal: ParserState): CanonicalSigClause[];
4
+ export declare function shiftCanonicalSigClauses(clauses: CanonicalSigClause[], offset: number): void;