【问题标题】:BISON AST production prints scrambled valuesBISON AST 生产打印加扰值
【发布时间】:2015-07-29 16:20:08
【问题描述】:

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

%{
#define YYDEBUG 1
%}

%start program

%token  NUMBER
%token  ID
%token  PLUS    MINUS   TIMES
%token  LP  RP  EQUALS  COMMA
%token  END

%token  LET IN  AND

%left   PLUS    MINUS
%left   TIMES
%left   LET IN  AND
%left   EQUALS

%%

program:{printf("Empty Input\n");}  /* empty */
        | program line /* do nothing */

line:   expr END        { printtree($1); printf("\n");}
    ;

expr    : /*Empty*/
    | LET deflist IN expr {}
    | ID        { printf("Found ID\n"); $$ = make_id_leaf($1);}
    | NUMBER    { printf("Found NUMBER\n"); $$ = make_number_leaf($1);}
        | PLUS LP expr COMMA expr RP  {$$ = make_plus_tree($3,$5); printf("Found expr PLUS expr.\n"); }
        | TIMES LP expr COMMA expr RP {$$ = make_times_tree($3,$5); printf("Found expr TIMES expr. Result:%d\n", $$);}
    | MINUS ID
    | MINUS NUMBER     { printf("found MINUS NUMBER\n"); }
        ;

deflist : definition
    | definition AND deflist
    ;

definition : /*Empty*/
       | ID EQUALS expr {printf("Found EQ\n");}
       ;
%%

/*int main (void) {return yyparse ( );}*/

int yyerror (char *s) {fprintf (stderr, "%s\n", s);}

词法分析器文件:

%{
#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;}

包含 yyparse() 函数的 ma​​in.c

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

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

    return 0;
}

还有包含函数定义的 treedefs.h 文件(我只包含了结构定义、数字叶子和加号树):

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.h 文件只包含一些声明,没什么大不了的,而且绝对与问题无关。

为什么数字是这样的?我该如何解决?任何帮助将不胜感激。

【问题讨论】:

    标签: c compiler-construction bison abstract-syntax-tree yacc


    【解决方案1】:

    这个问题其实和bison或者flex没有关系。它在您的 make_number_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
     }
    

    如上面的 cmets 所示,ch 是一个本地(堆栈分配的)变量,其生命周期在函数返回时结束。将其地址分配给变量c 并没有改变它。所以存储在leafNum-&gt;token中的c的值会在函数返回后立即变成一个悬空指针。

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

    你需要malloc一个字符缓冲区,当你freeTREE时记得free它。 (不过,leafNum-&gt;token 是字符串字面量的情况下,你不能调用free,所以你需要聪明一点。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-21
      • 1970-01-01
      • 2015-07-27
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多