Неопределенная двусмысленность в Clojure
У меня проблема с неоднозначным разбором в инсте. Вот грамматика:
(def yip-shape
(insta/parser
(str/join "\n"
["S = ( list-item | heading | text-block )*"
;; lists and that
"list-item = list-level <ws> anything"
"list-level = #' {0,3}\\*'"
;; headings
"heading = heading-level <ws> ( heading-keyword <ws> )? ( heading-date <ws> )? anything <eol?>"
"heading-level = #'#{1,6}'"
"heading-date = <'<'> #'[\\d-:]+' <'>'>"
"heading-keyword = 'TODO' | 'DONE'"
"text-block = anything*"
"anything = #'.+'"
"<eol> = '\\r'? '\\n'"
"<ws> = #'\\s+'"])))
Проблема с заголовком, как ## TODO Done
- Я могу понять, почему существует двусмысленность, я просто не уверен в том, как лучше ее решить. НАПРИМЕР
(insta/parses yip-shape "## TODO Done.")
Производит:
([:S [:text-block [:anything "## TODO Done."]]]
[:S [:heading [:heading-level "##"] [:anything "TODO Done."]]]
[:S [:heading [:heading-level "##"] [:heading-keyword "TODO"] [:anything "Done."]]])
Последний из которых - результат, который я ищу. Как лучше всего устранить двусмысленность и сузить результат до последнего в этом списке?
2 ответа
Грамматики предназначены для анализа структурированных данных. Если вы возьмете в противном случае разумную грамматику и добавите в нее правило "любой старый мусор", вы получите много разборов, которые включают любой старый мусор. Способ устранения неоднозначности состоит в том, чтобы быть более строгим в отношении того, что квалифицируется в вашем правиле "что угодно", или, еще лучше, полностью удалить его и вместо этого фактически проанализировать то, что там происходит.
Один из вариантов - настроить регулярное выражение на "что угодно", чтобы разрешить любой символ, кроме #. Таким образом, он только ест текст до следующего # символа.
Другой вариант - настроить регулярное выражение для "всего", чтобы не допустить использование символа # в качестве первого символа, и запретить символ новой строки в качестве любого символа. Также вероятно хотел бы изменить текстовый блок, чтобы быть (что угодно | eol)*. Таким образом, в этом случае "что-нибудь" будет полностью заполнено символом новой строки, что позволит текстовому блоку обрабатывать текст по одной строке за раз. Когда вы попадете в строку, начинающуюся с #, она не будет воспринята "чем-нибудь", но вместо этого будет выбрана другими правилами.
Это действительно зависит от поведения, которое вы хотите, но вот некоторые стратегии для того, чтобы сделать ваше описание "чего-либо" более точным.