File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 5757變數宣告式 = "元"・"・"・變數・"="・算式
5858```
5959
60- 算式則較為複雜,敏銳的道友可能已經注意到,算式也蘊含了遞回, 。
60+ 算式則較為複雜,敏銳的道友可能已經注意到,算式也蘊含了遞回。
6161
6262``` 語法
63- 算式 = 運算元・運算子・運算元 | "("・算式・")"
64- 運算元 = 變數 | 數字 | 算式
63+ 算式 = 變數
64+ | 數字
65+ | "("・算式・")"
66+ | 算式・運算子・算式
6567運算子 = "+" | "−" | "*" | "/"
6668```
67- ` 算式 = 運算元 ・運算子・運算元 | "("・算式・")" ` 將 ` 算式 ` 定義為 ` 運算元・運算子・運算元 ` ,而在算式兩側加上括號後,依然是合法括號,也就是說,` 1+2 ` 是` 算式 ` ,而` (1+2) ` 、` ((1+2)) ` 、` (((1+2))) ` ...也都是合法算式。
69+ ` 算式 ` 可以只是一個變數或數字, ` 算式 ・運算子・算式 ` 表明 ` 算式 ` 也可以是加減乘除的結果, ` "("・算式・")" ` ,而在算式兩側加上括號後,依然是合法括號,也就是說,` 1+2 ` 是` 算式 ` ,而` (1+2) ` 、` ((1+2)) ` 、` (((1+2))) ` ...也都是合法算式, ` 0 ` 、 ` (0) ` 、 ` ((0)) ` 也都合法 。
6870
6971
7072思考題:有沒有辦法定義上下文無關語法,把同一層級的括號限制在一對,禁止` ((1+2)) ` 、` (((1+2))) ` 之無意義括號?
73+
74+ 為方便觀看,以下將音界咒零・一版全部語法定義寫在一起,並將其縮排:
75+
76+ ``` 語法
77+ 音界咒 = 句
78+ | 句・音界咒
79+
80+ 句 = 變數宣告式
81+ | 算式
82+
83+ 變數宣告式 = "元"・"・"・變數・"="・算式
84+
85+ 算式 = 變數
86+ | 數字
87+ | "("・算式・")"
88+ | 算式・運算子・算式
89+
90+ 運算子 = "+"
91+ | "−"
92+ | "*"
93+ | "/"
94+ ```
95+
96+ ## 語法歧義
97+ 前文寫出的語法定義,定義的是如何** 生成** 合乎語法的字串,而非如何將字串的語法** 剖析** 出來。
98+
99+ 這意思是說,當吾人想生成出所有(長度小於 n)的` 算式 ` 時,可以遍歷` 算式 ` 的兩個分支得到` 變數宣告式 ` 、` 算式 ` 兩種語法,這兩種語法又可以繼續分支下去,如此遞迴,便能得出所有(長度小於 n)的` 算式 ` 。
100+
101+ 但是在遞迴遍歷的過程中,不同路徑很可能會造出重複的句子。
102+
103+ 以` 1+2*3 ` 為例,其生成方式可能是` 算式 ` => ` 算式+算式 ` => ` 算式+算式*算式 ` ,先以` + ` 展開,接著展開後的第二個再以` * ` 展開,也可能是` 算式 ` => ` 算式*算式 ` => ` 算式+算式*算式 ` ,初始算式先以` * ` 展開,展開後的第二個算式再以` + ` 展開,如圖:
104+
105+ ![ 算式展開同結果] ( ../image/算式展開同結果.png )
106+
107+ 一種語法出現不同展開過程但同結果這種情況,該語法就是「有歧義的」,亦有人稱「模糊」、「模稜兩可」、「二義性」。
108+
109+ 歧義是一項不良性質,若對上圖中得到的兩棵語法樹做後序運算求值,所得將會不相同,一個是先乘除後加減,另個則是先加減後乘除。
110+
111+ 即使語法存在歧義,還是有辦法剖析的,舉個例子,透過回溯來得到所有可能的語法樹,再依照某種方式挑選,如此還是能用一套算法總是從一套源碼中得到相同的語法樹。
112+
113+ 遇到歧義與法時,也可以嘗試直接修原語法定義,寫出一套無歧義的語法。` 算式 ` 的例子可以透過額外增加` 乘除式 ` 、` 原子式 ` 兩層級來迫使先乘除後加減:
114+
115+ ```
116+ 算式 = 乘除式 | 乘除式・加減・乘除式
117+ 乘除式 = 原子式 | 原子式・乘除・原子式
118+ 原子式 = 數字
119+ | 變數
120+ | "("・算式・")"
121+ 乘除 = "*"
122+ | "/"
123+ 加減 = "+"
124+ | "−"
125+ ```
You can’t perform that action at this time.
0 commit comments