Flex Lexer工具中的类istream

时间:2016-01-04 11:55:39

标签: c++ flex-lexer lexer

我在使用2.5.4版本的flex中面临一些问题而无法找出问题。最近,Rhel机器从5升级到6.5。

  1. 我可以将class istream替换为#include <isotream> using namespace std;
  2. 吗?
  3. 如果是,我应该写入lexer.l文件。
  4. 在flex-2.5.3中,它仅使用命名空间std生成#include<iostream>
  5. 我无法使用flex-2.5.3,因为它不支持RHEL5机器。
  6. lexer.l(修改以创建简单的测试用例)

    {
    /* need this for the call to atof() below */
    #include <math.h>
    #include <string>
    #include <iostream>
    
    #undef yyFlexLexer
    #define yyFlexLexer hSpiceConverterFlexer
    #include "kernel.h"
    using namespace std;
    static bool a = true;
    %}
    
    %option c++ debug
    
    %%
    
    %{
    string copyText;
    %}
    
    %%
    

    生成的扫描程序文件(文件很大,因此添加问题部分)

    /* A lexical scanner generated by flex */
    
    /* Scanner skeleton version:
     * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
     */
    
    #define FLEX_SCANNER
    #define YY_FLEX_MAJOR_VERSION 2
    #define YY_FLEX_MINOR_VERSION 5
    
    
    
    /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
    #ifdef c_plusplus
    #ifndef __cplusplus
    #define __cplusplus
    #endif
    #endif
    
    
    #ifdef __cplusplus
    
    #include <stdlib.h>
    class istream;
    #include <unistd.h>
    

    如果class istream替换为<iostream> using namespace std;,我可以使用gcc编译

    我用class istream得到的错误

    ex.yy.cc: In member function ¡virtual int hSpiceConverterFlexer::yylex()¢:
    lex.yy.cc:987:37: error: cannot convert ¡std::istream* {aka std::basic_istream<char>*}¢ to ¡istream*¢ in assignment
    lex.yy.cc: At global scope:
    lex.yy.cc:1095:25: error: expected constructor, destructor, or type conversion before ¡(¢ token
    lex.yy.cc:1130:35: error: variable or field ¡switch_streams¢ declared void
    lex.yy.cc:1130:35: error: reference to ¡istream¢ is ambiguous
    lexer.cpp:24:7: note: candidates are: class istream
     class istream;
           ^
    In file included from /depotbld/RHEL6.0/gcc-4.8.2/include/c++/4.8.2/ios:38:0,
                     from /depotbld/RHEL6.0/gcc-4.8.2/include/c++/4.8.2/ostream:38,
                     from /depotbld/RHEL6.0/gcc-4.8.2/include/c++/4.8.2/iostream:39,
                     from ../include/FlexLexer.h:47,
                     from lexer.cpp:239:
    /depotbld/RHEL6.0/gcc-4.8.2/include/c++/4.8.2/iosfwd:133:33: note:                 typedef class std::basic_istream<char> std::istream
       typedef basic_istream<char>   istream;
                                     ^
    lex.yy.cc:1130:44: error: ¡new_in¢ was not declared in this scope
    lex.yy.cc:1130:59: error: expected primary-expression before ¡*¢ token
    lex.yy.cc:1130:61: error: ¡new_out¢ was not declared in this scope
    lexer.cpp:209:14: warning: ¡void* yy_flex_alloc(yy_size_t)¢ declared ¡static¢ but never defined [-Wunused-function]
     static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
                  ^
    lexer.cpp:210:14: warning: ¡void* yy_flex_realloc(void*, yy_size_t)¢ declared ¡static¢ but never defined [-Wunused-function]
     static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
                  ^
    lexer.cpp:211:13: warning: ¡void yy_flex_free(void*)¢ declared ¡static¢ but never defined [-Wunused-function]
     static void yy_flex_free YY_PROTO(( void * ));
    

1 个答案:

答案 0 :(得分:1)

这个问题不太可能是由flex 2.5.4的变化引起的。 2.5.3和2.5.4之间的差异很小。更有可能的是,flex 2.5.3和2.5.4都不兼容RHEL 6.5中包含的标准C ++库版本

据我了解,RHEL 6.5的flex版本为2.5.35,虽然距离最新版本很远,但与现代版本相近。升级到该版本应该可以解决问题,因为它使用了一组更正常的C ++包含。

经过一些实验,我使用gcc-4.8和flex 2.5.4成功编译了一个带有C ++ API的简单flex文件。为此,我使用以下补丁文件创建了一个稍微修改过的flex.skl文件:

--- flex.skl    1996-09-10 18:58:54.000000000 -0500
+++ flex.skl.new        2016-01-05 23:16:36.435900415 -0500
@@ -8,9 +8,7 @@
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5

-%-
 #include <stdio.h>
-%*


 /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
@@ -25,7 +23,8 @@

 #include <stdlib.h>
 %+
-class istream;
+#include <iostream>
+using namespace std;
 %*
 #include <unistd.h>

另外,2.5.4分发引用iostream.h中包含的FlexLexer.h文件。您可能需要将其更改为iostream

完成后,我可以用:

生成C ++文件
flex-2.5.4 -Sflex.skl.new ...

从上面的补丁中可以看出,修复包括:

  • 始终包括stdio.h。如果您不这样做,则EOF未定义。
  • 删除istream的转发声明并将其替换为#include <iostream>。由于无论如何都会包含该标题,因此似乎可以更早地包含它。
  • 添加using namespace std;,与flex 2.5.4中的用法相匹配。显然,它设计使用的C ++标准库没有将标准原型放入std命名空间。

我仍然认为使用古老的flex版本不是一个好主意,我鼓励你升级到最新的稳定版本(目前是2.5.39),或者至少升级到2.5.35。如果您遇到一些问题,请尝试创建一个Minimal Compilable示例并提交一个单独的问题。