如何仅在另一个解析器接受时使用(Petit Parser for Dart)

问题描述 投票:0回答:1

我正在研究一种称为 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

关于如何让这种事情发挥作用有什么建议吗?

flutter dart antlr petitparser
1个回答
0
投票

提供的示例很难理解,并且不能最低限度地重现(可复制粘贴到编辑器中),所以我试图回答我认为可以提取的两个问题。

如何仅在另一个解析器接受时才消费?

有多种方法可以实现这一点:有逻辑谓词 andnot。此外,还有“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, ','])));

© www.soinside.com 2019 - 2024. All rights reserved.