【问题标题】:How to use Boost Spirit with variant with more than 20 types?20多种变种的Boost Spirit如何使用?
【发布时间】:2012-07-22 18:26:45
【问题描述】:

我正在使用 Boost Spirit 解析一个相当复杂的语法,但我遇到了一个具有 20 多种类型(此处为 21 种)的变体的问题:

namespace eddic { namespace ast {

typedef boost::mpl::vector<
            Integer,
            IntegerSuffix,
            Float,
            Litteral,
            VariableValue,
            DereferenceValue,
            Expression,
            Unary,
            Null,
            True,
            False,
            ArrayValue,
            FunctionCall,
            MemberFunctionCall,
            Cast,
            BuiltinOperator,
            Assignment,
            SuffixOperation,
            PrefixOperation,
            Ternary
        > types_initial;

typedef boost::mpl::push_back<types_initial, New>::type types;
typedef boost::make_variant_over<types>::type Value;

}}

Boost Spirit 无法识别使用 push_back 添加的最后一个类型 (eddic::ast::New)。当我解析具有此元素的内容时,它会失败并出现以下错误:

eddic: /usr/include/boost/variant/detail/visitation_impl.hpp:264: 类型名访客::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with which = mpl_::int_;步骤 0 = boost::detail::variant::visitation_impl_step, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0> , 0>, 0>, 0>, 0>, 0l>, boost::mpl::v_iter, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0> , 0>, 0>, 0>, 0>, 21l> >;访客 = boost::variant, boost::mpl::vector, eddic::ast::延迟, eddic::ast::Deferred, eddic::ast::Null, eddic::ast::True, eddic::ast::False, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟 >, 0> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::assigner; voidPtrCV = 常量 void*; NoBackupFlag = boost::variant, boost::mpl::vector, eddic::ast::延迟, eddic::ast::Deferred, eddic::ast::Null, eddic::ast::True, eddic::ast::False, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟, eddic::ast::延迟 >, 0> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::has_fallback_type_;类型名称 访客::result_type = void; mpl_::false_ = mpl_::bool_]: 断言 `!"Boost.Variant 内部错误:'which' 超出范围。"' 失败了。

如果我交换两个元素(例如三元和新),则可以正确识别新,但不能正确识别三元。它只是失败的最后一个元素。

我已经尝试过使用 push_front 或 vector21,但它并没有改变任何东西,它总是有问题的最后一个元素。在我看来,这是因为 Spirit 在将其复制到我的 variant_over 类型之前在内部使用了一个变体。

这个问题有解决办法吗?

我可以将这个数字减少到 20 个,但问题是我将来肯定会拥有更多。

非常感谢您的任何想法

【问题讨论】:

  • 有什么理由不与经典 OO 混合?在单个 AST 类型中滚动所有操作(多态),所有函数调用同样如此等等。看起来好像您在 ast 中包含了标记器级别的详细信息(IntegerSuffix - 真的吗?)
  • 我不确定我是否理解。你的意思是继承树?像 Value 一样是 Integer 的基类吗?
  • 我想你明白了。问题是,根据我的经验,拥有一个巨大的变体几乎是一种代码味道。
  • @BaptisteWicht,你的 AST 怎么样了?我目前正在设计我的 AST,很快就会遇到同样的问题。
  • @PeteUK 我已经能够稍微简化一下(github.com/wichtounet/eddic/blob/develop/include/ast/Value.hpp)。我仍然认为它可以改进,特别是关于可能合并的常量和文字。但是,我不想让 AST 的处理变得更复杂。

标签: c++ boost-spirit boost-mpl


【解决方案1】:

BOOST_MPL_LIMIT_VECTOR_SIZE 定义为您想要的任何新限制,但达到这么高通常暗示设计存在问题,因此值得考虑一下。

【讨论】:

  • 我刚试过,但没有解决问题。 IMO,问题不来自 mpl::vector。我也试过 boost::mpl::vector21 问题是一样的。
  • 它似乎与BOOST_MPL_LIMIT_LIST_SIZE 相关,也许您需要将两者都增加到一个新的限制。
  • 抱歉,但您似乎还需要定义BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS,在操场上尝试过,这似乎达成了交易:P。还需要坚持 10 的增量。
  • 我做到了 ;) 因为没有它,我增加了 Boost 其他部分的问题。但这并没有解决问题。
  • 这很奇怪,因为BOOST_VARIANT_VISITATION_UNROLLING_LIMIT 设置为低,而断言触发了BOOST_VARIANT_LIMIT_TYPES,而BOOST_MPL_LIMIT_LIST_SIZE 又设置为BOOST_MPL_LIMIT_LIST_SIZE。你确定你的定义是在任何包含合理地解析为mpl 中的东西之前完成的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多