我正在研究一种称为 fhir 映射语言 antlr 语法的东西,可以在这里找到。但我喜欢小解析器,所以我一直在尝试对其进行建模。我一直困惑的部分是 fhirpath 的制作。我制作了一个单独的 fhirpath 词法分析器/解析器,它运行良好。但对于 fhir 映射,只要输入是有效的 fhirpath,产品之一就会摄取输入。因此,我需要接受所有输入,直到到达不再有效的 fhirpath 为止。这可以通过多种方式来完成。我们可能到达文本末尾,但下一个文本不是有效的 fhirpath。还有一些分隔符,其中一些应该是有效的 fhirpath,但在本例中不是。我遇到的另一个问题是,有些分隔符是否可以转义,如果它们被转义,它们就是 fhirpath 的一部分,不应该算作分隔符。
这是基本设置:
Parser<String> fpLexer(String function, List<String> delimiters) {
return delimiters
.map(string)
.toChoiceParser()
.cast<String>()
.neg()
.plus()
.flatten()
.map((value) => fhirPathWithOrWithoutParen(value))
.where((value) {
try {
print('FUNCTION: $function: fpLexer: $value');
final result = lexer().parse(value);
return result is Success;
} catch (e) {
return false;
}
});
}
我尝试过使用它,有时可以识别分隔符,有时则不能。这显然不起作用,但这就是我正在搞乱的事情:
Parser<String> fpLexer(String function, List<String> delimiters) {
bool escaped = false;
return delimiters
.map(string)
.toChoiceParser()
.cast<String>()
.map((value) {
if (escaped) {
escaped = false;
return value;
} else {
return string(value).neg();
}
}, hasSideEffects: true)
.map((value) {
if (value == r'\') {
escaped = true;
}
return value;
})
.plus()
.flatten()
.map((value) => fhirPathWithOrWithoutParen(value))
.where((value) {
try {
print('FUNCTION: $function: fpLexer: $value');
final result = lexer().parse(value);
return result is Success;
} catch (e) {
return false;
}
});
}
给我带来麻烦的一行示例:
text.div as div -> act.text as text, text.reference as reference, reference.value = ('#' + %div.substring(%div.indexOf('id') + %div.substring(%div.indexOf('id')).indexOf('\"') + 1, %div.substring(%div.indexOf('id') + %div.substring(%div.indexOf('id')).indexOf('\"') + 1).indexOf('\"'))) "id";
包含我要解析的这一行的完整文件可以在这里找到:https://github.com/hl7ch/cda-fhir-maps/blob/master/input/maps/BundleToCdaCh.map
关于如何让这种事情发挥作用有什么建议吗?
提供的示例很难理解,并且不能最低限度地重现(可复制粘贴到编辑器中),所以我试图回答我认为可以提取的两个问题。
有多种方法可以实现这一点:有逻辑谓词 and 和 not。此外,还有“lazy”和“greedy”重复器会消耗一个解析器,直到另一个解析器成功。在下面的测试用例中,只要当前数字之后还有两位数字可用,解析器就会消耗数字(因此重复 3 次):
final parser = digit().starLazy(digit().repeat(3).not());
expect(parser, isParseSuccess('123', result: ['1'], position: 1));
expect(parser, isParseSuccess('1234', result: ['1', '2'], position: 2));
如何识别带有可选分隔符的项目列表?
这很简单,分离解析器创建一个元素和分隔符的列表(其中分隔符也可以是可选的解析器):
final parser = digit().plusSeparated(char(',').optional());
expect(parser, isParseSuccess('1,2,3', result: isSeparatedList<String, String?>(
elements: ['1', '2', '3'], separators: [',', ','])));
expect(parser, isParseSuccess('12,3', result: isSeparatedList<String, String?>(
elements: ['1', '2', '3'], separators: [null, ','])));