Boost Spirit和抽象语法树设计

Boost Spirit and abstract syntax tree design

本文关键字:语法树 抽象 Spirit Boost      更新时间:2023-10-16

我正在使用Boost Spirit中的Qi来解析VRML 1.0。有一个名为Separator的组节点,在Separator下可以容纳许多不同类型的节点。AST基于Boost。变体,到目前为止看起来很长。我即将达到变体中20种类型的极限。我知道我可以扩展变体的类型数量,但我相信一定有更好的方法来设计它。欢迎想法。

typedef boost::variant<
    Nil,
    Coordinate3,
    Info,
    Material,
    MaterialBinding,
    Normal,
    NormalBinding,
    Texture2,
    Texture2Transform,
    TextureCoordinate2,
    ShapeHints,
    MatrixTransform,
    Rotation,
    Scale,
    Transform,
    Translation,
    boost::recursive_wrapper<Separator>
> VRML1Node;

您确定没有提前优化吗?根据我的经验,变体的"认知开销"不会随着变体中元素类型的数量而增加[1]

你可能想要

使用类型序列指定有界类型

typedef mpl::vector< Coordinate3 > types_initial;
typedef mpl::push_front< types_initial, Nil >::type types;
boost::make_variant_over< types >::type VRML1Node;

或者

在这种情况下,您可以采用动态多态性路线,而不是采用静态多态性。

根据您的使用情况,性能不一定会受到严重影响。主要区别在于

  1. 为了获得完全可优化的访问者代码,您需要在变体现在为您执行类型eraruse的地方使用动态强制转换
  2. 内存分配的局部性可能不太理想(尽管自定义分配器可能会减轻您的负担)
  3. 存储需求实际上可能会得到改善(变体必须容纳最大的元素类型;当大多数元素类型实际上都较小时,将有效地分配较少的内存)。

    1. 在实际操作方面,您可能必须使用Phoenix(语义操作)来正确分配属性

我不推荐它,但很明显,你甚至可以使用boost::any

struct poorMansVariant
{
      TypeCode discriminator; // TypeCode::Nil, TypeCode::Coordinate3...
      boost::any value;
};

[1]尽管当一些元素类型是可转换/可赋值的,或者通常情况下,它们的构造函数变得不明确时,情况可能会变得稍微复杂。但这是另一个主题