C BISON AST生产打印置乱值

C BISON AST生产打印置乱值,c,compiler-construction,bison,abstract-syntax-tree,yacc,C,Compiler Construction,Bison,Abstract Syntax Tree,Yacc,我正在尝试制作一个简单的解析器。这是一个家庭作业,但也为自己的实验。我已经完成了lexer和解析器,现在我正在尝试输出一个AST。问题是,例如,当我添加两个整数时,结果树会打印出无法识别的符号。有效输入应为+(1,1),有效输出应为(+11)。相反,我得到的是(+�|K�|k)。我尝试过很多事情,但实际上没有任何显著的结果。sprintf函数返回空终止符,因此这可能不是问题所在。下面是解析器代码(.y文件): lexer文件: %{ #include "parser.h" %} DIGIT [0

我正在尝试制作一个简单的解析器。这是一个家庭作业,但也为自己的实验。我已经完成了lexer和解析器,现在我正在尝试输出一个AST。问题是,例如,当我添加两个整数时,结果树会打印出无法识别的符号。有效输入应为
+(1,1)
,有效输出应为
(+11)
。相反,我得到的是
(+�|K�|k)
。我尝试过很多事情,但实际上没有任何显著的结果。
sprintf
函数返回空终止符,因此这可能不是问题所在。下面是解析器代码(.y文件):

lexer文件:

%{
#include "parser.h"
%}
DIGIT [0-9]
LETTER [a-zA-Z]
%%

LET {printf("Encountered LET\n"); return(LET);}
IN  {printf("Encountered IN\n"); return(IN);}
AND {printf("Encountered AND\n"); return(AND);}
{DIGIT}+    {yylval = atoi(yytext); return NUMBER;}
{LETTER}*       { if (strlen(yytext) <= 8){
                    yylval = strlen(yytext);
            printf( "<ID, %s> ", yytext );
            return(ID);
                  } else {
                        yytext[8] = '\0';
                        printf("WARNING! Long identifier. Truncating to 8 chars\n");
                        printf( "<ID, %s> ", yytext );
            return(ID);
                  }
                }
[ \t] ;
[\n]     return(END); 
"+"      return(PLUS);
"-"      return(MINUS);
"*"      return(TIMES);
"="  return(EQUALS);
"("      return(LP);
")"      return(RP);
","  return(COMMA);
<<EOF>>  return(0);
%%

int yywrap (void) {return 1;}
文件tree.h只包含一些声明,没有什么大不了的,而且肯定与问题无关


为什么数字看起来像这样?我怎样才能修好它?任何帮助都将不胜感激。

这个问题实际上与bison或flex无关。它在您的
make\u number\u leaf
实现中:

TREE *make_number_leaf(int n){
    TREE *leafNum = malloc(sizeof(TREE));
    char *c, ch[8];
    //       ^ local variable
    sprintf(ch, "%d", n); /* Effective way to convert int to string */
    c = ch;
    leafNum->token = c;
    //               ^ dangling pointer
    // Remainder omitted
 }
如上面的注释所示,
ch
是一个本地(堆栈分配)变量,其生存期在函数返回时结束。将其地址分配给变量
c
不会改变这一点。因此,存储在
leafNum->token
中的
c
的值将在函数返回时变为悬空指针

因此,当您稍后尝试打印令牌时,您正在打印随机内存的内容

你需要
malloc
一个字符缓冲区,当你
空闲时,记得
释放
它。(但是,如果
leafNum->token
是字符串文字,则不能调用
free
,因此需要更聪明一些。)

#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
#include "treedefs.h"

int main(int argc, char **argv){
    yyparse();

    return 0;
}
typedef struct tree{
    char *token;
    TREE *l;
    TREE *r;
    TREE *child;
}TREE;

/* Make number leaves */

TREE *make_number_leaf(int n){

    TREE *leafNum = malloc(sizeof(TREE));

    char *c, ch[8];
    sprintf(ch, "%d", n); /* Effective way to convert int to string */
    c = ch;
    leafNum->token = c;
    leafNum->l = NULL;
        leafNum->r = NULL;
        leafNum->child = NULL;

    printf("NUM Leaf is: %s\n", leafNum->token);

    return (leafNum);
}

/* Addition tree */

TREE *make_plus_tree(TREE *l, TREE *r){

    TREE *plusTree = malloc(sizeof(TREE));

    plusTree->token = "+";
    plusTree->l = l;
    plusTree->r = r;
    plusTree->child = NULL;

    return (plusTree);

}
void printtree(TREE *tree)
{
    if (tree->l || tree->r){
            printf("(");
    }

    printf(" %s ", tree->token);

    if (tree->l){
        printtree(tree->l);
    }
    if (tree->r){
        printtree(tree->r);
    }
    if (tree->l || tree->r){
        printf(")");
    }
}
TREE *make_number_leaf(int n){
    TREE *leafNum = malloc(sizeof(TREE));
    char *c, ch[8];
    //       ^ local variable
    sprintf(ch, "%d", n); /* Effective way to convert int to string */
    c = ch;
    leafNum->token = c;
    //               ^ dangling pointer
    // Remainder omitted
 }