2016-05-23 13 views
0

Ich bin neu in C und noch mehr neu in Flex und Bison. Ich schreibe einen einfachen Parser für ein Projekt. Ich versuche, einen Ladebefehl zu machen, so kann ich Code von einer externen Datei laden und den Parser ausführen lassen. Hier ist der Code, ich habe:Eingangsfunktion für Parser mit Flex und Bison erstellen

Bison (spire.y):

#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include <string.h> 
#include "helper.h" 

/* prototypes */ 
nodeType *opr(int oper, int nops, ...); 
nodeType *id(int i); 
nodeType *con(int value); 
void freeNode(nodeType *p); 
int ex(nodeType *p); 
int yylex(void); 
void yyerror(char *s); 
int sym[26]; /* symbol table */ 
%} 

%union { 
    int iValue; /* integer value */ 
    char sIndex; /* symbol table index */ 
    char *var; 
    char *str; 
    nodeType *nPtr; /* node pointer */ 

}; 

%token <iValue> INTEGER 
%token <sIndex> VARIABLE 
%token <var> VARNAME 
%token <str> STRING 
%token WHILE IF TELL EXITCOMM LOAD 
%nonassoc IFX 
%nonassoc ELSE 
%left GE LE EQ NE '>' '<' BLKND 
%left '+' '-' 
%left '*' '/' 
%nonassoc UMINUS 
%type <nPtr> stmt expr stmt_list 

%% 

spire: 
    code { exit(0); } 
;  

code: 
    code stmt { ex($2); freeNode($2); } 
    | /* NULL */ 
;  

stmt: 
    ';' { $$ = opr(';', 2, NULL, NULL); } 
    | expr ';' { $$ = $1; } 
    | EXITCOMM {exit(EXIT_SUCCESS); } 
    | LOAD STRING ';' { char *f = $2; f++[strlen(f)-1] = 0; $$ = getCode(f); } 

... 

%% 

... 

const char * getCode(char *fileName){ 
    char ch; 
    char *code; 
    FILE *fp; 

    fp = fopen(fileName, "r"); 

    if(fp == NULL) 
    { 
     printf("Error while opening the file %s.\n", fileName); 
     return ';'; 
    }else{ 
     while((ch = fgetc(fp))!=EOF) 
      code = strcat(code, ch); 

     fclose(fp); 
     return code; 
} 

Flex (spire.l):

%{ 
#include <stdlib.h> 
#include "helper.h" 
#include "spire.tab.h" 
void yyerror(char *); 
%} 

%% 

[a-z] { 
     yylval.sIndex = *yytext - 'a'; 
     return VARIABLE; 
} 

0 { 
     yylval.iValue = atoi(yytext); 
     return INTEGER; 
} 

[1-9][0-9]* { 
     yylval.iValue = atoi(yytext); 
     return INTEGER; 
} 

[-()<>^=+*/;{}~."] { 
     return *yytext; 
} 

'~'  return EXITCOMM; 

"^^" return BLKND; 
">=" return GE; 
"<=" return LE; 
"==" return EQ; 
"!=" return NE; 
"while" return WHILE; 
"if" return IF; 
"else" return ELSE; 
"tell" return TELL; 
"load" return LOAD; 

[a-z][a-zA-Z0-9_]* { 
     yylval.var = strdup(yytext); 
     return VARNAME; 
} 

\"[^"\n]*["\n] { 
     yylval.str = strdup(yytext); 
     return STRING; 
} 

[ \t\n]+ ; /* ignore whitespace */ 
. yyerror("Unknown character"); 

%% 

int yywrap(void) { 
    return 1;  
} 

Hier ist die Last des Fehlers ich, Jedes Mal, Ich versuche, einen zu reparieren, den ich nur mehr bekomme.

Fehler:

spire.y: In function 'yyparse': 
spire.y:56: warning: assignment makes pointer from integer without a cast 
spire.y: At top level: 
spire.y:112: error: conflicting types for 'getCode' 
spire.y:56: note: previous implicit declaration of 'getCode' was here 
spire.y: In function 'getCode': 
spire.y:122: warning: return makes pointer from integer without a cast 
spire.y:125: warning: passing argument 2 of 'strcat' makes pointer from integer without a cast 
/usr/include/string.h:136: note: expected 'const char * __restrict__' but argument is of type 'char' 
spire.y:208: error: expected declaration or statement at end of input 

Lassen Sie mich wissen, wenn Sie die gesamte Bison

Antwort

1

getCode Datei will nur völlig falsch ist. Das hat nichts mit Bison zu tun. Eine ganze Datei einzeln zu lesen ist albern. Die Verkettung jedes Zeichens mit dem Ende einer Zeichenkette hat eine quadratische Ausführungszeit, da die gesamte Zeichenkette für jede Verkettung durchsucht werden muß, und in jedem Fall wird niemals Speicher für die Zeichenkette reserviert, die Sie zu konstruieren versuchen. Sie überprüfen nie, ob Sie den gesamten Speicher verwendet haben, der der Zeichenfolge zugeordnet ist, und Sie scheinen zu glauben, dass ein Zeichen eine Zeichenfolge aus einem Zeichen ist, obwohl es aus den Typen bestehen sollte, die ein Zeichen und ein Zeichen * vollständig sind anders. (Das ist keine vollständige Liste der Probleme mit dieser Funktion.) strcat erfordert zwei Zeichenfolgen, keine Zeichenfolge und ein Zeichen.

Aus einer Flex/Bison-Perspektive, da flex versteht, wie Eingabedateien gelesen werden, gibt es wirklich keinen Sinn, die Datei selbst zu lesen. Alles, was Sie tun müssen, ist ein FILE* öffnen und veranlassen, dass der Flex-generierte Scanner es liest. Eine Möglichkeit dazu finden Sie im Flex-Handbuch im Abschnitt über mehrere Eingabepuffer. Eine andere Möglichkeit wäre, einen Wiedereintrittsscanner und Parser zu verwenden und den Parser rekursiv aufzurufen.

Wo Sie getCode in Ihrem Parser aufrufen, zuweisen deren Rückgabewert (a const char *) auf den semantischen Wert ($$) von stmt, aber stmt hat den Typ-Tag NPTR, so dass die Zuordnung ist eine Art Fehler.