> For the complete documentation index, see [llms.txt](https://koshizuow.gitbook.io/compilerbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://koshizuow.gitbook.io/compilerbook/calculator_level_language/recursive_descendent_parsing/recursive_production_rule.md).

# 包含遞迴的生成規則

寫遞迴的文法在生成文法中也是稀鬆平常的事。底下是在四則運算加上代表優先順序的括號的文法生成規則：

```
expr = mul ("+" mul | "-"
 mul)*
mul  = term ("*" term | "/" term)*
term = num | "(" expr ")"
```

上述的文法和之前的文法的差異，在於以前我們放`num`的位置被`term`，也就是`num`或是 `"(" expr ")"`取代了。也就是說，在新的文法中，被包含在小括號中的式子和至今為止的單一數值是同等的「結合方式」。我們用一個範例來看。

底下是`1*2`的語法樹：

![1\*2的語法樹](https://416395721-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjokrNdcE1H2E8hE2Dc%2F-LnM7l3T2hivlH6PcsQL%2F-LnM6DyPDO8v2LptUeTJ%2Findex.svg?alt=media\&token=9cfc7e32-4df0-4daa-9445-d52971f2fa7f)

接下來的樹是`1*(2+3)`的語法樹：

![1\*(2+3)的語法樹](https://416395721-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LjokrNdcE1H2E8hE2Dc%2F-LnM7l3T2hivlH6PcsQL%2F-LnM6SshMeSMJTQ3GKf8%2Findex.svg?alt=media\&token=fec6f4b3-2d51-40a2-b14d-ff3cc722e3dd)

比較兩個樹，會發現只有`mul`的右子樹的`term`展開是不一樣的。樹裡充份表現了在樹展開的最尾端出現的`term`，可以展開為一個數值，也可以展開成被括號包住的任意式子的這條規則。像這樣，把括號的優先順序用很簡單的生成規則來表示，是不是覺得有點感動呢？
