You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:03:17