如何在YACC中获取当前匹配的规则文本?
在YACC中获取匹配的declaration完整字符串的方法
YACC本身不会自动保存匹配规则的完整字符串,需要配合LEX记录每个token的文本内容,再在YACC的动作中拼接得到完整的declaration字符串,具体实现步骤如下:
1. 定义YACC的语义值类型
在YACC文件开头,通过%union定义语义值结构体,用来存储每个token的文本:
%union { char* str; } // 指定每个token对应的语义值字段 %token <str> TYPE INSTANCE SEMICOLON
2. 修改LEX规则,保存token文本
在LEX文件中,让每个识别到的token把自身文本复制到语义值中,示例如下:
[a-zA-Z_][a-zA-Z0-9_]* { // 这里需要根据你的语法逻辑判断当前token是type还是instance if (is_type_keyword(yytext)) { // 假设你有判断类型关键字的自定义函数 yylval.str = strdup(yytext); return TYPE; } else { yylval.str = strdup(yytext); return INSTANCE; } } ";" { yylval.str = strdup(yytext); return SEMICOLON; }
3. 在YACC的declaration动作中拼接字符串
在declaration规则的动作里,将type、instance、SEMICOLON对应的文本拼接,得到完整的声明字符串:
declaration: type instance SEMICOLON { // 计算所需内存长度,包含空格和字符串结束符 int total_len = strlen($1) + strlen($2) + strlen($3) + 2; char* full_decl = malloc(total_len); if (full_decl != NULL) { // 拼接成完整的声明字符串 snprintf(full_decl, total_len, "%s %s%s", $1, $2, $3); // 此处可对full_decl进行打印、存储等操作 puts(full_decl); // 释放拼接后的字符串内存 free(full_decl); } // 释放每个token的文本内存,避免泄漏 free($1); free($2); free($3); } type: TYPE { $$ = $1; } instance: INSTANCE { $$ = $1; }
注意事项
- 内存管理:
strdup会分配堆内存,所有通过该函数生成的字符串都需要手动调用free释放。 - 复杂语法适配:如果
type或instance由多个token组成(比如long long或int* var),需要在对应的子规则中先完成子部分的字符串拼接,再传递给上层规则。
内容的提问来源于stack exchange,提问作者clay
相关产品推荐
相关产品推荐

