问题
I am trying to parse one input file using flex and bison but I am facing one difficulty while compiling my program. I am attaching my flex and bison code and error which I am getting.
Please help me out to solve these errors
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);
}
I build these using:
flex bas.l
bison -d yacc.y
g++ lex.yy.c yacc.tab.c -lfl -o scanner.exe
While compiling program I found following errors:
/tmp/cceIyDkD.o: In function `main':
yacc.tab.c:(.text+0x708): multiple definition of `main'
/tmp/ccatq95p.o:lex.yy.c:(.text+0x1228): first defined here
/usr/bin/ld: Warning: size of symbol `main' changed from 86 in /tmp/ccatq95p.o to 120 in /tmp/cceIyDkD.o
/tmp/cceIyDkD.o: In function `yyparse()':
yacc.tab.c:(.text+0x2d6): undefined reference to `yylex'
collect2: ld returned 1 exit status
Please help me out
回答1:
You have some errors in the code which stop it from compiling. You need to add into the file yacc.y:
%token <sval> TOK_EMPTY_LINE
and at the end:
#include "lex.yy.c"
and build this way:
flex bas.l
bison -d yacc.y
g++ yacc.tab.c -lfl -o scanner.exe
You will find it now compiles.
You may want to note I removed a couple of typos in your lexer source in the question. Not all the the rules started in the first column. I removed a couple of leading spaces on the basis that they were typos.
回答2:
In parser.y, more precisely C part of the code where you include stuff, you need to write:
extern int yylex(void);
. Extern keyword is not needed, because global functions by default have dynamic connectivity, but it is good practice to write keyword to point that function is not from that file you're working. Your code has no mistake here however.Compile lex.yy.c to the object file, compile y.tab.c to object file and then link them together in final program. It is very important to first do
yacc
command, because Lex is using yacc.tab.h generated with Yacc. You're getting error because you flex it, but you don't know what yacc.tab.h is.yacc -d yacc.y
Make y.tab.cg++ -c y.tab.c -o y.tab.o
Compile y.tab.c to object file y.tab.oflex lex.l
Make lex.yy.cg++ -c lex.yy.c -o lex.yy.o
Compile lex.yy.c to object file lex.yy.og++ lex.yy.o y.tab.o -o program
Link them together.
Note: Make sure that in your lex file you include "y.tab.h" after other includes, because it is possible that other includes use some function declared in y.tab.h, so have that in mind. Situations like this can occur when you're writing more complex parsers.
来源:https://stackoverflow.com/questions/34782625/undefined-reference-to-yylex