對 `absyntax_utils` 目錄的完整深入探討 - benchen2001/matiec GitHub Wiki
對 absyntax_utils 目錄的完整深入探討
absyntax_utils 目錄是 matiec 專案中極為重要的一部分,它提供了一系列輔助工具,用於處理和分析抽象語法樹(AST),從而支援編譯器的語意分析和程式碼生成階段。讓我們深入探討這個目錄的結構、核心元件和其在整個編譯過程中的角色。
一、目錄概述
absyntax_utils 目錄包含多個輔助工具類別,每個類別專注於特定的 AST 操作或分析任務。從檔案名稱可以看出,這些輔助工具大致可以分為幾個主要類別:
- 符號表管理與型別分析
- AST 遍歷與處理工具
- 變數與函式呼叫分析器
- 資料型別資訊抽取
二、核心文件詳解
1. absyntax_utils.cc/hh
這是目錄中最基礎的文件,提供了編譯器語意分析階段的基礎設施:
- 符號表初始化:建立並填充全域符號表(型別、函式、功能塊等)
- 識別字比較:提供了不區分大小寫的識別字比較功能
- AST 遍歷基礎:實現
populate_symtables_c類別,用於遍歷 AST 並填充符號表
2. get_datatype_info.cc/hh
這個文件負責處理與資料型別相關的資訊:
- 型別相容性檢查:判斷兩個資料型別是否相容
- 型別等級判定:判斷資料型別的等級(如整數、實數、布林值等)
- 型別轉換分析:分析是否可以進行隱式型別轉換
- 基本型別驗證:提供
is_type_valid、is_type_equal等函式來判斷型別的有效性與相等性
3. search_base_type.cc/hh
這個文件主要用於搜尋派生型別的基本型別:
- 基本型別搜尋:追蹤使用者自定義型別的基礎型別(如
MyInt: INT的基礎型別是INT) - 型別繼承鏈:處理多層型別定義的追蹤(如
A: B; B: C; C: INT的基礎型別仍是INT)
4. get_var_name.cc/hh
這個文件提供了從複雜變數表達式中抽取變數名稱的功能:
- 變數名稱提取:從各種變數結構(如陣列、結構體)中提取純變數名稱
- 變數路徑處理:處理如
a.b[3].c這樣的變數路徑
5. decompose_var_instance_name.cc/hh
負責分解變數實例名稱:
- 變數路徑分解:將如
fb1.fb2.var這樣的變數路徑分解成各部分 - 作用域解析:處理變數的作用域問題
6. search_fb_instance_decl.cc/hh 和 search_fb_typedecl.cc/hh
這兩個文件分別處理功能塊實例和型別宣告的搜尋:
- 功能塊實例搜尋:找到程式中功能塊的實例宣告
- 功能塊型別宣告搜尋:找到功能塊型別的宣告
7. 迭代器類別
目錄中包含多個迭代器類別,用於遍歷 AST 的特定部分:
- array_dimension_iterator.cc/hh:遍歷陣列維度
- function_call_iterator.cc/hh:遍歷函式呼叫
- function_call_param_iterator.cc/hh:遍歷函式呼叫參數
- function_param_iterator.cc/hh:遍歷函式參數
8. spec_init_separator.cc/hh
處理型別規格與初始值的分離:
- 型別/初始值分離:將如
INT := 5這樣的宣告分離成型別(INT)和初始值(5) - 輔助型別推斷:協助型別推導系統工作
9. type_initial_value.cc/hh
負責為各種型別提供預設的初始值:
- 型別初始值:為各種型別提供預設的初始值(如 INT 為 0,BOOL 為 FALSE 等)
- 複合型別初始化:處理陣列、結構體等複合型別的初始化
10. debug_ast.cc/hh
提供 AST 的除錯功能:
- AST 輸出:以人類可讀的格式輸出 AST
- 除錯輔助:協助開發者理解 AST 的結構
三、工作原理與流程
absyntax_utils 目錄中的工具在編譯過程中扮演著重要角色,尤其是在語意分析階段:
-
初始化階段:
- 呼叫
absyntax_utils_init初始化符號表 populate_symtables_c遍歷 AST,填充符號表
- 呼叫
-
型別檢查階段:
- 使用
get_datatype_info、search_base_type等工具進行型別相容性檢查 - 使用
spec_init_separator分析型別與初始值
- 使用
-
語意分析階段:
- 使用
decompose_var_instance_name分析變數路徑 - 使用
search_fb_instance_decl和search_fb_typedecl分析功能塊
- 使用
-
程式碼生成階段:
- 使用
get_sizeof_datatype計算型別大小 - 使用
type_initial_value生成型別的預設初始值
- 使用
四、簡單的例子:對 simple_spec_init 的處理
以你焦點中的 simple_spec_init 為例,它在 absyntax_utils.cc 中的處理流程是:
-
在
populate_symtables_c::visit(simple_type_declaration_c *symbol)中:type_symtable.insert(symbol->simple_type_name, symbol->simple_spec_init);這行程式碼將使用者定義的型別名稱與其對應的規格(型別+初始值)插入到型別符號表中。
-
接著,在語意分析階段,如果需要檢查型別相容性(例如
BOOL := 10),會使用:spec_init_separator將規格分離為型別和初始值get_datatype_info檢查型別與初始值的相容性
-
如果發現不相容(如
BOOL與10),就會透過print_datatypes_error報告錯誤。
五、總結
absyntax_utils 目錄提供了一套完整的 AST 分析與處理工具集,是 matiec 編譯器語意分析與程式碼生成階段的核心支援基礎設施。這些工具協同工作,確保 IEC 61131-3 程式的型別安全、語意正確性,並為程式碼生成準備必要的資訊。
對於處理 enable : BOOL := 10; 這樣的錯誤,正是這些工具的協作使得編譯器能夠檢測出型別不匹配的問題,並提供明確的錯誤訊息。