如何将Bison递归规则import_ids序列化为逗号分隔字符串或向量
实现Bison中import_ids返回逗号分隔字符串或向量的方案
前提准备
首先需要在Bison文件开头定义语义值类型,同时确保Flex中正确传递标识符的字符串值(比如将yytext赋值给对应的语义值字段)。
方案1:返回逗号分隔字符串
修改后的Bison核心代码如下:
%{ #include <iostream> #include <string> %} // 定义语义值的联合体类型 %union { std::string str; } // 声明token %token KW_IMPORT END ID STRING DECIMAL FLOAT // 指定import_ids的语义值类型为字符串 %type <str> import_ids %% program : | program stm ; stm : stmt | expr ; stmt : import_stmt ; expr : value ; value : STRING | DECIMAL | FLOAT | ID ; import_stmt : KW_IMPORT import_ids END { std::cout << "importing " << $2 << "\n"; } ; import_ids : ID { // 单个ID时,直接返回该ID的字符串 $$ = $1; } | import_ids "," ID { // 多个ID时,拼接成逗号分隔的字符串 $$ = $1 + ", " + $3; } ; %%
对应的Flex中ID的处理示例:
ID [a-zA-Z_][a-zA-Z0-9_]* { yylval.str = yytext; return ID; }
方案2:返回标识符向量
如果需要返回std::vector<std::string>类型,修改如下:
%{ #include <iostream> #include <string> #include <vector> %} %union { std::vector<std::string> vec; std::string str; } %token KW_IMPORT END ID STRING DECIMAL FLOAT // 指定import_ids的语义值类型为向量 %type <vec> import_ids %% // 其他规则保持不变,仅修改import_ids和import_stmt: import_stmt : KW_IMPORT import_ids END { std::cout << "importing "; // 遍历向量输出所有标识符 for (size_t i = 0; i < $2.size(); ++i) { if (i > 0) std::cout << ", "; std::cout << $2[i]; } std::cout << "\n"; } ; import_ids : ID { // 初始化向量并添加单个ID $$.push_back($1); } | import_ids "," ID { // 复制已有向量并添加新ID $$ = $1; $$.push_back($3); } ; %%
Flex中的ID处理和方案1一致,确保将yytext赋值给yylval.str。
关键说明
- 必须通过
%union定义语义值类型,让Bison知道非终结符import_ids返回的数据类型。 $$表示当前规则的返回值,$1、$3等表示对应位置token/非终结符的语义值。- Flex中要正确设置
yylval的对应字段,否则Bison无法获取标识符的字符串内容。
内容的提问来源于stack exchange,提问作者Sheol-Nugganoth
相关产品推荐
相关产品推荐

