c++ - 将 Boost.Spirit.X3 解析器拆分为多个 TU

标签 c++ boost boost-spirit boost-spirit-x3 translation-unit

我又在为 Boost.Spirit.X3 苦苦挣扎。

我有几个逻辑解析器组(语句、表达式等),每个解析器都由几个文件表示:

  • group.hpp - 包含 typedef年代,BOOST_SPIRIT_DECLAREextern那些在“外部”使用的解析器的变量声明
  • group_def.hpp - 包括前一个并包含解析器的实际定义,BOOST_SPIRIT_DEFINE
  • group.cpp - 包括前一个并包含显式模板实例化(通过 BOOST_SPIRIT_INSTANTIATE )

  • 基本上,它或多或少遵循官方tutorial中提出的结构。 .唯一的区别是我的语法要复杂得多,所以我试图把它分成几个翻译单元。然后将所有这些 TU 编译到一个库中,然后将其链接到主可执行文件。

    我试着做一个“最小”的例子here (生活在 Wandbox 上)因为在这里列出所有文件会很不方便。
    但是它不起作用因为一些 Unresolved external 因素,所以,很可能,我错误地实例化了一些东西,但我已经为此花了大约一周的时间,所以我很绝望,不觉得我能够自己处理这个.

    几个问题和答案:

    为什么我更喜欢每个“组”使用三个文件?

    首先,因为我试图以这样一种方式制作它,即我不想在任何小的更改上重新编译所有内容(不确定我是否成功了),所以我的想法是 somegroup.hpp只是一个带有声明的“轻量级”标题,somegroup_def.hpp是带有定义的标题,somegroup.cpp仅用于创建翻译单元。

    二、我拆分_def.hpp.cpp因为我还包括这些_def.hpp -文件直接用于测试,我不仅涵盖extern解析器,还有“内部”辅助的。

    为什么我使用 extern变量?

    我也尝试使用返回解析器的函数(类似于教程中的完成方式)。基本上,这就是它的实现方式和现在的工作方式。我不喜欢它,例如,给定一个解析器 lang::parser::import ,我必须给函数另一个名称( lang::parser::import_ )或将其放在另一个命名空间中(即 lang::import )。另外,我喜欢直接使用解析器的方式,它是如何在 Spirit 本身中完成的(即没有括号: importimport_() )。

    我的实际问题如下:
  • 如果我想将解析器分布在多个翻译单元上,如何正确组织结构?
  • 我在上面的代码示例中究竟遗漏了什么,所以它没有链接?

  • 我将不胜感激任何帮助。

    最佳答案

    Why do I prefer using three files per "group"?



    我,我自己,找到分离到grammar_def.hppgrammar.cpp没用,但这只是一种意见。

    Why am I using extern variables?

    I tried it also with functions that return parsers instead



    不要这样做。这将导致静态初始化命令惨败。规则占位符足够轻量级,可以在每个翻译单元中实例化它们。

    How to properly organize the structure if I want to spread my parsers over several translation units?



    这是一个关于口味的问题。您只需要在其中一个 TU 中实例化一个规则并拥有一个 x3::rule<...> + BOOST_SPIRIT_DECLARE在使用它的每个其他人中。

    实现这一目标的最佳方法是拆分 x3::rule<...>关闭 .cpp/_def.hpp放入单独的 header 中(将其放入“轻量级” .hpp 中),并将其包含在需要这些规则的每个 TU 中。

    https://github.com/mapnik/mapnik/pull/4072/fileshttps://github.com/boostorg/spirit/pull/493/files

    And what exactly am I missing in the example of code above, so that it doesn't link?


  • 你在混std::string::const_iteratorstd::string::iterator迭代器。
  • 您正在使用您的一些 skipper 作为解析器(例如 document_def = eols >> +megarule >> eols),但不要使用适当的上下文实例化它们。要么干脆不让它们成为规则,要么添加 BOOST_SPIRIT_INSTANTIATE带有您在错误消息中看到的上下文。
  • 关于c++ - 将 Boost.Spirit.X3 解析器拆分为多个 TU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59709229/

    相关文章:

    c++ - 在 vector 中存储两个不同的类对象

    c++ - Boost spirit 计算器示例运行

    c++ - 在 C++ 中标记 "Braced Initializer List"样式的字符串(使用 Boost?)

    c++ - boost::spirit 带有参数的惰性解析器?

    c++ - 重载 '>>' 运算符时出错

    c++ - 来自一个源目录的 Makefile 试图从其他目录访问 cpp 文件

    c++ - 有没有办法在信号量或输入事件发生之前阻塞单个线程?

    c++ - 标记枚举的非侵入式 Boost 序列化 C++

    c++ - Boost矩阵的iterator1和iterator2是什么,如何使用?

    c++ - 将 regex_search 与 std::string 一起使用时的无限循环