Bison throws me a segfault, assuming it has something to do with *char
I seem to be doing something very wrong in the use of *char as my YYSTYPE, I'm pretty new and unable to figure out myself what is going on. Bison either giv开发者_JAVA百科es me a syntax error or a segfault. Lexer code and Bison code can be found below. I'd be very thankful to anyway who can help me out here...
Lexer code:
/* 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 code:
%{
#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);
}
You declared <c>
as a type for rule start
.
<c>
in turn, is char *
. There are more of these errors, so I'll explain the one leading to your SEGFAULT
with the start
rule:
$$
is the rule's value, so you're practically doing this:
char *result;
sprintf(result,"<algorithm=%s/>", argument);
result
in this example is not allocated, so sprintf()
is attempting to write to an unallocated memory region. You'll need to implement a function like strdup()
(which you're using in your lexer, already) that accepts variadic arguments, allocates the proper ammount of memory and then does the sprintf
-magic:
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;
}
Needless to say, you're responsible for free()
ing the memory malloc()
ed in this function.
精彩评论