`ASSIGN` (`:=`) 在 `iec_bison.yy` 中的處理 - benchen2001/matiec GitHub Wiki
好的,我們來針對 iec_bison.yy 中 ASSIGN (:=) 符號的處理進行完整深入的探討與說明,並結合 average_st.txt 範例。
ASSIGN (:=) 在 iec_bison.yy 中的處理
ASSIGN 在 iec_bison.yy 中扮演著關鍵的語法角色,它標識了賦值語句的操作。以下是其處理過程的詳細說明:
1. 詞法定義 (%token)
- 宣告:在
iec_bison.yy的 Bison 宣告區,ASSIGN必須被定義為一個終端符號(token)。這通常看起來像這樣:%token ASSIGN /* Represents the ':=' operator */ - 來源:這個
ASSIGN標記是由詞法分析器(iec_flex.ll)在掃描到原始碼中的:=符號時產生的。iec_flex.ll會返回ASSIGN這個整數代碼給 Bison。
2. 語法規則 (Grammar Rules)
- 核心用途:
ASSIGN主要出現在定義賦值語句 (Assignment Statement) 的語法規則中。這是 ST 語言最基本的語句之一。 - 典型規則:一個典型的賦值語句規則如下所示:
assignment_statement: variable ASSIGN expression ';' { $$ = new_assignment_statement($1, $3); // Create AST node combine_locations($$, $1, $4); // Set location info } ; - 規則解析:
assignment_statement: 這是定義的非終端符號,代表一個完整的賦值語句。variable: 這是一個非終端符號,代表賦值操作的左側 (LHS)。它必須能夠解析為一個可以被賦值的目標(l-value),例如:- 簡單變數 (
symbolic_variable_c),如SUM。 - 陣列元素 (
array_variable_c),如arr[i]。 - 結構成員 (
structured_variable_c),如FIFO.XOUT。 - 直接地址變數 (
direct_variable_c),如%QX0.0。 (具體variable如何解析由其他規則定義)。
- 簡單變數 (
ASSIGN: 這是關鍵的終端符號,即詞法分析器返回的:=標記。它在語法上分隔了左側的目標變數和右側的表達式。expression: 這是一個非終端符號,代表賦值操作的右側 (RHS)。它可以是任何計算結果的有效表達式,例如:- 常數 (
constant_c)。 - 變數 (
symbolic_variable_c,structured_variable_c等)。 - 算術/邏輯/比較運算 (
add_expression_c,and_expression_c,gt_expression_c等)。 - 函式呼叫 (
function_invocation_c)。
- 常數 (
';': 分號終端符號,標記 ST 語句的結束。
3. 語法分析過程 (Shift/Reduce)
當 Bison 解析器遇到 ASSIGN 標記時:
- 移入 (Shift):通常,在解析了左側的
variable之後,如果下一個標記是ASSIGN,Bison 會將ASSIGN標記移入 (shift) 到其內部堆疊中,並轉換到下一個狀態,期望接下來能匹配一個expression。 - 歸約觸發 (Reduce Trigger):當 Bison 的堆疊頂部形成了
variable ASSIGN expression ;(或類似的匹配序列) 時,它就識別出這符合assignment_statement規則的右側。ASSIGN的存在是觸發這個歸約動作的關鍵條件之一。
4. 動作執行 (Action) 與 AST 構建
- 核心動作:在
assignment_statement規則的{...}動作塊中,主要工作是創建代表該賦值語句的 AST 節點。 - 創建節點:動作程式碼會呼叫
ast_build.cc中的輔助函數,通常是new_assignment_statement()。$$ = new_assignment_statement($1, $3);$1: 代表規則右側第一個符號 (variable) 的語義值,即指向 LHS 變數對應 AST 節點的指標 (symbol_c*)。$3: 代表規則右側第三個符號 (expression) 的語義值,即指向 RHS 表達式對應 AST 節點的指標 (symbol_c*)。$$: 代表規則左側非終端符號 (assignment_statement) 的語義值,它被設置為新創建的assignment_statement_c節點的指標。
ASSIGN的角色:請注意,ASSIGN(:=) 標記本身通常不會在 AST 中創建一個獨立的節點。它的語義(賦值操作)被隱含地表示在assignment_statement_c這個 AST 節點的結構中——該節點將 LHS 和 RHS 子節點關聯起來。ASSIGN在語法分析階段的主要作用是識別和驗證賦值語句的結構。- 位置資訊:動作通常還會計算新創建節點的源代碼位置,結合 LHS (
$1) 的起始位置和分號 ($4) 的結束位置。
5. 範例 (average_st.txt)
讓我們看看 SUM := SUM - FIFO.XOUT ; 這行程式碼的解析過程:
yylex()返回IDENTIFIER("SUM") -> 歸約為variable($1指向symbolic_variable_c("SUM"))。yylex()返回ASSIGN($2)。Bison 將其移入堆疊。yylex()返回IDENTIFIER("SUM"),SUB,IDENTIFIER("FIFO"),.,IDENTIFIER("XOUT") -> 經過一系列移入和歸約,最終形成expression($3指向sub_expression_c,其子節點分別是symbolic_variable_c("SUM")和structured_variable_c("FIFO.XOUT"))。yylex()返回;($4)。Bison 將其移入堆疊。- 歸約:此時堆疊頂部匹配
variable ASSIGN expression ;。 - 執行動作:
- 呼叫
new_assignment_statement($1, $3),其中$1是 LHS 的SUM節點,$3是 RHS 的SUM - FIFO.XOUT表達式樹。 - 返回一個新的
assignment_statement_c節點。 - 將
$$設置為這個新節點的指標。 - 設置新節點的位置資訊。
- 呼叫
- 壓棧:將代表
assignment_statement的狀態和其語義值 ($$) 壓回堆疊。
對於 average_st.txt 中的其他賦值語句,如 XOUT := SUM/N ; 或 SUM := N*XIN ;,處理流程完全相同,只是 $1 和 $3 指向的具體 AST 子樹不同。
六、總結
ASSIGN (:=) 在 iec_bison.yy 中:
- 是一個由
%token定義的終端符號。 - 是構成賦值語句語法規則的關鍵部分,用於分隔左側變數和右側表達式。
- 在語法分析過程中,它的出現是觸發
assignment_statement規則歸約的重要條件。 - 在 AST 構建時,其語義被
assignment_statement_c節點結構所體現,而ASSIGN標記本身通常不產生獨立的 AST 節點。
因此,ASSIGN 對於正確解析 ST 程式碼中的賦值操作至關重要,確保了程式碼的結構符合預期,並指導了相應 AST 節點的創建。