您可以使用一点技巧来解析缩进敏感的语言(如 Python 或 Haskell),这在 Python 语言参考的词法分析一章中有详细描述。如前所述,词法分析器将前导空格转换为INDENT
和DEDENT
标记 [注 1],然后以简单的方式在 Python 语法中使用它们。这是一个小摘录:
suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement ::= stmt_list NEWLINE | compound_stmt
stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
while_stmt ::= "while" expression ":" suite ["else" ":" suite]
因此,如果您准备描述(或参考)词法分析算法,BNF 很简单。
但是,您实际上不能将该算法编写为上下文无关文法,因为它不是上下文无关的。(我将省略证明,但它类似于非上下文无关的证明,你可以在大多数基本的正式语言教科书和整个互联网上找到它。)anbncn
ISO 标准 EBNF(提供免费 PDF)提供了一种包含“用户可能需要的扩展”的方法: a Special-sequence
,这是任何不包含?两边由 a 包围的文本的文本?。因此,您可以通过包含 [注 2] 来滥用该符号:
DEDENT = ? See section 2.1.8 of https://docs.python.org/3.3/reference/ ? ;
或者您可以插入算法的完整描述。当然,这些技术都不允许解析器生成器生成准确的词法分析器,但它是向人类读者传达意图的合理方式。
值得注意的是,EBNF 本身使用一个特殊的序列来定义它的一个产生式:
(* see 4.7 *) syntactic exception
= ? a syntactic-factor that could be replaced
by a syntactic-factor containing no
meta-identifiers
? ;
笔记
词法分析器还将一些物理换行符转换为NEWLINE
标记,同时使其他换行符消失。
EBNF 通常使用语法=
而不是::=
产生式,并坚持以 . 结尾;
。注释包含在(*
和之间*)
。