c - Bison 是如何管理内存的?

标签 c bison flex-lexer

我正在学习 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($$,$1,$3)”开始,然后按顺序: “格式()”->“扩展()”。问题发生在“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",$1);}
    ;

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

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

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

%%
#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] = '\0';
    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 的调用很奇怪,因为您将 $$ 作为参数传递,但 $$ 是规则。

  • 您从未设置过 expr 规则的返回值。像 expr_md '/' expr_hi 这样的规则需要一些处理,例如 {$$=$1/$3;}

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

我建议你先解决这个问题。至于bison的“内存管理”:它只是作为C程序运行,没有自己的内存管理。唯一需要注意的是使规则左递归,您就这样做(否则您可能会耗尽堆栈)。

关于c - Bison 是如何管理内存的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40107791/

相关文章:

c - 使用 CMake 构建错误

c - 重复直到用户按下 Enter 键

c - 如何通过PID唤醒进程? (在C中)

c++ - 使用 Bison/Flex 时的 C 字符串

c - bison 的逗号分隔值的语义

compiler-construction - 在没有 %prec 或 %left 的 Bison 中设置优先级和关联性

c - 在 C 中释放 malloc 字符串的二维数组失败

c - 一元运算符如何在 C 中工作,您不能预递增零

c - 柔性 : Syntax error before '=' token

lex - ....未声明(在此函数中首次使用)?