ezmedicationinput 0.1.42 → 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 +31 -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 +5 -2
  13. package/dist/format.js +581 -219
  14. package/dist/i18n.d.ts +4 -2
  15. package/dist/i18n.js +725 -197
  16. package/dist/index.d.ts +0 -1
  17. package/dist/index.js +221 -169
  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 +25 -0
  41. package/dist/timing-summary.js +138 -0
  42. package/dist/types.d.ts +248 -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);
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,161 +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, _f;
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);
471
- const computedLong = (0, format_1.formatInternal)(internal, "long", localization);
472
- const longText = localization ? computedLong : (_a = dosage.text) !== null && _a !== void 0 ? _a : computedLong;
490
+ const shortText = (0, format_1.formatCanonicalClause)(clause, "short", localization, options);
491
+ const computedLong = (0, format_1.formatCanonicalClause)(clause, "long", localization, options);
492
+ const longText = computedLong || dosage.text || "";
493
+ dosage.text = longText;
473
494
  return {
474
495
  fhir: dosage,
475
496
  shortText,
476
497
  longText,
477
- warnings: [],
498
+ warnings: (_a = clause.warnings) !== null && _a !== void 0 ? _a : [],
478
499
  meta: {
479
500
  consumedTokens: [],
480
- normalized: {
481
- route: internal.routeCode,
482
- unit: internal.unit,
483
- site: internal.siteText || ((_b = internal.siteCoding) === null || _b === void 0 ? void 0 : _b.code)
484
- ? {
485
- text: internal.siteText,
486
- coding: ((_c = internal.siteCoding) === null || _c === void 0 ? void 0 : _c.code)
487
- ? {
488
- code: internal.siteCoding.code,
489
- display: internal.siteCoding.display,
490
- system: internal.siteCoding.system
491
- }
492
- : undefined
493
- }
494
- : undefined,
495
- prnReason: internal.asNeededReason || ((_d = internal.asNeededReasonCoding) === null || _d === void 0 ? void 0 : _d.code)
496
- ? {
497
- text: internal.asNeededReason,
498
- coding: ((_e = internal.asNeededReasonCoding) === null || _e === void 0 ? void 0 : _e.code)
499
- ? {
500
- code: internal.asNeededReasonCoding.code,
501
- display: internal.asNeededReasonCoding.display,
502
- system: internal.asNeededReasonCoding.system
503
- }
504
- : undefined
505
- }
506
- : undefined,
507
- additionalInstructions: ((_f = internal.additionalInstructions) === null || _f === void 0 ? void 0 : _f.length)
508
- ? internal.additionalInstructions.map((instruction) => {
509
- var _a;
510
- return ({
511
- text: instruction.text,
512
- coding: ((_a = instruction.coding) === null || _a === void 0 ? void 0 : _a.code)
513
- ? {
514
- code: instruction.coding.code,
515
- display: instruction.coding.display,
516
- system: instruction.coding.system
517
- }
518
- : undefined
519
- });
520
- })
521
- : undefined
501
+ normalized: buildNormalizedMetaFromClause(clause),
502
+ canonical: {
503
+ clauses: [clause]
522
504
  }
523
505
  }
524
506
  };
525
507
  }
526
- function buildParseResult(internal, options) {
527
- 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);
528
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);
529
- const shortText = (0, format_1.formatInternal)(internal, "short", localization);
530
- const longText = (0, format_1.formatInternal)(internal, "long", localization);
531
- const fhir = (0, fhir_1.toFhir)(internal);
532
- if (longText) {
533
- fhir.text = longText;
534
- }
535
- const consumedTokens = internal.tokens
536
- .filter((token) => internal.consumed.has(token.index))
537
- .map((token) => token.original);
538
- const leftoverTokens = internal.tokens.filter((token) => !internal.consumed.has(token.index));
539
- const siteCoding = ((_a = internal.siteCoding) === null || _a === void 0 ? void 0 : _a.code)
540
- ? {
541
- code: internal.siteCoding.code,
542
- display: internal.siteCoding.display,
543
- 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);
544
597
  }
545
- : undefined;
546
- const prnReasonCoding = ((_b = internal.asNeededReasonCoding) === null || _b === void 0 ? void 0 : _b.code)
547
- ? {
548
- code: internal.asNeededReasonCoding.code,
549
- display: internal.asNeededReasonCoding.display,
550
- system: internal.asNeededReasonCoding.system
598
+ else {
599
+ leftoverParts.push(token.original);
551
600
  }
552
- : undefined;
553
- const additionalInstructions = ((_c = internal.additionalInstructions) === null || _c === void 0 ? void 0 : _c.length)
554
- ? internal.additionalInstructions.map((instruction) => {
555
- var _a;
556
- return ({
557
- text: instruction.text,
558
- coding: ((_a = instruction.coding) === null || _a === void 0 ? void 0 : _a.code)
559
- ? {
560
- code: instruction.coding.code,
561
- display: instruction.coding.display,
562
- system: instruction.coding.system
563
- }
564
- : undefined
565
- });
566
- })
567
- : undefined;
568
- const siteLookups = internal.siteLookups.length
569
- ? internal.siteLookups.map((entry) => ({
570
- request: entry.request,
571
- suggestions: entry.suggestions.map((suggestion) => ({
572
- coding: {
573
- code: suggestion.coding.code,
574
- display: suggestion.coding.display,
575
- system: suggestion.coding.system
576
- },
577
- text: suggestion.text
578
- }))
579
- }))
580
- : undefined;
581
- const prnReasonLookups = internal.prnReasonLookups.length
582
- ? internal.prnReasonLookups.map((entry) => ({
583
- request: entry.request,
584
- suggestions: entry.suggestions.map((suggestion) => ({
585
- coding: suggestion.coding
586
- ? {
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: {
587
609
  code: suggestion.coding.code,
588
610
  display: suggestion.coding.display,
589
611
  system: suggestion.coding.system
590
- }
591
- : undefined,
592
- text: suggestion.text
593
- }))
594
- }))
595
- : 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
+ }
596
638
  return {
597
639
  fhir,
598
640
  shortText,
599
641
  longText,
600
- warnings: internal.warnings,
642
+ warnings: state.warnings,
601
643
  meta: {
602
644
  consumedTokens,
603
- leftoverText: leftoverTokens.length
604
- ? leftoverTokens.map((t) => t.original).join(" ")
605
- : undefined,
606
- normalized: {
607
- route: internal.routeCode,
608
- unit: internal.unit,
609
- site: internal.siteText || siteCoding
610
- ? {
611
- text: internal.siteText,
612
- coding: siteCoding
613
- }
614
- : undefined,
615
- prnReason: internal.asNeededReason || prnReasonCoding
616
- ? {
617
- text: internal.asNeededReason,
618
- coding: prnReasonCoding
619
- }
620
- : undefined,
621
- additionalInstructions
645
+ leftoverText: leftoverParts.length ? leftoverParts.join(" ") : undefined,
646
+ normalized: buildNormalizedMetaFromClause(clause),
647
+ canonical: {
648
+ clauses: canonicalClauses
622
649
  },
623
650
  siteLookups,
624
651
  prnReasonLookups
@@ -679,6 +706,7 @@ function rebaseParseResult(result, fullInput, offset) {
679
706
  rebaseRequest(lookup.request);
680
707
  }
681
708
  }
709
+ (0, ir_1.shiftCanonicalSigClauses)(result.meta.canonical.clauses, offset);
682
710
  }
683
711
  function shiftRange(range, offset) {
684
712
  if (!range) {
@@ -693,23 +721,46 @@ function resolveLegacyParseResult(results, input, options) {
693
721
  if (results.length > 0) {
694
722
  return results[0];
695
723
  }
696
- const internal = (0, parser_1.parseInternal)(input, options);
697
- (0, parser_1.applyPrnReasonCoding)(internal, options);
698
- (0, parser_1.applySiteCoding)(internal, options);
699
- 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;
700
751
  }
701
752
  function resolveLegacyLintResult(results, input, options) {
702
753
  if (results.length > 0) {
703
754
  return results[0];
704
755
  }
705
- const internal = (0, parser_1.parseInternal)(input, options);
706
- (0, parser_1.applyPrnReasonCoding)(internal, options);
707
- (0, parser_1.applySiteCoding)(internal, options);
708
- const result = buildParseResult(internal, options);
709
- 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);
710
761
  const issues = groups.map((group) => {
711
762
  const text = group.range
712
- ? internal.input.slice(group.range.start, group.range.end)
763
+ ? state.input.slice(group.range.start, group.range.end)
713
764
  : group.tokens.map((token) => token.original).join(" ");
714
765
  return {
715
766
  message: "Unrecognized text",
@@ -718,5 +769,6 @@ function resolveLegacyLintResult(results, input, options) {
718
769
  range: group.range
719
770
  };
720
771
  });
772
+ issues.push(...buildSemanticLintIssues(result, input));
721
773
  return { result, issues };
722
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;