Bison中百分號的作用

Gold_stein發表於2024-10-27

Bison中百分號的作用

檔案開頭

在 Bison 中,百分號 % 是用於宣告和指示 Bison 解析器行為的符號。你提到的程式碼片段中的 %code requires%{ %} 是 Bison 特定的語法標記,用來包含 C++ 程式碼或指示特定的行為。

1. %code requires {}

  • 作用:用於宣告在解析器生成前必須包含的程式碼,通常是標頭檔案的引用或前置宣告。這部分程式碼會被放置在 Bison 自動生成的標頭檔案中,確保其他檔案或模組在包含這個標頭檔案時也能獲得這些定義。
  • 你程式碼中的例子
    %code requires {
      #include <memory>
      #include <string>
      #include "BaseAST.hpp"
    }
    
    這部分程式碼將被放入到生成的標頭檔案中,以便在解析器生成和編譯時可以直接訪問 std::stringstd::unique_ptr 以及你定義的 BaseAST 類。

2. %{ %}(C 程式碼塊)

  • 作用:用於包含需要嵌入在生成的解析器中的 C/C++ 程式碼。這部分程式碼通常被插入到生成的 .c.cpp 檔案的最前面,常見用途是定義輔助函式、宣告全域性變數、引入所需的標頭檔案等。
  • 你程式碼中的例子
    %{
    #include <iostream>
    #include <memory>
    #include <string>
    #include <vector>
    #include "BaseAST.hpp"
    
    // 宣告 lexer 函式和錯誤處理函式
    int yylex();
    void yyerror(std::unique_ptr<BaseAST> &ast, const char *s);
    
    using namespace std;
    %}
    
    這部分程式碼將被直接插入到生成的解析器的 .cpp 檔案中,確保解析器可以訪問這些庫和函式(如 yylexyyerror)。

3. 其他常見的 Bison 百分號指令

  • %token:用於宣告終結符。
  • %type:宣告非終結符的型別。
  • %start:指定起始規則。
  • %union:宣告用於儲存語法樹節點值的聯合體。

總結

  • %code requires {}:指定必須包含的程式碼,會被放入生成的標頭檔案中。
  • %{ %}:包含的 C/C++ 程式碼,直接插入到生成的解析器實現檔案中。

這些指令有助於管理程式碼的分工,讓 Bison 的自動生成程式碼與手寫程式碼合理地結合起來。

在 Bison 中,%% 也是一種特殊符號,用於劃分Bison 檔案中的不同部分。具體來說,Bison 檔案由宣告部分規則部分輔助程式碼部分組成,而 %% 用來將這些部分清晰地分隔開。


檔案總覽和主體

Bison 檔案結構及 %% 的作用

1. 檔案的基本結構

Bison 檔案通常由三大部分組成:

  1. 宣告部分
    在這一部分,我們定義終結符、非終結符及它們的資料型別。
  2. 規則部分
    定義語法規則,描述如何將輸入轉換為目標語法結構。
  3. 輔助程式碼部分
    包含 C/C++ 的實現程式碼,如錯誤處理函式等。

結構如下:

/* 宣告部分 */
%{
  // C/C++ 標頭檔案和全域性宣告
%}

/* 定義終結符、非終結符和起始符 */
%token INTEGER
%start program

/* 規則部分 */
%%

program:
    expr { std::cout << "Result: " << $1 << std::endl; }
;

expr:
    INTEGER { $$ = $1; }
  | expr '+' expr { $$ = $1 + $3; }
;

/* 輔助程式碼部分 */
%%

int yylex() {
  // 詞法分析器實現
}

void yyerror(const char *s) {
  std::cerr << "Error: " << s << std::endl;
}

2. %% 的具體作用

  1. 第一個 %%
    宣告部分規則部分分隔開。宣告部分通常包含 %token 等定義語句,以及引入的 C/C++ 標頭檔案。

  2. 第二個 %%
    規則部分輔助程式碼部分分隔開。規則部分定義語法規則,輔助程式碼部分則包含輔助函式的實現,例如詞法分析函式 yylex 和錯誤處理函式 yyerror


3. 你程式碼中的 %% 的作用

  • %% 前面的部分:這是語法規則的定義部分。你在這裡定義瞭如何透過語法規則將輸入解析為抽象語法樹(AST)或其他結構。

  • %% 後面的部分:這是輔助程式碼部分,你在這裡實現了函式,如 yylex()yyerror()。具體到你的例子,你可能在這個部分實現了 Bison 呼叫的錯誤處理函式:

void yyerror(std::unique_ptr<BaseAST> &ast, const char *s) {
    std::cerr << "Error: " << s << std::endl;
}
  • yyerror 函式:這是 Bison 的標準錯誤處理介面。當解析過程中遇到語法錯誤時,Bison 會呼叫這個函式,並傳入錯誤資訊字串 s

4. 小結

  • %% 是 Bison 檔案的分隔符,用於分割宣告部分、規則部分和輔助程式碼部分。
  • yyerror 是一個錯誤處理函式,用於報告解析過程中遇到的錯誤。
  • 你的程式碼結構大致如下:
    1. 宣告部分(引入標頭檔案、宣告函式)。
    2. 規則部分(定義語法規則)。
    3. 輔助程式碼部分(定義 yyerror 和其他輔助函式)。

這些分隔符確保你的程式碼邏輯清晰,並讓 Bison 能夠正確地生成解析器程式碼。

相關文章