在 Qt 中使用 Flex 和 Bison
Using Flex and Bison with Qt
我正在尝试将 flex 和 bison 与 qt.There 一起使用,许多关于 it.They 的网络资源都使用 QMAKE_EXTRA_COMPILERS 添加 precompile.But 我总是得到 LNK2019 的当我编译 code.My 代码时,yyerror 和 yywrap 如下:
专业文件
CONFIG += console
CONFIG -= app_bundle
LIBS += -lfl
FLEXSOURCES = lexer.l
BISONSOURCES = parser.y
OTHER_FILES += \
$$FLEXSOURCES \
$$BISONSOURCES
QT += core gui script
SOURCES += main.cpp
TEMPLATE = app
bisonsource.input = BISONSOURCES
bisonsource.output = ${QMAKE_FILE_BASE}.cpp
bisonsource.commands = bison -d --defines=${QMAKE_FILE_BASE}.h -o ${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_IN}
bisonsource.variable_out = SOURCES
bisonsource.name = Bison Sources ${QMAKE_FILE_IN}
bisonsource.CONFIG += target_predeps
QMAKE_EXTRA_COMPILERS += bisonsource
bisonheader.input = BISONSOURCES
bisonheader.output = ${QMAKE_FILE_BASE}.h
bisonheader.commands = @true
bisonheader.variable_out = HEADERS
bisonheader.name = Bison Headers ${QMAKE_FILE_IN}
bisonheader.CONFIG += target_predeps no_link
QMAKE_EXTRA_COMPILERS += bisonheader
flexsource.input = FLEXSOURCES
flexsource.output = ${QMAKE_FILE_BASE}.cpp
flexsource.commands = flex --header-file=${QMAKE_FILE_BASE}.h -o ${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_IN}
flexsource.variable_out = SOURCES
flexsource.name = Flex Sources ${QMAKE_FILE_IN}
flexsource.CONFIG += target_predeps
QMAKE_EXTRA_COMPILERS += flexsource
flexheader.input = FLEXSOURCES
flexheader.output = ${QMAKE_FILE_BASE}.h
flexheader.commands = @true
flexheader.variable_out = HEADERS
flexheader.name = Flex Headers ${QMAKE_FILE_IN}
flexheader.CONFIG += target_predeps no_link
QMAKE_EXTRA_COMPILERS += flexheader
lexer.l
%{
#include "parser.h"
extern void yyerror(const char *s);
%}
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
"(" { return OP; }
")" { return CP; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
\n { return EOL; }
"//".*
[ \t] { /* ignore white space */ }
. { yyerror("Mystery character\n"); }
%%
parser.y
%{
#include <stdio.h>
// yylex is a function generated by Flex and we must tell to Bison that it is
// defined in other place.
extern int yylex(void);
// Bison uses the yyerror function for informing us when a parsing error has
// occurred.
void yyerror(const char *s);
%}
/* declare tokens*/
%token NUMBER
%token ADD SUB MUL DIV ABS
%token OP CP
%token EOL
%%
calclist: /*nothing */
| calclist exp EOL { printf("= %d\n>", ); }
| calclist EOL { printf("> "); }/* blank line or a comment */
;
exp: factor
| exp ADD exp { $$ = + ; }
| exp SUB factor { $$ = - ; }
| exp ABS factor { $$ = | ; }
;
factor: term
| factor MUL term { $$ = * ; }
| factor DIV term { $$ = / ; }
;
term: NUMBER
| ABS term { $$ = >= 0? : - ; }
| OP exp CP { $$ = ; }
;
%%
void yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}
main.cpp
#include <QtCore>
// This header is generated by Flex.
#include "lexer.h"
// This header is generated by bison.
#include "parser.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QString str("1+1");
// Insert the string into the input stream.
YY_BUFFER_STATE bufferState = yy_scan_string(str.toUtf8().constData());
// Parse the string.
yyparse();
// flush the input stream.
yy_delete_buffer(bufferState);
return app.exec();
}
yywrap
未定义,因为您从未定义过它。你必须定义它,或者告诉 flex 它不需要。我假设你不需要它,所以你应该添加
%option noyywrap
到您的 flex 输入文件 (lexer.l
)。 (它在第一个 %%
之前,但不在序言内部(被 %{
和 %}
包围的部分。)(有关更多信息,请参阅 flex manual。)
yyerror
未定义(在词法分析器文件中),因为它是在解析器文件中定义的,并且您将解析器编译为 C++ 程序,同时将词法分析器编译为 C 程序。
您没有在这两个文件中使用 C++,因此您可以将它们都编译为 C。或者您可以将它们都编译为 C++。或者您可以将 yyerror 声明为 extern "C"
。如果将解析器编译为 C 程序,则需要在 main.cpp
中将 yyparse
声明为 extern "C"
,它使用 QT,因此必须是 C++。
我正在尝试将 flex 和 bison 与 qt.There 一起使用,许多关于 it.They 的网络资源都使用 QMAKE_EXTRA_COMPILERS 添加 precompile.But 我总是得到 LNK2019 的当我编译 code.My 代码时,yyerror 和 yywrap 如下:
专业文件
CONFIG += console
CONFIG -= app_bundle
LIBS += -lfl
FLEXSOURCES = lexer.l
BISONSOURCES = parser.y
OTHER_FILES += \
$$FLEXSOURCES \
$$BISONSOURCES
QT += core gui script
SOURCES += main.cpp
TEMPLATE = app
bisonsource.input = BISONSOURCES
bisonsource.output = ${QMAKE_FILE_BASE}.cpp
bisonsource.commands = bison -d --defines=${QMAKE_FILE_BASE}.h -o ${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_IN}
bisonsource.variable_out = SOURCES
bisonsource.name = Bison Sources ${QMAKE_FILE_IN}
bisonsource.CONFIG += target_predeps
QMAKE_EXTRA_COMPILERS += bisonsource
bisonheader.input = BISONSOURCES
bisonheader.output = ${QMAKE_FILE_BASE}.h
bisonheader.commands = @true
bisonheader.variable_out = HEADERS
bisonheader.name = Bison Headers ${QMAKE_FILE_IN}
bisonheader.CONFIG += target_predeps no_link
QMAKE_EXTRA_COMPILERS += bisonheader
flexsource.input = FLEXSOURCES
flexsource.output = ${QMAKE_FILE_BASE}.cpp
flexsource.commands = flex --header-file=${QMAKE_FILE_BASE}.h -o ${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_IN}
flexsource.variable_out = SOURCES
flexsource.name = Flex Sources ${QMAKE_FILE_IN}
flexsource.CONFIG += target_predeps
QMAKE_EXTRA_COMPILERS += flexsource
flexheader.input = FLEXSOURCES
flexheader.output = ${QMAKE_FILE_BASE}.h
flexheader.commands = @true
flexheader.variable_out = HEADERS
flexheader.name = Flex Headers ${QMAKE_FILE_IN}
flexheader.CONFIG += target_predeps no_link
QMAKE_EXTRA_COMPILERS += flexheader
lexer.l
%{
#include "parser.h"
extern void yyerror(const char *s);
%}
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"|" { return ABS; }
"(" { return OP; }
")" { return CP; }
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
\n { return EOL; }
"//".*
[ \t] { /* ignore white space */ }
. { yyerror("Mystery character\n"); }
%%
parser.y
%{
#include <stdio.h>
// yylex is a function generated by Flex and we must tell to Bison that it is
// defined in other place.
extern int yylex(void);
// Bison uses the yyerror function for informing us when a parsing error has
// occurred.
void yyerror(const char *s);
%}
/* declare tokens*/
%token NUMBER
%token ADD SUB MUL DIV ABS
%token OP CP
%token EOL
%%
calclist: /*nothing */
| calclist exp EOL { printf("= %d\n>", ); }
| calclist EOL { printf("> "); }/* blank line or a comment */
;
exp: factor
| exp ADD exp { $$ = + ; }
| exp SUB factor { $$ = - ; }
| exp ABS factor { $$ = | ; }
;
factor: term
| factor MUL term { $$ = * ; }
| factor DIV term { $$ = / ; }
;
term: NUMBER
| ABS term { $$ = >= 0? : - ; }
| OP exp CP { $$ = ; }
;
%%
void yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}
main.cpp
#include <QtCore>
// This header is generated by Flex.
#include "lexer.h"
// This header is generated by bison.
#include "parser.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QString str("1+1");
// Insert the string into the input stream.
YY_BUFFER_STATE bufferState = yy_scan_string(str.toUtf8().constData());
// Parse the string.
yyparse();
// flush the input stream.
yy_delete_buffer(bufferState);
return app.exec();
}
yywrap
未定义,因为您从未定义过它。你必须定义它,或者告诉 flex 它不需要。我假设你不需要它,所以你应该添加
%option noyywrap
到您的 flex 输入文件 (lexer.l
)。 (它在第一个 %%
之前,但不在序言内部(被 %{
和 %}
包围的部分。)(有关更多信息,请参阅 flex manual。)
yyerror
未定义(在词法分析器文件中),因为它是在解析器文件中定义的,并且您将解析器编译为 C++ 程序,同时将词法分析器编译为 C 程序。
您没有在这两个文件中使用 C++,因此您可以将它们都编译为 C。或者您可以将它们都编译为 C++。或者您可以将 yyerror 声明为 extern "C"
。如果将解析器编译为 C 程序,则需要在 main.cpp
中将 yyparse
声明为 extern "C"
,它使用 QT,因此必须是 C++。