對 `absyntax_utils` 目錄的完整深入探討 - benchen2001/matiec GitHub Wiki

absyntax_utils 目錄的完整深入探討

absyntax_utils 目錄是 matiec 專案中極為重要的一部分,它提供了一系列輔助工具,用於處理和分析抽象語法樹(AST),從而支援編譯器的語意分析和程式碼生成階段。讓我們深入探討這個目錄的結構、核心元件和其在整個編譯過程中的角色。

一、目錄概述

absyntax_utils 目錄包含多個輔助工具類別,每個類別專注於特定的 AST 操作或分析任務。從檔案名稱可以看出,這些輔助工具大致可以分為幾個主要類別:

  1. 符號表管理與型別分析
  2. AST 遍歷與處理工具
  3. 變數與函式呼叫分析器
  4. 資料型別資訊抽取

二、核心文件詳解

1. absyntax_utils.cc/hh

這是目錄中最基礎的文件,提供了編譯器語意分析階段的基礎設施:

  • 符號表初始化:建立並填充全域符號表(型別、函式、功能塊等)
  • 識別字比較:提供了不區分大小寫的識別字比較功能
  • AST 遍歷基礎:實現 populate_symtables_c 類別,用於遍歷 AST 並填充符號表

2. get_datatype_info.cc/hh

這個文件負責處理與資料型別相關的資訊:

  • 型別相容性檢查:判斷兩個資料型別是否相容
  • 型別等級判定:判斷資料型別的等級(如整數、實數、布林值等)
  • 型別轉換分析:分析是否可以進行隱式型別轉換
  • 基本型別驗證:提供 is_type_validis_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 目錄中的工具在編譯過程中扮演著重要角色,尤其是在語意分析階段:

  1. 初始化階段

    • 呼叫 absyntax_utils_init 初始化符號表
    • populate_symtables_c 遍歷 AST,填充符號表
  2. 型別檢查階段

    • 使用 get_datatype_infosearch_base_type 等工具進行型別相容性檢查
    • 使用 spec_init_separator 分析型別與初始值
  3. 語意分析階段

    • 使用 decompose_var_instance_name 分析變數路徑
    • 使用 search_fb_instance_declsearch_fb_typedecl 分析功能塊
  4. 程式碼生成階段

    • 使用 get_sizeof_datatype 計算型別大小
    • 使用 type_initial_value 生成型別的預設初始值

四、簡單的例子:對 simple_spec_init 的處理

以你焦點中的 simple_spec_init 為例,它在 absyntax_utils.cc 中的處理流程是:

  1. populate_symtables_c::visit(simple_type_declaration_c *symbol) 中:

    type_symtable.insert(symbol->simple_type_name, symbol->simple_spec_init);
    

    這行程式碼將使用者定義的型別名稱與其對應的規格(型別+初始值)插入到型別符號表中。

  2. 接著,在語意分析階段,如果需要檢查型別相容性(例如 BOOL := 10),會使用:

    • spec_init_separator 將規格分離為型別和初始值
    • get_datatype_info 檢查型別與初始值的相容性
  3. 如果發現不相容(如 BOOL10),就會透過 print_datatypes_error 報告錯誤。

五、總結

absyntax_utils 目錄提供了一套完整的 AST 分析與處理工具集,是 matiec 編譯器語意分析與程式碼生成階段的核心支援基礎設施。這些工具協同工作,確保 IEC 61131-3 程式的型別安全、語意正確性,並為程式碼生成準備必要的資訊。

對於處理 enable : BOOL := 10; 這樣的錯誤,正是這些工具的協作使得編譯器能夠檢測出型別不匹配的問題,並提供明確的錯誤訊息。