# 7.1 具象语法树生成器

具象语法树（CST），有时被称为**语法分析树（parse tree）**，是一种有序的有根树结构，其表示在上下文无关文法中的代码。

\*\*分词器（tokenizer）**和**解析器（parser）\*\*创建出 CST。你已经在“Python 语言和语法”章节中探索了解析器生成器。解析器生成器的输出是一张有限自动机（DFA）解析表，描述了上下文无关文法中的可能状态。

{% hint style="info" %}
**参见**

Python 的原作者 Guido van Rossum 开发了一种上下文有关文法，用于 CPython 3.9 中，作为 LL(1)文法的替代方案，LL(1) 文法是 CPython 以前版本的文法。新文法被称为**解析表达式文法（PEG）**。

PEG 解析器在 Python 3.9 中可用。Python 3.10 将完全删除旧的 LL(1) 文法。
{% endhint %}

在“Python 语言和语法”章节中，你已经探索了一些表达式类型，如：`if_stmt` 和 `with_stmt` 。具象语法树将语法符号（如：`if_stmt`）作为分支，而单词和终结符号作为叶子节点。

比如：将算术表达式 “a + 1” 转换成具象语法树，如下图所示：

<figure><img src="https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-426e48a85fe9b808917ca8accfc7970d6a44b782%2F%E5%9B%BE7.1.1%20a%2B1%E7%9A%84%E5%85%B7%E8%B1%A1%E8%AF%AD%E6%B3%95%E6%A0%91.png?alt=media" alt=""><figcaption></figcaption></figure>

算术运算符在这里用三个分支来表示：左分支、操作符分支和右分支。

解析器迭代来自输入流的单词符号，并与语法中的可能状态和单词符号匹配，以构建 CST。

在上面具象语法树中展示的所有符号都已经被定义在 `Grammar/Grammar` 文件中：

<figure><img src="https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-4a06250f1a355aef171cd6949bc34d0a8db85fba%2F%E5%9B%BE7.1.2%20%E7%AC%A6%E5%8F%B7%E5%AE%9A%E4%B9%89.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-5c3379d73e1fc9ab9ea67ca71c6137a835279987%2F%E5%9B%BE7.1.3%20%E7%AC%A6%E5%8F%B7%E5%AE%9A%E4%B9%892.png?alt=media" alt=""><figcaption></figcaption></figure>

而单词符号（token）被定义在 `Grammar/Tokens` 文件中：

<figure><img src="https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-fd826f24ffb6e0ee45b449a9d2c59a3b83123ae0%2F%E5%9B%BE7.1.4%20%E5%8D%95%E8%AF%8D%E7%AC%A6%E5%8F%B7%E5%AE%9A%E4%B9%89.png?alt=media" alt=""><figcaption></figcaption></figure>

`Name` 单词符号可以表示变量、函数、类或者是模块的名称。但 Python 的语法不支持 `NAME` 成为保留关键字之一，如：`await` 和 `async` 亦或者是数值及其他文字类型。

比如：你尝试定义一个为 1 的函数，Python 会抛出一个语法错误：

<figure><img src="https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-289f8fd1de887aaa9c944c209737911464df6eeb%2F%E5%9B%BE7.1.5%20%E8%AF%AD%E6%B3%95%E9%94%99%E8%AF%AF.png?alt=media" alt=""><figcaption></figcaption></figure>

`NUMBER` 是一种特殊的单词符号类型，可以表示 Python 许多数值之一。Python 有一个特殊的数值语法，包含以下可能的数值：

* 八进制值，如：0o20；
* 十六进制值，如：0x10；
* 二进制值，如：0b10000；
* 复数，如：10j；
* 浮点数，如：1.01；
* 下划线作为逗号，如：1\_000\_000。

你可以通过 Python 中的 `symbol` 和 `token` 模块看到编译的符号和单词。

<figure><img src="https://1029588898-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FJhewUmzI3BNeGgeFH9Rv%2Fuploads%2Fgit-blob-b973f473bb33dbda6ddf7acc655f16ea72e2db0c%2F%E5%9B%BE7.1.6%20%E5%9C%A8Python%E4%B8%AD%E4%BD%BF%E7%94%A8symbol%E5%92%8Ctoken.png?alt=media" alt=""><figcaption></figcaption></figure>
