【问题标题】:How can I run Wave quick start example?如何运行 Wave 快速入门示例?
【发布时间】:2021-01-21 18:36:42
【问题描述】:

(源自this问题。)

我尝试使用this 示例失败。

我的尝试是复制并稍微编辑链接处的代码。结果是这样的(我留下了 Boost 网站的评论,以便更容易地将我的编辑与原始版本进行比较):

#include <boost/wave.hpp>
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>

int main() {
    // The following preprocesses a given input file.
    // Open the file and read it into a string variable
    std::string input("int main() { std::cout << \"Hello world\"; }");
    // The template boost::wave::cpplexer::lex_token<> is the  
    // token type to be used by the Wave library.
    // This token type is one of the central types throughout 
    // the library, because it is a template parameter to some 
    // of the public classes and templates and it is returned 
    // from the iterators.
    // The template boost::wave::cpplexer::lex_iterator<> is
    // the lexer iterator to use as the token source for the
    // preprocessing engine. In this case this is parameterized
    // with the token type.
    typedef boost::wave::cpplexer::lex_iterator<
            boost::wave::cpplexer::lex_token<> >
        lex_iterator_type;
    typedef boost::wave::context<
            std::string::iterator, lex_iterator_type>
        context_type;

    context_type ctx(input.begin(), input.end(), "preproc.cpp");

    // At this point you may want to set the parameters of the
    // preprocessing as include paths and/or predefined macros.
    //ctx.add_include_path("...");
    //ctx.add_macro_definition("...");

    // Get the preprocessor iterators and use them to generate 
    // the token sequence.
    context_type::iterator_type first = ctx.begin();
    context_type::iterator_type last = ctx.end();

    // The input stream is preprocessed for you during iteration
    // over [first, last)
    while (first != last) {
        std::cout << (*first).get_value();
        ++first;
    }
}

我可以成功编译

g++ -std=c++17 -lboost_thread -lboost_filesystem -lboost_wave source.cpp

但在运行可执行文件时出现此错误

terminate called after throwing an instance of 'boost::wrapexcept<boost::wave::preprocess_exception>'
  what():  boost::wave::preprocess_exception
Aborted (core dumped)

正如评论中所建议的,在将 std::cout &lt;&lt; (*first).get_value(); 更改为 std::cout &lt;&lt; (*first).get_value() &lt;&lt; '\n'; 后,显然在 EOF 处引发了异常。纯粹猜测,我尝试在input 末尾添加\n 并且程序运行良好,没有异常。

但是,当我将代码还原为链接示例时,input 是从文件中读取的,而不是硬编码的,

    //std::string input("int main() { std::cout << \"Hello world\"; }");
    std::ifstream instream("somefile.cpp");
    std::string input(
        std::istreambuf_iterator<char>(instream.rdbuf()),
        std::istreambuf_iterator<char>());

然后我得到了同样的错误。


一个问题似乎与字符串末尾缺少\n有关,因此更改此

    std::string input("int main() { std::cout << \"Hello world\"; }");

到这里

    std::string input("int main() { std::cout << \"Hello world\"; }\n");

似乎解决了这个问题。除了问题比这更广泛。确实,如果我在字符串中添加标题:

    std::string input("#include<iostream>\nint main() { std::cout << \"Hello world\"; }\n");

然后我得到同样的失败。最令人惊讶的是,如果我评论该标题:

    std::string input("//#include<iostream>\nint main() { std::cout << \"Hello world\"; }\n");

然后程序运行,但输出是:

#line 2 "/home/enrico/preproc.cpp"
int main() { std::cout << "Hello world"; }

我完全不知道#include&lt;iostream&gt; 是如何变成#line 2 "/home/enrico/preproc.cpp" 的。

【问题讨论】:

  • std::cout &lt;&lt; (*first).get_value &lt;&lt; '\n'; 将在引发该异常时更清楚。和/或登录到std::cerr 而不是std::cout
  • @rici,你的建议肯定很有用,但是我已经更新了这个问题。
  • 很高兴我能提供帮助。希望真正了解升压波预处理器的人能够为您提供更多帮助。 (提及该文件中的内容可能会有所帮助:-)。当然,还要检查您是否能够真正打开文件。
  • 您是否尝试过捕获异常并打印消息,或者您是否尝试过使用调试器?
  • 我也遇到了同样的预处理异常,解决方案是在输入文件的末尾添加换行符。确实很奇怪的行为。

标签: c++ parsing boost token lexer


【解决方案1】:

技术上没有尾随换行符is invalid 的 C 源文件。您必须确保末尾有换行符:

std::string input("int main() { std::cout << \"Hello world\"; }\n");

【讨论】:

  • 感谢您的调查。我可以再做一些实验。对我来说,如果我在int main 之前写#include&lt;iostream&gt;\n,程序会以同样的方式终止(terminate called after throwing ...)。所以问题似乎涉及更多。
  • 还有更奇怪的事情。我稍后会更新问题。
猜你喜欢
  • 2016-02-24
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
  • 1970-01-01
  • 2021-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多