2016-02-22 3 views
0

У меня проблема с двусмысленным анализом в insta. Вот грамматика:Неопределенность Instaparse в 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

Грамматики предназначены для анализа структурированных данных. Если вы возьмете разумную грамматику в противном случае и бросите в нее правило «любого старого мусора», вы получите множество анализов, связанных с любым старым барахлом. Способ устранения двусмысленности заключается в том, чтобы быть более строгим в отношении того, что квалифицируется в вашем правиле «ничего», или, еще лучше, полностью удалить его и вместо этого фактически анализировать материал, который идет туда.

0

Один из вариантов - настроить правильное выражение для «ничего», чтобы разрешить любой символ кроме #. Таким образом, он только съедает текст до следующего символа #.

Другой вариант - настроить правильное выражение для «ничего», чтобы не допускать # в качестве первого символа и не допускать символ новой строки как любой символ. Также, вероятно, вы захотите изменить текстовый блок на (ничего | eol) *. Таким образом, в этом случае «все» будет доходить до символа новой строки, в основном позволяя текстовому блоку обрабатывать текст по одной строке за раз. Когда вы нажмете строку, начинающуюся с символа #, она не будет подхвачена «чем угодно», но вместо этого будет использована другие правила.

Это действительно зависит от поведения, которое вы хотите, но это некоторые стратегии для более точного описания вашего «чего-либо».

Смежные вопросы