iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
Software Development

離塵指引.卷之一.試結丹:程式語言自舉系列 第 26

音界咒零.二版再遇分詞(二)視關鍵字為特殊識別子

  • 分享至 

  • xImage
  •  

把狀態機完整畫完,再在零.一版的分詞器源碼的基礎上依狀態機畫葫蘆即可寫出分詞器。

先將關鍵字當識別子

但若真的把整套狀態機畫出來,會發現頗為繁雜,關鍵字會製造出許多狀態,其每個狀態會都隨時會轉換成識別子。這昭示關鍵字與識別子的關係十分接近。不妨先將關鍵字當識別子,等識別子被斷詞後,再一次性判定該識別子的內容是否是某個關鍵字。

如此狀態機會簡單得多:

零・二版分詞狀態機簡化

實作

零.二版開始有 2 字的特殊符號,但這不難處理,只要往前多看一個字元就能判斷:

fn 起點態(&mut self) -> Option<O詞> {
    let 字 = self.字流.pop_front()?;
    match 字 {
        '+' => Some(O詞::運算子(O運算子::加)),
        '-' => Some(O詞::運算子(O運算子::減)),
        '*' => Some(O詞::運算子(O運算子::乘)),
        '/' => Some(O詞::運算子(O運算子::除)),
        '%' => Some(O詞::運算子(O運算子::餘)),
        '=' => match self.字流.front() {
            Some('=') => {
                self.字流.pop_front()?;
                Some(O詞::運算子(O運算子::等於))
            }
            _ => Some(O詞::賦值),
        },
        '!' => match self.字流.front() {
            Some('=') => {
                self.字流.pop_front()?;
                Some(O詞::運算子(O運算子::異於))
            }
            _ => panic!("!後必接="),
        },
        '<' => match self.字流.front() {
            Some('=') => {
                self.字流.pop_front()?;
                Some(O詞::運算子(O運算子::小於等於))
            }
            _ => Some(O詞::運算子(O運算子::小於)),
        },
        '>' => match self.字流.front() {
            Some('=') => {
                self.字流.pop_front()?;
                Some(O詞::運算子(O運算子::大於等於))
            }
            _ => Some(O詞::運算子(O運算子::大於)),
        },
        '(' => Some(O詞::左圓括號),
        ')' => Some(O詞::右圓括號),
        '【' => Some(O詞::左基括號),
        '】' => Some(O詞::右基括號),
        '.' => Some(O詞::音界),
        '、' => Some(O詞::頓號),
        '\n' => Some(O詞::換行),
        '\t' | ' ' | ' ' => Some(O詞::空白),
        '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0' => {
            self.數字態(字.to_string())
        }
        _ => self.識別子態(字.to_string()),
    }
}

數字態實作維持不變,識別子態會在斷詞完成時判定是否是關鍵字:

fn 識別子態(&mut self, mut 前綴: String) -> Option<O詞> {
    let 字 = self.字流.front()?;
    match 字類(字) {
        O字類::數字 | O字類::其他 => {
            前綴.push(self.字流.pop_front()?);
            self.識別子態(前綴)
        }
        O字類::特殊符號 => {
            // 遇到特殊符號,識別子截止
            // 判定是否是關鍵字
            match 前綴.as_str() {
                "元" => Some(O詞::元),
                "術" => Some(O詞::術),
                "歸" => Some(O詞::歸),
                "若" => Some(O詞::若),
                "或若" => Some(O詞::或若),
                "不然" => Some(O詞::不然),
                _ => Some(O詞::識別子(前綴)),
            }
        }
    }
}

上一篇
音界咒零.二版再遇分詞(一)狀態機
下一篇
音界咒零.二版再遇剖析(一)調車場算法
系列文
離塵指引.卷之一.試結丹:程式語言自舉31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言