Parsing Clojure中的语法歧义

Parsing Clojure中的语法歧义,parsing,clojure,ebnf,instaparse,Parsing,Clojure,Ebnf,Instaparse,我在insta中遇到了一个模棱两可的解析问题。语法如下: (def yip-shape (insta/parser (str/join "\n" ["S = ( list-item | heading | text-block )*" ;; lists and that "list-item = list-level <ws> anything" "list-le

我在insta中遇到了一个模棱两可的解析问题。语法如下:

(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+'"])))
产生:

([:S [:text-block [:anything "## TODO Done."]]] 
 [:S [:heading [:heading-level "##"] [:anything "TODO Done."]]] 
 [:S [:heading [:heading-level "##"] [:heading-keyword "TODO"] [:anything "Done."]]])

最后一个是我想要的结果。如何最好地消除歧义并将结果缩小到列表中的最后一个?

语法用于解析结构化数据。如果你使用一个合理的语法,并在其中加入一个“任何旧垃圾”规则,你会得到很多涉及任何旧垃圾的解析。解决歧义的方法是对“anywhere”规则中的限定条件更加严格,或者更好的做法是完全删除它,而是实际解析其中的内容。

一个选项是将正则表达式调整为“anywhere”,以允许除#之外的任何字符。这样,它只会在下一个字符之前吃掉文本

另一个选项是调整正则表达式中的“anything”,使其不允许将#作为第一个字符,也不允许将换行符作为任何字符。还可能希望将textblock更改为(任何| eol)*。因此,在这种情况下,“任何东西”都会吃掉换行符,基本上允许textblock一次处理一行文本。当你击中一条以#开头的线时,它不会被“任何东西”拾取,而是会被其他规则拾取

这确实取决于你想要的行为,但这些是一些策略,可以让你对“任何事情”的描述更精确

([:S [:text-block [:anything "## TODO Done."]]] 
 [:S [:heading [:heading-level "##"] [:anything "TODO Done."]]] 
 [:S [:heading [:heading-level "##"] [:heading-keyword "TODO"] [:anything "Done."]]])