缩进是如何解析的

在解析之前,空格由词法分析器处理。

词法分析器使用堆栈来存储缩进级别。在开始时,堆栈只包含值 0,这是最左边的位置。每当嵌套块开始时,新的缩进级别被推入堆栈,并且 INDENT 标记被插入到令牌流中,该令牌流被传递给解析器。一行中永远不会有多个 INDENT 标记(IndentationError)。

当遇到具有较小缩进级别的行时,将从堆栈中弹出值,直到值在顶部,该值等于新缩进级别(如果未找到,则发生语法错误)。对于弹出的每个值,将生成 DEDENT 标记。显然,连续可能有多个 DEDENT 令牌。

词法分析器会跳过空行(仅包含空格和可能的注释),并且永远不会为它们生成 INDENTDEDENT 标记。

在源代码的末尾,为堆栈上剩下的每个缩进级别生成 DEDENT 标记,直到只剩下 0。

例如:

if foo:
    if bar:
        x = 42
else:
    print foo

分析如下:

<if> <foo> <:>                    [0]
<INDENT> <if> <bar> <:>           [0, 4]
<INDENT> <x> <=> <42>             [0, 4, 8]
<DEDENT> <DEDENT> <else> <:>      [0]
<INDENT> <print> <foo>            [0, 2]
<DEDENT> 

解析器将 INDENTDEDENT 标记作为块分隔符处理。