Я хочу проаналізувати визначені користувачем мови домену. Ці мови, як правило, близькі до математичних позначень (я не розбираю природну мову). Користувачі визначають свою DSL у позначенні BNF, наприклад:
expr ::= LiteralInteger
| ( expr )
| expr + expr
| expr * expr
Введення типу "подібне" 1 + ( 2 * 3 )
повинно бути прийнято, тоді як введення "подібне" 1 +
повинно бути відхилено як неправильне, а введення "подібне" 1 + 2 * 3
має бути відхилено як неоднозначне.
Основна складність тут - впоратися з неоднозначними граматиками зручним для користувача способом. Обмежувати граматику однозначною - це не варіант: саме така мова - ідея полягає в тому, що письменники вважають за краще опускати дужки, коли їм не потрібно уникати двозначності. Поки вираз не є неоднозначним, мені потрібно його розібрати, а якщо його немає, мені потрібно відкинути його.
Мій аналізатор повинен працювати над будь-якою безтекстовою граматикою, навіть неоднозначною, і повинен приймати всі однозначні дані. Мені потрібно дерево розбору для всіх прийнятих даних. Для неправдивого або неоднозначного введення я в ідеалі хочу хороших повідомлень про помилки, але для початку я візьму те, що можу отримати.
Я, як правило, посилаюсь на аналізатор на відносно коротких входах, з періодичними тривалими введеннями. Тож асимптотично швидший алгоритм може бути не найкращим вибором. Я хотів би оптимізувати розподіл приблизно 80% входів довжиною менше 20 символів, 19% від 20 до 50 символів та 1% рідкісних довгих входів. Швидкість недійсних входів не викликає особливих проблем. Крім того, я очікую зміни DSL приблизно кожні 1000 - 100000 входів; Я можу витратити пару секунд, переробляючи свою граматику, а не пару хвилин.
Який алгоритм розбору я повинен досліджувати, враховуючи мої типові вхідні розміри? Якщо повідомлення про помилки має бути фактором у моєму виборі, чи слід зосередитись на аналізі однозначних входів та, можливо, запустити повністю окремий, повільніший синтаксичний аналіз, щоб забезпечити зворотний зв'язок з помилками?
(У проекті, де мені це було потрібно (деякий час назад), я використовував CYK , який був не надто важким для реалізації та працював адекватно для моїх розмірів введення, але не створював дуже приємних помилок.)
x+y+z
.
+
, тому x+y+z
це дійсно неоднозначно, отже, помилково.