YACC编译警告:$2(IDENTIFIER)未类型化问题求助
问题分析与修复方案
警告原因
警告$2 (IDENTIFIER) is untyped的核心问题是:你在%union里定义了char* str类型,但IDENTIFIER这个token没有关联到该类型,YACC无法识别它的语义值类型,所以在memDeclaration规则里引用$2(对应IDENTIFIER)时触发警告。
具体修复步骤
1. 给IDENTIFIER指定类型
修改%token行,给IDENTIFIER加上<str>标记,让YACC明确它的语义值为char*类型:
%token TYPEDEF STRUCT CHAR SHORT INT FLOAT DOUBLE <str>IDENTIFIER SEMICOLON LBRACE RBRACE LBRACKET RBRACKET
2. 修复structDeclaration规则的两个问题
- 当前
program规则里使用了$1(structDeclaration的语义值),但原规则未给$$赋值,会导致输出错误,需在动作里将结构体名($3,即第一个IDENTIFIER)赋值给$$; - 动作代码里多了一个多余的右括号,需删除。
修改后的structDeclaration规则:
structDeclaration: TYPEDEF STRUCT IDENTIFIER LBRACE memDeclaration RBRACE IDENTIFIER SEMICOLON { $$ = strdup($3); // 将结构体名赋值给当前规则的语义值,供program规则使用 printf("}\n"); }
3. 可选:处理内存泄漏(非必须但推荐)
因为用strdup分配了内存,可在program规则的动作里释放,避免内存泄漏:
program: structDeclaration { printf("public class %s {\n", $1); free($1); // 释放strdup分配的内存 } ;
修复后的完整代码
%{ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "lex.yy.c" extern int yylex(); extern FILE* yyin; void yyerror(const char *s); int yywrap() { return 1; } %} %union { char* str; } %token TYPEDEF STRUCT CHAR SHORT INT FLOAT DOUBLE <str>IDENTIFIER SEMICOLON LBRACE RBRACE LBRACKET RBRACKET %type <str>structDeclaration memDeclaration %% program: structDeclaration { printf("public class %s {\n", $1); free($1); } ; structDeclaration: TYPEDEF STRUCT IDENTIFIER LBRACE memDeclaration RBRACE IDENTIFIER SEMICOLON { $$ = strdup($3); printf("}\n"); } ; memDeclaration: INT IDENTIFIER SEMICOLON { printf(" private int %s;\n", $2);} |CHAR IDENTIFIER SEMICOLON { printf(" private String %s;\n", $2);} |SHORT IDENTIFIER SEMICOLON { printf(" private short %s;\n", $2);} |FLOAT IDENTIFIER SEMICOLON { printf(" private float %s;\n", $2);} |DOUBLE IDENTIFIER SEMICOLON {printf(" private double %s;\n", $2);} ; %% void yyerror(const char *s) { fprintf(stderr, "Error: %s\n", s); } int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "Invalid usage: %s <input-file>\n", argv[0]); return 1; } yyin = fopen(argv[1], "r"); if (!yyin) { perror("fopen"); return 1; } yyparse(); fclose(yyin); return 0; }
额外说明
- 原main函数里的错误信息
Unvalid改成了规范的Invalid; - 现在重新执行
yacc -d xxx.y就不会再出现警告,编译后可正常将输入的C结构体定义转换成Java类格式。
内容的提问来源于stack exchange,提问作者Cepheus
相关产品推荐
相关产品推荐

