Skip to content

Commit abb91c4

Browse files
committed
Merge branch 'LF-3510-fix-delimited-identifiers' into 'master'
Delimited identifiers can now have string escapes See merge request lfor/fhirpath.js!57
2 parents 45483ce + bcff0e6 commit abb91c4

5 files changed

Lines changed: 57 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
This log documents significant changes for each release. This project follows
44
[Semantic Versioning](http://semver.org/).
55

6+
## [4.9.1] - 2026-03-11
7+
### Fixed
8+
- Delimited identifiers can now have string escapes.
9+
610
## [4.9.0] - 2026-02-19
711
### Added
812
- **Precise decimal arithmetic mode** (`preciseMath` option): A new mathematical

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "fhirpath",
3-
"version": "4.9.0",
3+
"version": "4.9.1",
44
"description": "A FHIRPath engine",
55
"main": "src/fhirpath.js",
66
"types": "src/fhirpath.d.ts",

src/fhirpath.js

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ engine.PolarityExpression = function(ctx, parentData, node) {
260260

261261
engine.TypeSpecifier = function(ctx, parentData, node) {
262262
let namespace, name;
263-
const identifiers = node.text.split('.').map(i => i.replace(/(^`|`$)/g, ""));
263+
const identifiers = node.text.split('.').map(getDelimitedIdentifierVal);
264264
switch (identifiers.length) {
265265
case 2:
266266
[namespace, name] = identifiers;
@@ -369,24 +369,10 @@ engine.StringLiteral = function(ctx, parentData, node) {
369369
* @return {string}
370370
*/
371371
function getStringLiteralVal(str) {
372-
return str.replace(/(^'|'$)/g, "")
373-
.replace(/\\(u\d{4}|.)/g, function(match, submatch) {
374-
switch(match) {
375-
case '\\r':
376-
return '\r';
377-
case '\\n':
378-
return "\n";
379-
case '\\t':
380-
return '\t';
381-
case '\\f':
382-
return '\f';
383-
default:
384-
if (submatch.length > 1)
385-
return String.fromCharCode('0x'+submatch.slice(1));
386-
else
387-
return submatch;
388-
}
389-
});
372+
if (str && str[0] === "'" && str[str.length - 1] === "'") {
373+
return handleStringEscapes(str.slice(1, -1));
374+
}
375+
return str;
390376
}
391377

392378
engine.BooleanLiteral = function(ctx, parentData, node) {
@@ -450,12 +436,49 @@ engine.Identifier = function(ctx, parentData, node) {
450436
};
451437

452438
/**
453-
* Removes the beginning and ending back-quotes.
439+
* Resolves an identifier value, including delimited identifiers.
454440
* @param {string} str - identifier string
455441
* @return {string}
456442
*/
457443
function getIdentifierVal(str) {
458-
return str.replace(/(^`|`$)/g, "");
444+
return getDelimitedIdentifierVal(str);
445+
}
446+
447+
/**
448+
* Handles string-style escape sequences.
449+
* @param {string} str - string content without surrounding quotes
450+
* @return {string}
451+
*/
452+
function handleStringEscapes(str) {
453+
return str.replace(/\\(u\d{4}|.)/g, function(match, submatch) {
454+
switch (match) {
455+
case '\\r':
456+
return '\r';
457+
case '\\n':
458+
return "\n";
459+
case '\\t':
460+
return '\t';
461+
case '\\f':
462+
return '\f';
463+
default:
464+
if (submatch.length > 1) {
465+
return String.fromCharCode('0x' + submatch.slice(1));
466+
}
467+
return submatch;
468+
}
469+
});
470+
}
471+
472+
/**
473+
* Removes the beginning and ending back-quotes and handles escapes.
474+
* @param {string} str - identifier string
475+
* @return {string}
476+
*/
477+
function getDelimitedIdentifierVal(str) {
478+
if (str && str[0] === '`' && str[str.length - 1] === '`') {
479+
return handleStringEscapes(str.slice(1, -1));
480+
}
481+
return str;
459482
}
460483

461484
engine.InvocationTerm = function(ctx, parentData, node) {

test/cases/simple.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ tests:
77
- Chalmers
88
- Windsor
99

10+
- desc: delimited identifier with escape
11+
expression: 'Patient.`odd\`name`'
12+
result:
13+
- odd-value
14+
1015
- desc: mapcat arrays
1116
expression: Patient.name.given
1217
result: ["Peter", "James", "Jim", "Peter", "James"]
@@ -188,6 +193,7 @@ tests:
188193
subject:
189194
resourceType: Patient
190195
id: example
196+
"odd`name": odd-value
191197
address:
192198
- use: home
193199
city: PleasantVille

0 commit comments

Comments
 (0)