【发布时间】: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