y.tab.c: 未定义对 yylex 的引用
y.tab.c: undefined reference to yylex
我正在尝试 运行 我在网上找到的计算器示例。但是每次我 运行 我的 gcc 命令都会显示这个错误。这是我 运行:
的命令
flex -l calc3.l
yacc -vd calc3.y
gcc y.tab.c -lm -ll
-> 此时我收到此错误消息:
/tmp/ccPOq58f.o : In function 'yyparse':
y.tab.c: undefined reference to 'yylex'
collect2: error: ld returned 1 exit status
这是我的代码:
calc3.l
%{
#include <stdlib.h>
#include "calc3.h"
#include "y.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 GE;
"<=" return LE;
"==" return EQ;
"!=" return NE;
"while" return WHILE;
"if" return IF;
"else" return ELSE;
"print" return PRINT;
[ \t\n]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
这里是calc3.h
typedef enum { typeCon, typeId, typeOpr } nodeEnum;
/* constants */
typedef struct {
int value; /* value of constant */
} conNodeType;
/* identifiers */
typedef struct {
int i; /* subscript to sym array */
} idNodeType;
/* operators */
typedef struct {
int oper; /* operator */
int nops; /* number of operands */
struct nodeTypeTag **op; /* operands */
} oprNodeType;
typedef struct nodeTypeTag {
nodeEnum type; /* type of node */
union {
conNodeType con; /* constants */
idNodeType id; /* identifiers */
oprNodeType opr; /* operators */
};
} nodeType;
extern int sym[26];
这里是calc3.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "calc3.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 */
nodeType *nPtr; /* node pointer */
};
%token <iValue> INTEGER
%token <sIndex> VARIABLE
%token WHILE IF PRINT
%nonassoc IFX
%nonassoc ELSE
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <nPtr> stmt expr stmt_list
%%
program:
function { exit(0); }
;
function:
function stmt { ex(); freeNode(); }
| /* NULL */
;
stmt:
';' { $$ = opr(';', 2, NULL, NULL); }
| expr ';' { $$ = ; }
| PRINT expr ';' { $$ = opr(PRINT, 1, ); }
| VARIABLE '=' expr ';' { $$ = opr('=', 2, id(), ); }
| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, , ); }
| IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, , ); }
| IF '(' expr ')' stmt ELSE stmt { $$ = opr(IF, 3, , , ); }
| '{' stmt_list '}' { $$ = ; }
;
stmt_list:
stmt { $$ = ; }
| stmt_list stmt { $$ = opr(';', 2, , ); }
;
expr:
INTEGER { $$ = con(); }
| VARIABLE { $$ = id(); }
| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, ); }
| expr '+' expr { $$ = opr('+', 2, , ); }
| expr '-' expr { $$ = opr('-', 2, , ); }
| expr '*' expr { $$ = opr('*', 2, , ); }
| expr '/' expr { $$ = opr('/', 2, , ); }
| expr '<' expr { $$ = opr('<', 2, , ); }
| expr '>' expr { $$ = opr('>', 2, , ); }
| expr GE expr { $$ = opr(GE, 2, , ); }
| expr LE expr { $$ = opr(LE, 2, , ); }
| expr NE expr { $$ = opr(NE, 2, , ); }
| expr EQ expr { $$ = opr(EQ, 2, , ); }
| '(' expr ')' { $$ = ; }
;
%%
nodeType *con(int value) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeCon;
p->con.value = value;
return p;
}
nodeType *id(int i) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeId;
p->id.i = i;
return p;
}
nodeType *opr(int oper, int nops, ...) {
va_list ap;
nodeType *p;
int i;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
if ((p->opr.op = malloc(nops * sizeof(nodeType *))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeOpr;
p->opr.oper = oper;
p->opr.nops = nops;
va_start(ap, nops);
for (i = 0; i < nops; i++)
p->opr.op[i] = va_arg(ap, nodeType*);
va_end(ap);
return p;
}
void freeNode(nodeType *p) {
int i;
if (!p) return;
if (p->type == typeOpr) {
for (i = 0; i < p->opr.nops; i++)
freeNode(p->opr.op[i]);
free (p->opr.op);
}
free (p);
}
void yyerror(char *s) {
fprintf(stdout, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}
如果你只是使用
flex calc3.l
然后 flex 生成一个名为 lex.yy.c
的扫描仪。 (我删除了原始问题中使用的 -l
选项。-l
使 flex 与原始 lex 实用程序的某些方面更加兼容,并且除了编译古老的 lex 扫描器之外没有任何用处。 )
同样,如果你只是使用
yacc -vd calc3.y
野牛将生成名为 y.tab.c
和 y.tab.h
的文件。并且
gcc y.tab.c -lm -ll
将生成一个名为 a.out
的文件。
None 那是个好主意。最好根据输入的文件名给文件起有意义的名字。所有这三个工具都理解 -o
指定输出名称文件的命令行标志。
所以你可以这样做:
flex calc3.l
yacc -vd calc3.y
gcc lex.yy.c y.tab.c -lm -ll
但我会推荐这样的东西:
flex -o calc3.lex.c calc3.l
bison -o calc3.tab.c -vd calc3.y
gcc -o calc3 calc3.lex.c calc3.tab.c -lm -ll
执行此操作时,您需要将 #include "y.tab.h"
更改为 #include "calc3.tab.h"
。 (请注意,如果您将 bison 调用为 bison
而不是 yacc
,它会自动生成名称基于语法文件的输出文件。但是明确无误。)
如果你把它放在一个 Makefile 中,或者至少是一个脚本文件中,那就更好了。
我正在尝试 运行 我在网上找到的计算器示例。但是每次我 运行 我的 gcc 命令都会显示这个错误。这是我 运行:
的命令flex -l calc3.l
yacc -vd calc3.y
gcc y.tab.c -lm -ll
-> 此时我收到此错误消息:
/tmp/ccPOq58f.o : In function 'yyparse':
y.tab.c: undefined reference to 'yylex'
collect2: error: ld returned 1 exit status
这是我的代码:
calc3.l
%{
#include <stdlib.h>
#include "calc3.h"
#include "y.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 GE;
"<=" return LE;
"==" return EQ;
"!=" return NE;
"while" return WHILE;
"if" return IF;
"else" return ELSE;
"print" return PRINT;
[ \t\n]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
这里是calc3.h
typedef enum { typeCon, typeId, typeOpr } nodeEnum;
/* constants */
typedef struct {
int value; /* value of constant */
} conNodeType;
/* identifiers */
typedef struct {
int i; /* subscript to sym array */
} idNodeType;
/* operators */
typedef struct {
int oper; /* operator */
int nops; /* number of operands */
struct nodeTypeTag **op; /* operands */
} oprNodeType;
typedef struct nodeTypeTag {
nodeEnum type; /* type of node */
union {
conNodeType con; /* constants */
idNodeType id; /* identifiers */
oprNodeType opr; /* operators */
};
} nodeType;
extern int sym[26];
这里是calc3.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "calc3.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 */
nodeType *nPtr; /* node pointer */
};
%token <iValue> INTEGER
%token <sIndex> VARIABLE
%token WHILE IF PRINT
%nonassoc IFX
%nonassoc ELSE
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <nPtr> stmt expr stmt_list
%%
program:
function { exit(0); }
;
function:
function stmt { ex(); freeNode(); }
| /* NULL */
;
stmt:
';' { $$ = opr(';', 2, NULL, NULL); }
| expr ';' { $$ = ; }
| PRINT expr ';' { $$ = opr(PRINT, 1, ); }
| VARIABLE '=' expr ';' { $$ = opr('=', 2, id(), ); }
| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, , ); }
| IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, , ); }
| IF '(' expr ')' stmt ELSE stmt { $$ = opr(IF, 3, , , ); }
| '{' stmt_list '}' { $$ = ; }
;
stmt_list:
stmt { $$ = ; }
| stmt_list stmt { $$ = opr(';', 2, , ); }
;
expr:
INTEGER { $$ = con(); }
| VARIABLE { $$ = id(); }
| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, ); }
| expr '+' expr { $$ = opr('+', 2, , ); }
| expr '-' expr { $$ = opr('-', 2, , ); }
| expr '*' expr { $$ = opr('*', 2, , ); }
| expr '/' expr { $$ = opr('/', 2, , ); }
| expr '<' expr { $$ = opr('<', 2, , ); }
| expr '>' expr { $$ = opr('>', 2, , ); }
| expr GE expr { $$ = opr(GE, 2, , ); }
| expr LE expr { $$ = opr(LE, 2, , ); }
| expr NE expr { $$ = opr(NE, 2, , ); }
| expr EQ expr { $$ = opr(EQ, 2, , ); }
| '(' expr ')' { $$ = ; }
;
%%
nodeType *con(int value) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeCon;
p->con.value = value;
return p;
}
nodeType *id(int i) {
nodeType *p;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeId;
p->id.i = i;
return p;
}
nodeType *opr(int oper, int nops, ...) {
va_list ap;
nodeType *p;
int i;
/* allocate node */
if ((p = malloc(sizeof(nodeType))) == NULL)
yyerror("out of memory");
if ((p->opr.op = malloc(nops * sizeof(nodeType *))) == NULL)
yyerror("out of memory");
/* copy information */
p->type = typeOpr;
p->opr.oper = oper;
p->opr.nops = nops;
va_start(ap, nops);
for (i = 0; i < nops; i++)
p->opr.op[i] = va_arg(ap, nodeType*);
va_end(ap);
return p;
}
void freeNode(nodeType *p) {
int i;
if (!p) return;
if (p->type == typeOpr) {
for (i = 0; i < p->opr.nops; i++)
freeNode(p->opr.op[i]);
free (p->opr.op);
}
free (p);
}
void yyerror(char *s) {
fprintf(stdout, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}
如果你只是使用
flex calc3.l
然后 flex 生成一个名为 lex.yy.c
的扫描仪。 (我删除了原始问题中使用的 -l
选项。-l
使 flex 与原始 lex 实用程序的某些方面更加兼容,并且除了编译古老的 lex 扫描器之外没有任何用处。 )
同样,如果你只是使用
yacc -vd calc3.y
野牛将生成名为 y.tab.c
和 y.tab.h
的文件。并且
gcc y.tab.c -lm -ll
将生成一个名为 a.out
的文件。
None 那是个好主意。最好根据输入的文件名给文件起有意义的名字。所有这三个工具都理解 -o
指定输出名称文件的命令行标志。
所以你可以这样做:
flex calc3.l
yacc -vd calc3.y
gcc lex.yy.c y.tab.c -lm -ll
但我会推荐这样的东西:
flex -o calc3.lex.c calc3.l
bison -o calc3.tab.c -vd calc3.y
gcc -o calc3 calc3.lex.c calc3.tab.c -lm -ll
执行此操作时,您需要将 #include "y.tab.h"
更改为 #include "calc3.tab.h"
。 (请注意,如果您将 bison 调用为 bison
而不是 yacc
,它会自动生成名称基于语法文件的输出文件。但是明确无误。)
如果你把它放在一个 Makefile 中,或者至少是一个脚本文件中,那就更好了。