Бизон бросает мне ошибку, предполагая, что это как-то связано с * char - PullRequest
1 голос
/ 11 июля 2011

Я, кажется, делаю что-то очень неправильное в использовании * char в качестве моего YYSTYPE, я довольно новичок и не могу сам понять, что происходит. Бизон либо выдает мне синтаксическую ошибку, либо ошибку. Код 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); }
    }
   }
}*/

Код зубра:

%{
#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);
}

1 Ответ

2 голосов
/ 11 июля 2011

Вы объявили <c> как тип для правила start.

<c>, в свою очередь, это char *.Этих ошибок больше, поэтому я объясню одну, ведущую к вашему SEGFAULT, с помощью правила start:

$$ - это значение правила, так что вы практически делаете это:

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

result в этом примере не выделено, поэтому sprintf() пытается выполнить запись в нераспределенную область памяти.Вам нужно реализовать функцию типа strdup() (которую вы уже используете в своем лексере), которая принимает переменные аргументы, выделяет необходимое количество памяти и затем выполняет 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;
}

Излишне говорить, что вы несете ответственность за free() сохранение памяти malloc(), редактируемой в этой функции.

...