我正在尝试一个在网上找到的简单示例,该示例使用flex和bison实现了Word计数器。以下是.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文件中声明,因此编译器会抱怨扫描器的类型未知。现在,我无法在.y文件中包含“ mc_scanner.hpp”,因为它将引入循环依赖关系。
循环依赖项:扫描程序文件mc_scanner.hpp依赖于mc_parser.tab.hh,因为它需要知道什么是语义类型。 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_parser.y中加入mc_scanner.hpp。
关于如何消除这种依赖性的任何想法?
答案 0 :(得分:0)
我解决了这个问题。我必须在语法块开始之前包括扫描程序类的头文件。