3使用lex和yacc生成地址代码

时间:2016-03-09 12:12:46

标签: yacc lex

我试图生成与基本算术表达式相对应的3个地址代码。我之前没有使用lex和yacc工具(Newbie),我很难理解两者之间的控制/命令流程,即两个程序如何交互。

lex.l

%{
    #include<stdio.h>
    #include"y.tab.h"
    int k=1;
%}

%%
[0-9]+ {
yylval.dval=yytext[0];
return NUM;
}

\n {return 0;}
. {return yytext[0];}
%%

void yyerror(char* str)
{
        printf("\n%s",str);
}
char *gencode(char word[],char first,char op,char second)
{
    char temp[10];
    sprintf(temp,"%d",k);
    strcat(word,temp);
    k++;
    printf("%s = %c %c %c\n",word,first,op,second);

    return word; //Returns variable name like t1,t2,t3... properly
}
int yywrap()
{
    return 1;
}

main()
{
        yyparse();
        return 0;
}

yacc.y

%{
#include<stdio.h>
int aaa;
%}

%union{
    char dval;
}

%token <dval> NUM
%type <dval> E
%left '+' '-'
%left '*' '/' '%'

%%
statement : E {printf("\nt = %c \n",$1);}
          ;

E : E '+' E 
    {   
        char word[]="t";
        char *test=gencode(word,$1,'+',$3);
        $$=test;

    }
  | E '-' E 
    {
        char word[]="t";
        char *test=gencode(word,$1,'-',$3);
        $$=test;
    }
  | E '%' E 
    {
        char word[]="t";
        char *test=gencode(word,$1,'%',$3);
        $$=test;
    }
  | E '*' E 
    {
        char word[]="t";
        char *test=gencode(word,$1,'*',$3);
        $$=test;
    }
  | E '/' E 
    {
        char word[]="t";
        char *test=gencode(word,$1,'/',$3);
        $$=test;
    }
  | '(' E ')' 
    {
        $$=$2;
    }
  | NUM 
    {
        $$=$1;
    }
  ;
%%

问题getting garbage value in output

表达式(2 + 3)* 5 的预期输出应该如下:

t1= 2 + 3
t2= t1 * 5

获得输出:

t1= 2 + 3
t2= garbage value * 5

我无法弄清楚如何纠正这个问题。变量名称(例如t1,t2,t3)正在lex.l中的gencode()方法中正确返回

char *test=gencode(word,$1,'%',$3);

但是我完全不知道之后出了什么问题。我相信我没有正确处理$$,$1,$3条款。

请帮助我了解出了什么问题,需要做什么以及如何做。 一点帮助和一些解释将非常有帮助。谢谢。

2 个答案:

答案 0 :(得分:1)

这里的问题不在于使用弹性或野牛;相反,它是C代码中的未定义行为。

您的gencode函数返回其第一个参数。然后你这样称呼它,粗略地说:

{
  char word[] = ...
  ... = gencode(word, ...);
}

word的生命周期在块完成时结束,这是在调用gencode之后。实际上,这与经典的悬空指针生成器没有区别:

char* dangle(void) {
  char temporary[] = "some string";
  return temporary;
}

这显然是不正确的,因为局部变量在返回其地址之前不再存在。

此外,您实际上创建了word作为双字符数组:

char word[] = "t";

因为省略大小告诉C为初始字符串留下足够的空间(一个字符加上空终止符)。这没关系,但是你不能更多的字符附加到字符串(strcat),因为没有剩余的空间,你最终会覆盖其他一些变量(或更糟)。

答案 1 :(得分:-1)

mentall甚至不会在函数返回后结束。这就是为什么我在调用函数之前声明char word []的原因。 ideone.com/RBz0y2是我分别编写并在此处使用的代码。不对吗– Swagnik Dutta 16年3月9日在16:38 @novice:如果调用方在堆栈上分配并传递给被调用的函数,那很好。呼叫者仍然有记忆。但是,一旦呼叫者返回其呼叫者,内存就消失了。您不能将持久变量设置为该地址。所以,不,这是不对的。如果您需要保留将来的价值,则需要使用malloc进行分配;堆栈分配存储