【问题标题】:Bison multiple nonterminals with attributes具有属性的 Bison 多个非终结符
【发布时间】:2018-06-05 06:56:47
【问题描述】:

我正在使用 bison 和 flex 创建(在未来的某个地方)抽象语法树 (AST)。现在,我只想有一个算术表达式(例如 +),比如 expression->expression '+' expression |常量,但我希望表达式具有两个属性:代码(即规则右侧第一个元素的值(RHS)、+ 和第二个表达式的值的字符串)。

我创建了以下结构:

%union {
    struct{
        char* code;
        char* varn;
    } attributes;

    int intval;
}

这会将它们都保存为字符串(现在,我只想打印它们)。 标记和项目以及语法按以下方式定义:

%token <intval> CONST
%type <attributes> expr

%%
expr:
    expr '+' expr 
    {
        printf("%s ",$1.val);
        printf("%s \n",$3.val);
        printf("code: %s %s\n",$1.code,$3.code);
    }
expr:
    CONST 
    {
        int source=$1;
        char temp[100];
        sprintf(temp, "%d", source);
        $$.val=strcat(temp,"1");
        $$.code=temp;
        printf("val for %d is %s; code is %s\n",$1,$$.val,$$.code);
    }

%%

在 flex 中,我将 CONST 的值 (intval) 设置为元素本身(因此 4 的 val 将是 4)。应用第二条规则时,程序会正确打印该值。但是,当应用第一个时(打印整个内容时),两个表达式具有相同的 val。

varn for 4 is 41; code is 41
varn for 5 is 51; code is 51
51 51 
code: 51 51

(添加 1 只是为了测试一些东西,它不是计划的一部分)

我不知道究竟是为什么。如果我将 expr 更改为 int 类型

%type <intval> expr

它工作正常。

【问题讨论】:

  • $$.code=temp 看起来很可疑 - temp 的范围是什么?这可能意味着每个$$.code 都指向相同的值?
  • 我正在尝试将 $1 的 int 值转换为字符串,以便可以将其分配给 $$.code,即 char*。我也认为这完全是因为一些指针,但我已经很长时间没有使用 C 语言了,这是我可以进行这种转换的唯一方法。 Temp 被用作临时变量来存储从 int 到 string 的转换值(如果我尝试在 sprintf 中直接使用 $$.code 会出错)
  • 你可能想要$$.code=strdup(temp);,然后记得free在适当的点分配内存
  • 成功了,非常感谢!我真的需要刷新我的 C 指针技能!

标签: c parsing bison abstract-syntax-tree flex-lexer


【解决方案1】:

您的代码正在执行的操作与以下内容并不太相似:

char temp[100];

strcpy(temp,"hello");
char *str1=temp;

strcpy(temp,"world");
char *str2=temp;

printf("%s %s\n",str1,str2);

str1str2 都指向内存中的同一点,因此您将获得输出“世界世界”。您需要为每个字符串分配内存,以便它们在内存中拥有自己的位置。

然后在“expr '+' expr”模式中,您将 free 每个字符串并创建新字符串以传递解析链。

【讨论】:

  • 好吧,这是有道理的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 2021-12-28
  • 2018-07-17
相关资源
最近更新 更多