如何在野牛中管理内存?

How is memory managed in bison?

我正在学习野牛并遇到了一个问题。我尝试设计一个 RE 来接受整数集,例如 {1,2,3}。 以下是我的部分代码。

printf("given {, str_to_out before %s \n", str_to_out);
str_to_out[0] = '{';
printf("given {, str_to_out after %s \n", str_to_out);

问题是,当我输入“{1} - {2}”时,一个简单的集合计算,代码运行不正确。我得到两个打印如下:

given {, str_to_out before  
given {, str_to_out after {1}

问题是什么?我认为这是因为内存管理有问题,也许我不明白。 谢谢大家帮助我!! 其他代码如下所示: 该过程从函数 "MinusPoly($$,,)" 开始,然后顺序为: "Format()" -> "Expand()"。问题发生在 "Expand()"

%{
#define YYSTYPE char *
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 5000
int yyerror(const char* s);
int yylex(void);
void MinusPoly(char *a,const char *p1, const char *p2);
void Format(char* str);
void AppendIntToStr(char* str, int num);
void Expand(char* str);
void RmRedunInt(char *str_to_out);
void StrToIntList(char *str, int list[], int *count);
int IsExist(int target, int list[], int length);
void IntListToStr(char *str, int list[], int length);
void RmWs(char* str);
%}
%token NUM
%token LB RB POLY BRACE SET INTERSECT UNION MAX MIN
%left '-' '+'
%left '*' '/' DOTM
%right '^'
%%
/* grammar rules and actions follow in {}*/

input: input line
    | line
    ;

line:   '\n'
        | expr '\n' {printf("res %s\n",);}
    ;

expr:   expr '-' expr_md {MinusPoly($$,,);}
    | expr '+' expr_md {}
    | expr_md {$$=;}
    ;

expr_md: expr_md '*' expr_hi  {printf("multiply \n");}
    | expr_md '/' expr_hi      {}
    | expr_hi {$$=;}
    ; 

expr_hi: LB expr RB {$$ = ;}
    | SET {printf("set %s\n",);}
    ;

%%
#include<ctype.h>
int main(void){
return yyparse();
}
int yyerror(const char* s) { return 0; }

void MinusPoly(char *a,const char *p1, const char *p2){
    int l1 = strlen(p1), l2 = strlen(p2);
    int i;
    char s, np1[MAXL],np2[MAXL];
    strcpy(np1,p1);
    strcpy(np2,p2);
    Format(np1);
    Format(np2);
    printf("np1 %s\n",np1);
    printf("np2 %s\n",np2);
    return;
}

void Format(char* str){
    char temp[MAXL];
    int i, j ,len;
    strcpy(temp,str);
    RmWs(temp);
    Expand(temp);
    len = strlen(temp);
    printf("str is %s\n",temp);
    for(i=0; i < len; i ++){
        str[i] = temp[i];
    }
    str[i] = '[=12=]';
    return;
}

void Expand(char* str){
    int i,j, len, outlen = 0, num1, num2,len1 = 0, len2 = 0,curr_num = 0;
    char temp_sbl;
    char str_to_out[MAXL], str_range[10], str_num[10];
    strcpy(str_to_out,"");
    len = strlen(str);
    printf("input str is %s, length %d\n",str,len);
    if(len <= 2)
        return;
    for(i = 0 ;i  < len; i ++){
        temp_sbl = str[i];
        if(temp_sbl == '{'){
printf("given {, str_to_out before %s \n", str_to_out);
            str_to_out[0] = '{';
printf("given {, str_to_out after %s \n", str_to_out);
            outlen++;
            continue;
        }
        if(temp_sbl == '-'){
            num1 = curr_num;
            num2 = 0;
            curr_num = 0;
            for(j = i + 1; j <len; j ++){
                if(!isdigit(str[j])){
                    break;
                }
                num2 = num2 * 10 + str[j] - '0';
            }
            i = j;
            if(num1 <= num2){
                for(j = num1; j <=num2; j++){
                    AppendIntToStr(str_to_out,j);
                    outlen = strlen(str_to_out);
                    if(j<num2){
                        str_to_out[outlen] = ',';
                        outlen++;
                    }
                }
            }
            else{
                for(j = num2; j <=num1; j++){
                    AppendIntToStr(str_to_out,j);
                    outlen = strlen(str_to_out);
                    if(j<num1){
                        str_to_out[outlen] = ',';
                        outlen++;
                    }
                }               
            }
            str_to_out[outlen] = str[i];
            outlen++;
            continue;
        }
        if(temp_sbl == ',' || temp_sbl == '}'){
            AppendIntToStr(str_to_out,curr_num);
            outlen = strlen(str_to_out);
            str_to_out[outlen] = temp_sbl;
            outlen++;
            curr_num = 0;
            continue;
        }
        curr_num = curr_num * 10 + str[i] - '0';

    }
    strcpy(str,"");
    RmRedunInt(str_to_out);
    strcpy(str,str_to_out);
    return;
}

void IntListToStr(char *str, int list[], int length){
    int i,j, len = 0;
    char str_num[50];
    str[0] = '{';
    len = 1;
    for(i = 0 ; i < length; i ++){
        strcpy(str_num,"");
        sprintf(str_num,"%d",list[i]);
        strcat(str,str_num);
        len = strlen(str);
        if(i < length - 1)
            str[len] = ',';
        else
            str[len] = '}';
        len++;
    }
    return;
}

int IsExist(int target, int list[], int length){
    if(length==0)
        return 0;
    int i;
    for(i=0;i<length;i++)
        if(list[i]==target)
            return i+1;
    return 0;
}

void StrToIntList(char *str, int list[], int *count){
    int i, j , tempcount = 0, temp_ls[1000], len = strlen(str);
    int curr_num = 0;
    for(i = 0 ; i < len ; i ++){
        if(str[i] == '{')
            continue;
        if(str[i] == ',' || str[i] == '}'){
            list[tempcount] = curr_num;
            tempcount++;
            curr_num = 0;
            continue;
        }
        curr_num = curr_num * 10 + str[i] - '0';
    }
    *count = tempcount;
    return;
}

void RmRedunInt(char *str_to_out){
    int i,j ,len;
    int ls_num[1000],count = 0, temp_ls[1000], tempcount = 0;
    char str_temp[MAXL];
    strcpy(str_temp,"");
    StrToIntList(str_to_out,temp_ls,&tempcount);
    for(i = 0; i < tempcount; i ++){
        if(IsExist(temp_ls[i],ls_num,count))
            continue;
        ls_num[count] = temp_ls[i];
        count++;
    }
    IntListToStr(str_temp,ls_num,count);
    strcpy(str_to_out,"");
    strcpy(str_to_out,str_temp);
    return;
}



void AppendIntToStr(char* str, int num){
    char str_num[50];
    strcpy(str_num,"");
    sprintf(str_num,"%d",num);
    strcat(str,str_num);
    return;
}

我观察到:

  • 您对 MinusPoly 的调用很奇怪,因为您将 $$ 作为参数传递,但 $$ 是规则的 return 值。

  • 您从未设置 expr 规则的 return 值。 expr_md '/' expr_hi 之类的规则需要进行一些处理,例如 {$$=/;}

  • 其他规则你也犯了这个错误

我建议你先解决这个问题。至于bison的"memory management":它只是运行一个C程序,没有自己的内存管理。唯一需要注意的是使规则成为左递归的,你可以这样做(否则你可以 运行 出栈)。