EBNF中的大纲模式

时间:2013-12-21 08:04:57

标签: parsing clojure ebnf

我正在尝试使用instaparse库为org模式文件编写解析器。该库采用EBNF表示法并将其转换为解析函数。组织模式文件使用以星号开头的行来制作大纲标题,其中星号设置大纲树中的级别,如下所示

* Headline
** Sub headline1
** Sub headline2

我的第一个尝试是将所有标题放在结果树中的同一级别:

(def outline
  (insta/parser
   "<S> = Headline-node *
    Headline-node =  Level <' '> Headline
    Level = #'^\\*+'
    Headline = #'\\S'+ <'\n'>"))
(outline "* Headline\n** Subheadline\n")
;=>
([:Headline-node [:Level "*"] [:Headline "H" "e" "a" "d" "l" "i" "n" "e"]] 
 [:Headline-node [:Level "**"] [:Headline "S" "u" "b" "h" "e" "a" "d" "l" "i" "n" "e"]])

也许我可以在之后对树进行转换,将标题放在头条新闻中。但我更喜欢从一开始就在标题内创建一个带有子标题的树。到目前为止,我唯一的想法是手动创建不同的级别:

(def outline
  (insta/parser
   "<S> = Headline-node1 *
    Headline-node1 =  <#'^\\* '> Headline (Headline-node2)*
    Headline-node2 =  <#'^\\*\\* '> Headline
    Headline = #'\\S'+ <'\n'>"))
(outline "* Headline\n** Subheadline\n")
;=>
([:Headline-node1 [:Headline "H" "e" "a" "d" "l" "i" "n" "e"] 
                  [:Headline-node2 [:Headline "S" "u" "b" "h" "e" "a" "d" "l" "i" "n" "e"]]])

但我想创建无限级别的头条新闻。有没有办法在EBNF中传达这一点?

1 个答案:

答案 0 :(得分:1)

我认为这是不可能的。下推式自动机可以准确识别无上下文的语言。但请考虑下推自动机如何操作以确定示例中标题的级别。

下推自动机具有一组有限的状态。因此,如果我们要允许几乎很深的水平,它就不能使用状态来跟踪航向的水平。所以它必须使用它的堆栈。使用堆栈计数的唯一方法是每次读取*时推送堆栈符号(也有有限数量的堆栈符号)。假设它位于某些*开头的输入字符串中的某个位置。它通过推送每*的堆栈符号来继续。但是当涉及输入字符串中* s的结尾时,自动机可以用来决定其动作的唯一内容是:输入字符串中的符号,其状态以及堆栈中的顶部符号。我们已经&#34;知道输入符号不是*,所以这没有帮助。我们知道堆栈的顶部是我们为每*推送一次的符号,所以这也无济于事。如前所述,状态集是有限的,因此我们不能以某种方式使用状态来计算堆栈上的符号数。