自頂向下的實現方式之一遞迴下降的語法分析

2021-09-29 04:38:32 字數 1902 閱讀 3244

前面已經說過了自頂向下的語法分析是什麼,這篇部落格,聊一下用遞迴的方式實現自頂向下的語法分析。

先給出偽**:

a()else if(xi是乙個終結符號 && xi與掃瞄指標指向的字元相同)else

}

}

這個函式就表示了非終結符號a的最左推導過程,但是這段偽**還沒有完善,但是大致的框架已經搭建了起來。

修改一開始給出的偽**:

a()else if(xi是乙個終結符號 && xi與掃瞄指標指向的字元相同)

}//回溯的位置在這裡,如果不符合要求,則試探下乙個產生式

inputbufferptr = ptr;

}}

× 語法錯誤,因為要進行回溯,所以對於每一次產生式選擇錯誤的情況,都不能認為是語法錯誤,需要試探完所有的產生式,如果還是沒有合適的產生式,則返回上一層,上一層試探下乙個產生式,就這樣一層一層的回溯,直到開始符號的所有產生式也試探完畢,但是還是沒有找到產生式,這才會報語法錯誤。

x 回溯的時機,在**回溯?首先要明白,回溯需要幹什麼?要進行試探多次時,每一次試探的初始條件是一樣的,所以,每一次試探之前,要恢復到初始條件。也就是在「換產生式」的時候,恢復初始條件。什麼時候「換產生式」?判定乙個產生式不合適的時候,換下乙個產生式。也就是說,在換產生的時候,恢復初始條件,也就是掃瞄指標的位置。

再次修改偽**:

boolean a()

}else if(xi是乙個終結符號 && xi與掃瞄指標指向的字元相同)else

}if(flag == true)

//回溯的位置在這裡,如果不符合要求,則試探下乙個產生式

inputbufferptr = ptr;

}retun false;

}

解釋上述**:

使用flag來記錄a的乙個產生式是否合適。什麼是合適的產生式?經過推導之後,可以得到乙個匹配的短語。在**層面來說,對於產生式右部的所有xi,如果xi是非終結符號,呼叫xi()返回true;如果xi是終結符號,則與掃瞄指標指向的符號相同。flag就是起到乙個記錄的作用。如果整個產生式的右部被分析完,flag==true,則說明這條產生式是合適的,就返回上一層,繼續推導下乙個符號。

關於如下文法的遞迴向下分析法的實現 圖1

點這裡檢視示例**

在示例中,沒有使用迴圈,而是選擇了將迴圈展開;而且**的結構也發生了一些變化,對於產生式右部,也沒有使用乙個乙個的判斷,而是根據產生式結構直接展開,通過短路運算進行控制,如果結果為false,直接就跳出來了,效果和迴圈中使用break是相同的。

不推薦使用,需要回溯,效率不高,而且需要試探所有的產生式,最後將結果返回到開始符號對應的函式,如果語法出現錯誤,想要糾錯是很困難的

關於**分析法,一般會使用非遞迴的方式,所以這裡僅做乙個介紹。

「**分析」,就是對於每一步的推導,都確定的使用乙個產生式,當然,這需要在之前做一些工作,就是計算乙個**分析表,這個表給出了當前推導的終結符號需要使用哪乙個產生式。

接下來給乙個例子,用於簡單描述**分析法。

使用語法分析程式,判斷乙個括號序列是否配對。

首先,給出括號序列的文法:

g[s]:

s→(s)s|ε

怎麼**分析呢?很簡單,如果當前要匹配的符號是「(」,那一定使用了產生式「(s)s」,否則,使用產生式「ε」

核心偽**:這段**很粗糙

s()

else

使用ε產生式

}

檢視示例**點這裡

這樣的方式不用進行回溯,效率要高很多,而且掃瞄指標會停留在出錯的地方,所以,如果掃瞄指標沒有掃瞄到最後,就是有語法錯誤,最後,給出出錯的位置,也就是掃瞄指標的下標即可。

(原創)自頂向下分析法 遞迴下降分析程式構造

題目 自頂向下分析法 遞迴下降分析程式構造 開發環境 vc6.0 include include 全域性變數 char exp 30 gra 30 prod 30 chexp int expsize 0,grasize 0,step 0 函式宣告 1 e tg 2 g tg tg 3 t fs 4 ...

編譯原理 自頂向下的遞迴下降語法分析器 解析

任務 給定乙個算術表示式的無關文法,實現乙個語法分析器 分析 根據乙個上下文無關語法生成乙個遞迴下降的語法分析器需要注意幾個方面 思路 步驟 1.觀察給定語法,如果遇到左遞迴,則需要改寫語法來消除左遞迴 2.根據給定的語法,生成相應符號的first集和fllow集 3.依照first集和fllow集...

自頂向下分析乙個簡單的語音識別系統(二)

上回咱們說到專案的目錄以及各個檔案的作用,這回我們自頂向下開始分析該專案。專案開始於tf train ctc.py檔案。如下圖所示 if name main import click use click to parse command line arguments click.command cl...