2013-06-15 9 views
7

Ich versuche, einen Compiler für eine Mini-Pascal-ähnliche Sprache zu erstellen. Ich benutze dafür Flex und Bison und habe diesen Fehler gefunden.Undefinierter Verweis auf `_yyerror 'beim Kompilieren mit Flex und Bison

Meine Flex-Datei:

%{ 
#include "y.tab.h" 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
void yyerror(char *); 
%} 

%% 

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

program  return PROGRAM; 
or   return OR; 
and   return AND; 
not   return NOT; 
if   return IF; 
else  return ELSE ; 
while  return WHILE; 
"+"   return PLUS; 
"-"   return MINUS; 
"*"   return MUL; 
"/"   return DIV; 
"["   return LSB; 
"]"   return RSB; 
"{"   return LCB; 
"}"   return RCB; 
"("   return LEFTPAR; 
")"   return RIGHTPAR; 
":="  return ASSIGN; 
"=="  return ISEQUAL; 
"<"   return LTHAN; 
">"   return GTHAN; 
"<>"  return NOTEQUAL; 
"<="  return LESSEQUAL; 
">="  return GREATEREQUAL; 

[a-zA-z][a-z0-9]* { 
        yylval.s = (char*)malloc(strlen(yytext)*sizeof(char)); 
        strcopy(yylval.s,yytext); 
        return ID; 
}    

[ \t\n]+       /* eat up whitespace */   

.         yyerror("Unknown Character"); 

%% 
int yywrap(void) { 
    return 1; 
} 

Meine Bison-Datei:

%{ 
    #include <stdio.h> 
    #include <string.h> 
    int yylex(void); 
    void yyerror(char *s); 
%} 

%union { 
    int i; 
    char *s; 
}; 

%token <i> INTEGERNUM 

%token PROGRAM; 
%token OR; 
%token AND; 
%token NOT; 
%token IF; 
%token ELSE; 
%token WHILE; 
%token PLUS; 
%token MINUS; 
%token MUL; 
%token DIV; 
%token LSB; 
%token RSB; 
%token LCB; 
%token RCB; 
%token LEFTPAR; 
%token RIGHTPAR; 
%token ID; 
%token INT; 
%token ASSIGN; 
%token ISEQUAL; 
%token LTHAN; 
%token GTHAN; 
%token NOTEQUAL; 
%token LESSEQUAL; 
%token GREATEREQUAL; 

%% 

program: 
     PROGRAM ID block 
     ; 

block: 
     LCB sequence RCB 
     ; 

sequence: 
     statement ';' sequence 
     | statement ';' 
     ; 

bracketsSeq: 
     LCB sequence RCB 
     ; 

brackOrStat:   
     bracketsSeq 
     | statement 
     ; 

statement: 
     assignmentStat 
     |ifStat 
     |whileStat 
     | 
     ; 

assignmentStat: 
     ID ':=' expression 

ifStat: 
     IF LEFTPAR condition RIGHTPAR brackOrStat elsepart 
     ; 

elsepart: 
     ELSE brackOrStat 
     | 
     ; 

whileStat: 
     WHILE LEFTPAR condition RIGHTPAR brackOrStat 
     ; 

expression: 
     optionalSign expression 
     |expression addOper expression 
     |term 
     ; 

term: 
     term mulOper term 
     |factor 
     ; 

factor: 
     INT 
     |LEFTPAR expression RIGHTPAR 
     |ID 
     ; 

condition: 
     condition AND condition 
     |boolterm 
     ; 

boolterm: 
     boolterm OR boolterm 
     |boolfactor 
     ; 

boolfactor: 
     NOT LSB condition RSB 
     |LSB condition RSB 
     |expression relationalOper expression 
     ; 

relationalOper: 
     ISEQUAL 
     |LTHAN 
     |GTHAN 
     |NOTEQUAL 
     |LESSEQUAL 
     |GREATEREQUAL 
     ; 

addOper: 
     PLUS 
     |MINUS 
     ; 

mulOper: 
     MUL 
     |DIV 
     ; 

optionalSign: 
     addOper 
     | 
     ; 

%% 

int main(int argc, char **argv) 
      { 
      printf("TEST\n"); 

      }  

Die Reihe von Schritten, die ich ausgeführt wurde:

$ ./bison.exe -dy comp.y 
$ ./flex.exe comp.l 
$ gcc -c -w lex.yy.c 
$ gcc -c -w comp.tab.c 
$ gcc comp.tab.o lex.yy.o -o ex 
comp.tab.o:comp.tab.c:(.text+0x4cd): undefined reference to `_yyerror' 
comp.tab.o:comp.tab.c:(.text+0x61c): undefined reference to `_yyerror' 
lex.yy.o:lex.yy.c:(.text+0x34a): undefined reference to `_strcopy' 
lex.yy.o:lex.yy.c:(.text+0x362): undefined reference to `_yyerror' 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/ld: lex.yy.o: bad reloc address    0x828 in section `.rdata' 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/ld: final link failed: Invalid    operation 
collect2: ld returned 1 exit status 
$ 

Ratschläge, was zu erklären und wo Denn da scheint es so zu sein, dass ich etwas falsch deklariert habe!

+0

Sie können eine Bibliothek haben, '-ly' (' liby.a' oder 'liby.so'), die bietet eine Version von 'yyerror()' und 'main()'. Sie würden dann "-ly" zur verbindenden Befehlszeile hinzufügen. –

Antwort

14

Es reicht nicht, yyerror zu deklarieren. Sie müssen eine Definition angeben.

Die bison manual schlägt folgende als minimale Implementierung:

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

Das andere Problem, das Sie haben, ist, dass Sie strcpy in Ihrer Flex-Datei falsch geschrieben.

Genauer gesagt, das andere Problem, das durch die Linkerfehler aufgedeckt wird, ist die falsch geschriebene strcpy, weil Ihr Kopiercode falsch ist. Es berücksichtigt nicht das Byte NUL, das Zeichenfolgen beenden muss. strcpy kopiert dieses Byte mit dem Ergebnis, dass es eine 0 in nicht zugeordneten Speicher schreiben wird. Sie werden es viel einfacher finden, strdup zu verwenden. (Und vergessen Sie nicht, dass Sie free die Zeichenfolgen benötigen, wenn Sie mit ihnen fertig sind.)