Я пытаюсь сделать лексический анализатор, используя flex. Для удобства я хочу скомпилировать свой scanner.l
в lex.yy.cc
, а затем скомпилировать файл .cc
командой:
g++ lex.yy.cc -lfl
.
-lfl
обязателен. Затем g++ выдал мне следующее сообщение об ошибке: неопределенная ссылка на 'yylex'
Вот краткий снимок моего scanner.l
%{
...
#include ...
extern "C" int yylex();
...
%}
...
%option c++
%option noyywrap
%%
/* rules */
%%
Я провел некоторое исследование, переполнение стека говорит, что это должно быть исправлено добавлением extern "C" int yylex();
. Однако этого не произошло.
Я использую flex 2.6.4
на удаленной (из школы) Linux-машине.
Вы проверили содержимое lex.yy.c
, чтобы убедиться, что yylex
был сгенерирован?
@TedLyngmo, я подумал, что flex
должен дать мне определение.
@john Нет, нет. Разве flex
не должен помочь мне сгенерировать yylex
?
TL;DR: удалить %option c++
.
-lfl
обязателен.
Вы уверены? libfl предоставляет только две функции: yywrap()
, которые вам не нужны из-за
%option noyywrap
, и main()
, которые вам не нужны, если вы предоставите свои main()
. main()
в libfl просто вызывает yylex()
снова и снова, пока последний не сигнализирует об окончании ввода, что, безусловно, является причиной зависимости от yylex()
в вашем случае.
Если у вас есть какое-то внешнее требование полагаться на libfl для вашей программы main
, то вы выстрелили себе в ногу, указав
%option c++
. Этот вариант больше касается API, который будет предоставлять сгенерированный сканер, чем языка, который будет использоваться для его компиляции. Вам нужно скомпилировать как C++, если вы его используете, но вы все равно можете скомпилировать как C++, если вы этого не делаете. Вы должны опустить эту опцию, чтобы иметь yylex()
в качестве точки входа сканера.
Объявление связи C для yylex()
— это то, что вы делаете, если планируете опустить %option c++
, скомпилировать с помощью компилятора C++ и связать с другим кодом (например, libfl), который ожидает интерфейс C для yylex()
. Но это редко бывает выгодной комбинацией, потому что типы действий, которые должен выполнять типичный сканер, не сильно выигрывают от C++ по сравнению с C. Таким образом, если вы хотите, чтобы интерфейс C yylex()
, то обычно чище просто напишите действия на C и скомпилируйте сканер с помощью компилятора C. И, конечно же, вы все еще можете вызывать это из C++, если хотите.
Чтобы уточнить, я имел в виду, что это требуется ТА.
Спасибо, это исправлено. lex,yy.c
теперь скомпилирован g++
отлично.
Вам также нужно определение
yylex
. Сейчас у вас есть только декларация.