14

我正在尝试为类似帕斯卡的迷你语言制作编译器。我为此使用了 Flex 和 Bison,但我遇到了这个错误。

我的弹性文件:

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

我的野牛文件:

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

             }      

我执行的一系列步骤是:

$ ./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
$

关于声明什么以及原因似乎是我以错误的方式声明的任何建议!

4

1 回答 1

24

声明是不够的yyerror。您必须提供定义。

野牛手册建议以下作为最小实现:

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

您遇到的另一个问题是您strcpy在 flex 文件中拼写错误。

更准确地说,链接器错误揭示的另一个问题是拼写错误strcpy,因为您的复制代码不正确。它不考虑NUL必须终止字符串的字节。strcpy将复制该字节,结果它将 a 写入0未分配的存储中。您会发现使用起来要简单得多strdup。(并且不要忘记,free当你完成它们时,你需要使用它们。)

于 2013-06-16T03:30:15.037 回答