我正在尝试使用flex和bison解析一个输入文件,但是在编译程序时我遇到了一个困难。我正在附加我的flex和bison代码以及我得到的错误。
请帮我解决这些错误
lex.l
%{
#include <iostream>
#include <stdio.h>
#include "yacc.tab.h"
#define YY_DECL extern "C" int yylex()
using namespace std;
%}
DOT "."
COLON ":"
SEMICOLON ";"
COMMA ","
ANGLE_LEFT "<"
ANGLE_RIGHT ">"
AT "@"
EQUAL "="
SQUARE_OPEN "["
SQUARE_CLOSE [^\\]"]"
OPENBRACE "\("
CLOSEBRACE "\)"
QUOTE "\""
QUOTE_OPEN "\""
QUOTE_CLOSE [^\\]"\""
SPACE " "
TAB "\t"
CRLF "\r\n"
QUOTED_PAIR "\\"[^\r\n]
DIGIT [0-9]
ALPHA [a-zA-Z]
QTEXT [0-9a-zA-Z!#$%&'()*+,\-.\/:;<=>?@\[\]^_`{|}~]
%%
[a-zA-Z0-9]+ { yylval.sval = strdup(yytext); return TOK_STRING; }
{SPACE}* {return TOK_SPACE; }
{SPACE}*Name.* {return TOK_NAME; }
{SPACE}*SIZE.* {return TOK_SIZE; }
{SPACE}*ITERATE.* {return TOK_ITERATE; }
{SPACE}*DIRECTION.* {return TOK_DIRECTION; }
^{CRLF} { return TOK_EMPTY_LINE; }
{CRLF} {}
. {}/* ignore unknown chars */
yacc.y
%{
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdio.h>
using namespace std;
extern "C" int yylex();
extern "C" FILE *yyin;
void yyerror(const char* s);
%}
%union
{
char* sval;
};
%token <sval> TOK_NAME
%token <sval> TOK_SIZE
%token <sval> TOK_STRING
%token <sval> TOK_ITERATE
%token <sval> TOK_DIRECTION
%token TOK_SPACE
%%
str:
TOK_SPACE TOK_NAME TOK_SPACE TOK_STRING
{
cout << "Value:" << $2 << "->" << $4;
}
;
%%
int main(void) {
FILE * pt = fopen("new file ", "r" );
if(!pt)
{
cout << "Bad Input.Noexistant file" << endl;
return -1;
}
yyin = pt;
do
{
yyparse();
}while (!feof(yyin));
}
void yyerror(const char *s)
{
cout << "Error. " << s << endl;
exit(-1);
}
我使用以下方法构建这些:
flex bas.l
bison -d yacc.y
g++ lex.yy.c yacc.tab.c -lfl -o scanner.exe
编译程序时,我发现以下错误:
/tmp/cceIyDkD.o:在函数`main'中:
yacc.tab.c :(。text + 0x708):`main'的多重定义
/tmp/ccatq95p.o:lex.yy.c:(.text+0x1228):这里首先定义
/ usr / bin / ld:警告:符号“main”的大小从/tmp/ccatq95p.o中的86更改为/tmp/cceIyDkD.o中的120 /tmp/cceIyDkD.o:在函数`yyparse()'中:
yacc.tab.c :(。text + 0x2d6):未定义的引用`yylex'
collect2:ld返回1退出状态
请帮帮我
答案 0 :(得分:3)
代码中存在一些错误,导致编译停止。您需要将 yacc.y :
添加到文件中%token <sval> TOK_EMPTY_LINE
最后:
#include "lex.yy.c"
以这种方式构建:
flex bas.l
bison -d yacc.y
g++ yacc.tab.c -lfl -o scanner.exe
你会发现它现在已编译。
您可能需要注意我在问题中删除了lexer源中的几个拼写错误。并非所有规则都在第一列中开始。我删除了几个前导空格,因为它们是拼写错误。
答案 1 :(得分:2)
在parser.y中,更准确地说是包含内容的代码的C部分,您需要编写:extern int yylex(void);
。不需要Extern关键字,因为默认情况下全局函数具有动态连接,但最好将关键字写入指向该函数不是来自您正在使用的文件。但是,你的代码没有错。
将lex.yy.c编译到目标文件,将y.tab.c编译为目标文件,然后在最终程序中将它们链接在一起。 首先执行yacc
命令非常重要,因为Lex正在使用yacc生成的yacc.tab.h。因为你弯曲它而得到错误,但是你不知道是什么yacc.tab.h。
yacc -d yacc.y
制作y.tab.c
g++ -c y.tab.c -o y.tab.o
将y.tab.c编译为目标文件y.tab.o
flex lex.l
制作lex.yy.c
g++ -c lex.yy.c -o lex.yy.o
将lex.yy.c编译到目标文件lex.yy.o
g++ lex.yy.o y.tab.o -o program
将它们链接在一起。
注意:确保在你的lex文件中包含“y.tab.h”之后的其他包含,因为其他包含可能会使用y.tab.h中声明的某个函数,所以记住这一点。当您编写更复杂的解析器时,可能会出现这种情况。
答案 2 :(得分:0)
我有一个类似的问题,事实证明flex 2.6.x改变了yylex的行为方式。我通过使用旧版本的Flex解决了这个问题。在Ubuntu中,有一个名为flex-old的软件包,它是较旧的版本。用flex-old代替flex为我解决了这个问题。