Почему *any* не возвращается в этом примере?
Я пытаюсь понять, почему в следующем примере я не получаю совпадение на f2. Сравните это с f1, который успешно, как и ожидалось.
импорт 'package: petitparser / petitparser.dart'; импорт 'package: petitparser / debug.dart';
main() {
showIt(p, s, [tag = '']) {
var result = p.parse(s);
print('''($tag): $result ${result.message}, ${result.position} in:
$s
123456789123456789
''');
}
final id = letter() & word().star();
final f1 = id & char('(') & letter().star() & char(')');
final f2 = id & char('(') & any().star() & char(')');
showIt(f1, 'foo(a)', 'as expected');
showIt(f2, 'foo(a)', 'why any not matching a?');
final re1 = new RegExp(r'[a-zA-Z]\w*\(\w*\)');
final re2 = new RegExp(r'[a-zA-Z]\w*\(.*\)');
print('foo(a)'.contains(re1));
print('foo(a)'.contains(re2));
}
Выход:
(as expected): Success[1:7]: [f, [o, o], (, [a], )] null, 6 in:
foo(a)
123456789123456789
(why any not matching a?): Failure[1:7]: ")" expected ")" expected, 6 in:
foo(a)
123456789123456789
true
true
Я почти уверен, что причина кроется в том факте, что что- либо соответствует закрытию. Но когда он ищет закрывающуюся часть и не может ее найти, разве не так?
- вернуть последний символ
- предположим, что any().star() преуспел только с 'a'
- принять окончательный вариант и добиться успеха
Также в отличие от этого я показываю аналогичные регулярные выражения, которые делают это.
1 ответ
Как вы правильно проанализировали, анализатор any в вашем примере использует закрывающую скобку. А звездный парсер, обертывающий любой парсер, жадно потребляет как можно больше входных данных.
Возврат, как вы описываете, не выполняется автоматически PEG (синтаксический анализ выражений грамматики). Только заказанный выбор возвращается автоматически.
Чтобы исправить ваш пример, есть несколько возможностей. Наиболее прямолинейным является то, что нельзя сопоставлять закрывающую скобку:
id & char('(') & char(')').neg().star() & char(')')
или же
id & char('(') & pattern('^)').star() & char(')')
В качестве альтернативы вы можете использовать оператор starLazy. Его реализация использует операторы звездочки и упорядоченного выбора. Объяснение можно найти здесь.
id & char('(') & any().starLazy(char(')')) & char(')')