Я хотел бы попросить совета по использованию petitparser (я обновляю этот вопрос). Существует основанная на json грамматика под названием FHIRPath, которую я пытаюсь воссоздать в dart. Я новичок в подобных грамматиках, поэтому мне потребовалось некоторое время, чтобы понять, что я хочу, чтобы он делал (или что, по моему мнению, я хочу, чтобы он делал). Мне удалось заставить его анализировать пути 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, кажется, что это входит в бесконечный цикл. Так что, по крайней мере, я думаю, что это то, что происходит. Но я не думаю, что понимаю, как это соответствие вызывает бесконечный цикл.