使用 Flutter 的 PetiteParser 创建 FHIRPath

如何解决使用 Flutter 的 PetiteParser 创建 FHIRPath

我想寻求一些使用 petitparser 的指导(我正在更新这个问题)。我正在尝试在 dart 中重新创建一个基于 json 的语法,称为 FHIRPath。我是这样的语法的新手,所以我花了一点时间来理解我想要它做什么(或者我认为我想要它做什么)。我已经设法让它解析 json 路径和一般函数,它看起来像这样:

class FhirPathGrammar extends GrammarDeFinition {
  Parser start() => ref0(value).end();

  Parser value() => (ref0(parens) | ref0(dotString) | ref0(path)).star();

  Parser parens() =>
      (char('(') & ref0(value) & char(')')).map((value) => value);

  Parser dotString() =>
      (anyOf('-_') | letter() | digit() | range(0x80,0x10FFF))
          .plus()
          .flatten();
          
  Parser path() => (char('.') & ref0(dotString)).map((value) => value);
}

如果我运行这个函数

void main() {
  var pathString = 'Patient.name.exists()';
  var deFinition = FhirPathGrammar();
  final parser = deFinition.build();
  print(parser.parse(pathString));
}

结果如下:

[Patient,[.,name],exists],[(,[],)]]

到目前为止一切顺利。但是现在如果我改变我的语法类,并添加一个相等的解析器:

class FhirPathGrammar extends GrammarDeFinition {
  Parser start() => ref0(value).end();

  Parser value() =>
      (ref0(parens) | ref0(dotString) | ref0(path) | ref0(equal)).star();

  Parser equal() =>
      (ref0(value) & string(' = ') & ref0(value)).map((value) => value);

  Parser parens() =>
      (char('(') & ref0(value) & char(')')).map((value) => value);

  Parser dotString() =>
      (anyOf('-_') | letter() | digit() | range(0x80,0x10FFF))
          .plus()
          .flatten();

  Parser path() => (char('.') & ref0(dotString)).map((value) => value);
}

我收到以下错误

Unhandled exception:
Stack Overflow
#0      ChoiceParser.parSEOn  package:petitparser/…/combinator/choice.dart:71
#1      PossessiveRepeatingParser.parSEOn  package:petitparser/…/repeater/possessive.dart:59
#2      FlattenParser.parSEOn  package:petitparser/…/action/flatten.dart:31
// Then these 4 lines repeat
#3      ChoiceParser.parSEOn  package:petitparser/…/combinator/choice.dart:69
#4      PossessiveRepeatingParser.parSEOn  package:petitparser/…/repeater/possessive.dart:67
#5      SequenceParser.parSEOn  package:petitparser/…/combinator/sequence.dart:39
#6      MapParser.parSEOn  package:petitparser/…/action/map.dart:38
// until it gets here
#9491   ChoiceParser.parSEOn  package:petitparser/…/combinator/choice.dart:69
#9492   PossessiveRepeatingParser.parSEOn  package:petitparser/…/repeater/possessive.dart:67
#9493   SequenceParser.parSEOn  package:petitparser/…/combinator/sequence.dart:39
#9494   PickParser.parSEOn  package:petitparser/…/action/pick.dart:26
#9495   CastParser.parSEOn  package:petitparser/…/action/cast.dart:17
#9496   Parser.parse  package:petitparser/…/core/parser.dart:51
#9497   main  fhir_path/also_main.dart:7
#9498   _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
#9499   _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

正如@lukas-renggli 所指出的,它似乎进入了一个无限循环。所以至少我认为这就是正在发生的事情。但我想我不明白它是如何匹配导致无限循环的。

解决方法

如果没有一个最小的、可重现的例子,很难说出发生了什么。但是,我怀疑 star-operator 中选择的解析器之一总是在不消耗任何东西的情况下成功(ref0(empty) 看起来很可疑)。这将导致无限循环。

例如,以下解析器显示了这种行为:

epsilon().star().parse('');   // loops forever

对更新问题的回答:您的语法是 equals 产生式中的 left-recursive。一个类似的、稍微简单一点的例子是:

// Loops forever: expression is recursively called without consuming anything.
Parser expression() => (ref0(expression) & char('+') & ref0(expression)) 
    | digit();`

// Fixes the infinite loop by forcing the grammar to consume something 
// at each step.
Parser expression() => digit().separatedBy(char('+'));

有多种方法可以修复您的示例,具体取决于您想要的确切行为。最简单的选择是重写语法以在其他选项之间使用相等作为分隔符:

Parser value() => (ref0(parens) | ref0(dotString) | ref0(path))
    .separatedBy(string(" = "));

我建议您查看 Expression Builder。它可以简化构建表达式解析器并避免常见的陷阱。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?