Bison中百分号的作用

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 能够正确地生成解析器代码。

posted @ 2024-10-27 03:37  Gold_stein  阅读(25)  评论(0编辑  收藏  举报