c - Bison 抛出一个段错误,假设它与 *char 有关

标签 c segmentation-fault bison flex-lexer

我似乎在使用 *char 作为我的 YYSTYPE 时做错了一些事情,我很新,无法弄清楚自己发生了什么。 Bison 要么给我一个语法错误,要么给我一个段错误。 Lexer 代码和 Bison 代码可以在下面找到。无论如何,我将非常感谢能帮助我的人...

词法分析器代码:

/* token codes */
%{
#include <string.h>
#include "printOut.tab.h"
   int decl;
%}
%%
"variables" {decl = 1; return VARS;}
"while" {return WHILE;}
"(" {return OB;}
")" {return CB;}
"{" {decl = 0; return OA;}
"}" {return CA;}
";" {return CP;}
"if" {return IF;}
":=" {return ASGN;}
"=" {return IS;}
"<" {return SML;}
">" {return BIG;}
"/=" {return NIS;}
"+" {return PLS;}
"-" {return MIN;}
"^" {return POW;}       
"/" {return DIV;}
"*" {return MUL;}
"||" {return MA;}
"->" {return ARR;}
\\in {return VIS;}
"int"|"string" {yylval.c = strdup(yytext); return TYP;}
[ \t\n] {/*ignore whitespace and newline*/}
[A-Za-z0-9]*(\[[a-zA-Z \.0-9\-\+]+(->)*[a-zA-Z \.0-9\-\+]+\])* {yylval.c = strdup(yytext); return VAR;}
%%
/*main(int argc, char **argv)
{
   int tok;
   yyin = fopen(argv[1], "r");
   while(tok = yylex()) {
    if(decl && tok == IS) {  tok = VIS; printf("%d ", tok); }
    else {
       if(tok == VAR){ printf("%s ", yylval); } else { printf("%d ", tok); }
    }
   }
}*/

Bison 代码:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
%}


%union {
  char *c;
}

%token <c> VAR TYP
%token <c> VARS WHILE IF
%token <c> VIS IS NIS MIN PLS POW DIV MUL ASGN MA SML BIG ELSE ARR
%token <c> OB CB OA CA CP

%type <c> vardec constr assign cond expr subexp input dec
%type <c> start

%%


input:  /* nothing */
    | input constr {printf("%s\n", $1); }
    | input start {printf("%s\n", $1); }
    | input vardec {printf("%s\n", $1); }
;
start: MIN MIN VAR OA {sprintf($$,"<algorithm=%s/>", $3); }
;
vardec: VARS dec {sprintf($$,"<declarations>%s</declarations>", $2); }
;
dec:    TYP VAR VIS VAR CP {sprintf($$,"<declaration type=%s name=%s>%s</declaration>",$1,$2,$4);}
    | dec CP TYP VAR VIS VAR CP {sprintf($$,"%s<declaration type=%s name=%s>%s</declaration>",$1,$3,$4,$6);}
;
constr: WHILE OB cond CB OA constr CA CP {sprintf($$,"<construct type=%s><condition>%s</condition><body>%s</body></construct>","while",$3,$6);}
    | IF OB cond CB OA constr CA CP {sprintf($$,"<construct type=%s><condition>%s</condition><body>%s</body></construct>","if",$3,$6);}
    | IF OB cond CB OA constr CA ELSE OA constr CA CP  {sprintf($$,"<construct type=%s><condition>%s</condition><body>%s</body><altbody>%s</altbody></construct>","if",$3,$6,$10);}
    | assign CP
    | OA constr CA {$$ = $2;}
;
assign: VAR ASGN expr {sprintf($$,"<assignment name=%s>%s</assignment>",$1,$3);}
    | assign MA VAR ASGN expr {sprintf($$,"<combinedassignment>%s<assignment name=%s>%s</assignment></combinedassignment>",$1,$3,$5);}
;
cond:   VAR {sprintf($$,"<variable name=%s/>",$1);}
    | expr IS expr {sprintf($$,"<equality><left>%s</left><right>%s</right></equality>",$1,$3);}
    | expr SML expr {sprintf($$,"<smaller><left>%s</left><right>%s</right></smaller>",$1,$3);}
    | expr BIG expr {sprintf($$,"<bigger><left>%s</left><right>%s</right></bigger>",$1,$3);}
    | expr NIS expr {sprintf($$,"<inequality><left>%s</left><right>%s</right></inequality>",$1,$3);}
;
expr:   subexp
    | expr PLS subexp {sprintf($$,"<add><left>%s</left><right>%s</right></add>",$1,$3);}
    | expr MIN subexp {sprintf($$,"<subtract><left>%s</left><right>%s</right></subtract>",$1,$3);}
/*  | MIN expr {sprintf($$,"<subtract><left>%s</left></subtract>",$2);}
*/  | expr POW subexp {sprintf($$,"<power><left>%s</left><right>%s</right></power>",$1,$3);}
/*  | OB expr CB {$$ = $2;}
*/;
subexp: VAR {sprintf($$,"<variable name=%s/>",$1);}
    | subexp DIV VAR {sprintf($$,"<divide><left>%s</left><right>%s</right></divide>",$1,$3);}
    | subexp MUL VAR {sprintf($$,"<multiply><left>%s</left><right>%s</right></multiply>",$1,$3);}
/*  | OB subexp CB {$$ = $2;}
*/;
%%
main()
{
while(!feof(stdin)){
  yyparse();
}
}

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

最佳答案

您声明了 <c>作为规则的类型 start .

<c>反过来,是char * .这些错误还有很多,所以我将解释导致您的 SEGFAULT 的错误。与 start规则:

$$是规则的值,所以您实际上是在这样做:

char *result;
sprintf(result,"<algorithm=%s/>", argument);

result在这个例子中没有分配,所以sprintf()正在尝试写入未分配的内存区域。您需要实现类似 strdup() 的功能(你已经在你的词法分析器中使用了)它接受可变参数,分配适当的内存量然后执行 sprintf -魔法:

char* alloc_string(char *szFormat, ...) {
    va_list args;
    va_start(args, szFormat);
    char szBuffer[1] = "\0";

    // vsnprintf() returns the bytes needed (*excluding* the null terminator)
    // for a given formatter string and argument list
    int nSize = vsnprintf(szBuffer, 0, szFormat, args);

    char *szResult = (char *) malloc(1 + nSize);
    vsnprintf(szResult, nSize + 1, szFormat, args);
    return szResult;
}

不用说,你负责free()读取内存 malloc()在此函数中编辑。

关于c - Bison 抛出一个段错误,假设它与 *char 有关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6653973/

相关文章:

c++ - 二进制文件和跨平台兼容性

c - Swift2 @convention(c) 与 char* 和 type**

c++ - 将结构传递给 unordered_map 时出现段错误

c++ - 试图用 mmap 引起段错误

javascript - Jison 解析器中的语法错误

c++ - 如何在 x86-64 上优化 C 和 C++ 中的函数返回值?

c - 运行时错误 : Segmentation fault (core dumped)

c - yyerror 的 Bison 冲突类型

bison - 弯曲 : input rules are too complicated (>= 32000 NFA states) (while compiling HLA on 62bit)

c - c中 "|"运算符和 "<<"运算符的用途是什么