语言语法的 BNF 示例,其中缩进级别定义了一个块?

hum*_*ace 5 python indentation bnf ebnf

我尝试通过使用称为扩展 Backus-Naur-Form EBNF ( BNFmenuentries.conf )的符号描述语法/语法来记录我在 中使用的语法,这是菜单项的配置文件。此 menuentries.conf 使用缩进级别作为语法组件如本例中所示:

menu_entry_1
menu_entry_2
    menu_entry_2_submenu_entry_1
    menu_entry_2_submenu_entry_2
        menu_entry_2_submenu_entry_2_subsubmenu_1
        menu_entry_2_submenu_entry_2_subsubmenu_2
    menu_entry_2_submenu_entry_3
menu_entry_3
    menu_entry_3_submenu_entry_1
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,每个条目都由一个字符串表示,为了示例的目的,该字符串暗示/指示其位置。此外,示例应遵循以下规则

  • 每个菜单项都由单行表示(因此菜单项由换行符分隔)
  • 没有任何缩进的菜单项是“顶级”菜单项
  • 带有缩进的菜单条目不是“顶层”,而是相应更高/上层菜单条目的子条目。

我尝试提供 BNF 的方法如下:

换行符 := '\n'
缩进 := ' '
menu_entry_string := ('a'|'b'|....|'z'|'_'|'0'|'1'|...|'9')+
菜单条目 := 菜单条目 (NEWLINE 菜单条目)*
menu_entry := menu_entry_string (换行缩进 menu_entry)*
submenu_entry := 缩进 menu_entry_string
subsubmenu_entry := 缩进 缩进 menu_entry_string

因此,我的问题是关于我对递归声明的概念menu_entry及其与submenu_entryand的冗余的不满subsubmenu_entry
知道Python也使用缩进来创建块的概念,我想查找Python语法的BNF/定义(如下所示: https: //docs.python.org/3/reference/grammar.html)但是它留下了语法中INDENTDEDENT语法之外的相关概念。

因此,我的问题是: 如何正确使用 EBNF 来描述使用缩进作为分组块的语法/语法? 理想情况下,一个小例子(或者如果可能的话纠正我的尝试)将不胜感激。

在最好的情况下,EBNF 将定义 的概念nesting-levelblock1 表示 submenu_entry,2 表示 subsubmenu_entry ....

小智 4

当你需要语言创造者的思维时,你可能会用程序员的思维来思考。传统上创建语言有两个部分:

  1. 词位规范:定义表示单个语法结构(即标记或终端值)的字符组
  2. 语法规范:定义语法结构/标记/终结值的有效组合,这些组合构成了表达语言如何使用的非终结值

有些语言能够结合语言创建的词汇和句法部分,但在您的情况下这样做并不是一个好主意,因为语法本身无法单独表达特定缩进的想法。这是你留给词法分析器处理的事情。

下面是 BNF 语法,其中STRINGNEWLINEINDENTDEDENT都是词法分析器生成的终端值:

start ::= list
        | list NEWLINE
        .

list  ::= entry
        | list entry
        .

entry ::= STRING NEWLINE
        | STRING NEWLINE INDENT list DEDENT
        .
Run Code Online (Sandbox Code Playgroud)

很简单,对吧?我添加了start规则以确保任何以 NEWLINEDEDENT标记结尾的文件都是有效的。如果没有它,以令牌结尾NEWLINE且前面没有STRING令牌的文件将无效。

我使用了 BNF,但如果您愿意,也可以轻松使用 EBNF。关键是词法分析器可以理解使用多少个缩进空间来生成INDENTorDEDENT标记(或必要时生成错误),并且您的语法应该简单地指定如何使用生成的标记。