在Spirit语义动作中检测参数类型 [英] Detecting the parameter types in a Spirit semantic action

查看:95
本文介绍了在Spirit语义动作中检测参数类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一般情况:我不知道为什么我的Spirit语法/语义动作不是编译。



有时,编译器会抱怨分配或类型不兼容,我不知道有什么问题。该问题发生在两个主要方面:




  • 预测规则/表达式的合成属性类型

    • 因此,预测哪些类型的属性可以合法地定义为规则的公开属性(依赖于建立转换,融合适配器或精灵自定义点)

    li>
  • 匹配语义动作的参数类型,以便

    • 编译器将能够编译函数调用
    • $ b $



编译器错误不是很容易处理,并且文档是错误的,或者我误解了它。



无论如何,有什么方法可以精确地找出精灵进入我的语义动作的方式? >

示例代码:



  struct mybase {int a,b; }; 
struct myderived:mybase {int c,d; };

BOOST_FUSION_ADAPT_STRUCT(mybase,(int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived,(int,a)(int,b)(int,c)(int,d));

auto base_expr = int_>> int_; //避免赋值给struct属性

rule< decltype(f),mybase(),space_type> base_ = int_>> int_;
rule< decltype(f),myderived(),space_type> derived_ = base_>> int_>> int_;

myderived data;
bool ok = phrase_parse(f,l,derived_,space,data);

这段代码不会编译,带来大量的不可读的错误。



精神一般列表

解决方案

为了清楚起见,这里的错误是 base_>> int_>> int _ 用作创建 myderived 的规则的表达式,并且由于 base _ 固定为类型 mybase ,我们必须从 mybase 创建 myderrived / code>和两个 int ,但没有什么可告诉Spirit如何做。



您可以获得boost,打印出升级创建的值的类型从解析 base_>> int_>> int _ 通过定义一个函数,它将接受任何参数,并告诉你它们是什么(下面的代码是从一些代码适应SO聊天):

  struct what_is_the_attr 
{
template< typename> struct result {typedef bool type; };

template< typename T>
static void print_the_type()
{
std :: cout< ;
std :: cout<< typeid(T).name();
if(std :: is_const< typename std :: remove_reference< T> :: type> :: value)
std :: cout< const;
if(std :: is_rvalue_reference< T> :: value)
std :: cout< &&;
else if(std :: is_lvalue_reference< T> :: value)
std :: cout<< &;
}

template< typename Th,typename Th2,typename ... Tt>
static void print_the_type()
{
print_the_type< Th>();
std :: cout<< ,\\\
;
print_the_type< Th2,Tt ...>();
}

template< typename ... Ts>
void operator()(Ts&& ...)const
{
std :: cout< what_is_the_attr(\\\
;
print_the_type< Ts ...>();
std :: cout<<)< std :: endl;
}
};

然后,使用上面的actor在初始化器的语义操作中为您的错误规则: / p>

  std :: string input =1 2 3 4; 
auto f(std :: begin(input)),l(std :: end(input));

rule< decltype(f),mybase(),space_type> base_ = int_>> int_;
rule< decltype(f),myderived(),space_type> derived_ =(base_>> int_>> int _)[what_is_the_attr()];

myderived data;
bool ok = phrase_parse(f,l,derived_,space,data);注意,不能使用自动属性传播与%=

/ code>(除非你从规则的声明类型中删除暴露的属性类型)。

运行这应该产生一个编码类型可以用 c ++ filt -t Live on Coliru

  $ g ++ 9404189.cpp -std = c ++ 0x 
$ ./a.out | c ++ filt -t
what_is_the_attr(
boost :: fusion :: vector3< mybase,int,int>&
boost :: spirit :: context< boost :: fusion :: cons< boost :: spirit :: unused_type& boost :: fusion :: nil>,boost :: fusion :: vector0< void>& $ b bool&)

第一行 boost :: fusion: :vector3< mybase,int,int> ,最少告诉你boost是试图从类型 mybase code> int int


General case: I can't figure out why my Spirit grammar/semantics actions aren't compiling.

Sometimes, the compiler will complain about assignment or type incompatibilities and I have no clue what's wrong. The problem occurs in two main areas:

  • predicting the type of synthesized attributes for a rule/expression
    • consequently, predicting what types of attributes can be legally defined as the exposed attribute for the rule (relying in builting conversions, fusion adaptors or Spirit customization points)
  • matching the argument types for my semantic action so that
    • the compiler will be able to compile the function invocation
    • the invocation will not invoke unnecessary implicit conversions in the process

The compiler error is not exactly tractable, and either the documentation is wrong, or I misunderstood it.

Is there a way to find out exactly what Spirit passes into my semantic action, anyway?

Example code:

struct mybase             { int a,b; };
struct myderived : mybase { int c,d; };

BOOST_FUSION_ADAPT_STRUCT(mybase,    (int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived, (int,a)(int,b)(int,c)(int,d));

auto base_expr = int_ >> int_; // avoids assigning to struct attribute

rule<decltype(f), mybase()   , space_type> base_       = int_ >> int_;
rule<decltype(f), myderived(), space_type> derived_    = base_ >> int_ >> int_;

myderived data;
bool ok = phrase_parse(f,l,derived_,space,data);

This code won't compile, with a huge amount of impenetrable errors.

(loosely adapted from a posting on the spirit-general list)

解决方案

For clarity - the error here is that base_ >> int_ >> int_ was used as the expression for a rule that creates a myderived, and since base_ is fixed to type mybase, we'd have to create a myderrived from a mybase and two ints, but there's nothing to tell Spirit how to do that.

You can get boost to print out the type of the value that boost creates from parsing base_ >> int_ >> int_ by defining a functor that will take any parameters, and tell you what they are (the following code is adapted from some code sehe put on SO chat):

struct what_is_the_attr
{
    template <typename> struct result { typedef bool type; };

    template <typename T>
    static void print_the_type()
    {
        std::cout << "    ";
        std::cout << typeid(T).name();
        if(std::is_const<typename std::remove_reference<T>::type>::value)
            std::cout << " const";
        if(std::is_rvalue_reference<T>::value)
            std::cout << " &&";
        else if(std::is_lvalue_reference<T>::value)
            std::cout << " &";
    }

    template <typename Th, typename Th2, typename... Tt>
    static void print_the_type()
    {
        print_the_type<Th>();
        std::cout << ",\n";
        print_the_type<Th2, Tt...>();
    }

    template <typename... Ts>
    void operator()(Ts&&...) const
    {
        std::cout << "what_is_the_attr(\n";
        print_the_type<Ts...>();
        std::cout << ")" << std::endl;
    }
};

Then to use it, use the above actor in a semantic action on initializer for your faulty rule:

std::string input = "1 2 3 4";
auto f(std::begin(input)), l(std::end(input));

rule<decltype(f), mybase()   , space_type> base_    = int_ >> int_;
rule<decltype(f), myderived(), space_type> derived_ = (base_ >> int_ >> int_)[what_is_the_attr()];

myderived data;
bool ok = phrase_parse(f,l,derived_,space,data);

Note, you cannot use automatic attribute propagation with %= (unless you remove the exposed attribute type from the rule's declared type).

Running this should then yield an encoded type, which can be decoded with c++filt -t: Live On Coliru

$ g++ 9404189.cpp -std=c++0x
$ ./a.out |c++filt -t
what_is_the_attr(
    boost::fusion::vector3<mybase, int, int> &,
    boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type&, boost::fusion::nil>, boost::fusion::vector0<void> > &,
    bool &)

The first line, boost::fusion::vector3<mybase, int, int>, least tells you that boost is trying to create your return type from 3 objects of types mybase, int and int.

这篇关于在Spirit语义动作中检测参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆