Я пытаюсь найти простой пример, который я нашел в Интернете, который реализует счетчик Word с помощью flex и bison.Ниже приведены файлы .y и .l:
mc_lexer.l
%{
/* C++ string header, for string ops below */
#include <string>
/* Implementation of yyFlexScanner */
#include "mc_scanner.hpp"
#undef YY_DECL
#define YY_DECL int MC::MC_Scanner::yylex( MC::MC_Parser::semantic_type *
const lval, MC::MC_Parser::location_type *loc )
/* typedef to make the returns for the tokens shorter */
using token = MC::MC_Parser::token;
/* define yyterminate as this instead of NULL */
#define yyterminate() return( token::END )
/* msvc2010 requires that we exclude this header file. */
#define YY_NO_UNISTD_H
/* update location on matching */
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
%}
%option debug
%option nodefault
%option yyclass="MC::MC_Scanner"
%option noyywrap
%option c++
%%
%{ /** Code executed at the beginning of yylex **/
yylval = lval;
%}
[a-z] {
return( token::LOWER );
}
[A-Z] {
return( token::UPPER );
}
[a-zA-Z]+ {
yylval->build< std::string >( yytext );
return( token::WORD );
}
%%
mc_parser.yy
%skeleton "lalr1.cc"
%require "3.0"
%debug
%defines
%define api.namespace {MC}
%define parser_class_name {MC_Parser}
%code requires{
namespace MC {
class MC_Driver;
class MC_Scanner;
}
%parse-param { MC_Scanner &scanner }
%parse-param { MC_Driver &driver }
%code{
#include <iostream>
#include <cstdlib>
#include <fstream>
/* include for all driver functions */
#include "mc_driver.hpp"
#undef yylex
#define yylex scanner.yylex
}
... / * остальная часть файла */
mc_scanner.hpp
#if ! defined(yyFlexLexerOnce)
#include <FlexLexer.h>
#endif
#include "mc_parser.tab.hh"
#include "location.hh"
namespace MC{
class MC_Scanner : public yyFlexLexer{
public:
MC_Scanner(std::istream *in) : yyFlexLexer(in)
{};
virtual ~MC_Scanner() {};
//get rid of override virtual function warning
using FlexLexer::yylex;
virtual
int yylex( MC::MC_Parser::semantic_type * const lval,
MC::MC_Parser::location_type *location );
// YY_DECL defined in mc_lexer.l
// Method body created by flex in mc_lexer.yy.cc
private:
/* yyval ptr */
MC::MC_Parser::semantic_type *yylval = nullptr;
};
} /* end namespace MC */
Когда я собираю с помощью Makefile, который нашел в сети, сборка завершается успешно.Когда я пытался протестировать его с помощью моей системы сборки, компилятор жалуется на следующие строки кода:
#undef yylex
#define yylex scanner.yylex
Поскольку MC_Scanner просто объявлен в файле .yy, компилятор жалуется, что тип сканеранеизвестноТеперь я не могу включить «mc_scanner.hpp» в файл .y, потому что он вводит циклическую зависимость.
Круговая зависимость: файл сканера mc_scanner.hpp зависит от mc_parser.tab.hh, потому что он должен знать, что такое semantic_type.mc_parser.tab.hh генерируется mc_parser.y.
Теперь mc_parser.y имеет следующие строки кода:
#undef yylex
#define yylex scanner.yylex
А сканер объявлен следующим образом:
%code requires{
namespace MC {
class MC_Driver;
class MC_Scanner;
}
%parse-param { MC_Scanner &scanner }
%parse-param { MC_Driver &driver }
Таким образом, компилятор жалуется, что не может определитьтип сканера.И я не могу включить mc_scanner.hpp в mc_parser.y из-за этой циклической зависимости.
Есть какие-нибудь идеи относительно того, как я мог бы сломать эту зависимость?