Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > boost.spirit -- action
【标  题】:boost.spirit -- action
【关键字】:boost.spirit,--,action
【来  源】:http://blog.csdn.net/kenryHuang/archive/2006/08/11/1050391.aspx

boost.spirit -- action

Your Ad Here

7       action

action是用来解析完成以后执行某种动作的类,所有的action类使用起来的形式为parser[action]

 

一望而知,parser类必定实现了一个operator[]。这个函数实现在基类parser中,被所有的parser继承。

 

        template <typename ActionT>

        action<DerivedT, ActionT>

        operator[](ActionT const& actor) const

        {

            return action<DerivedT, ActionT>(derived(), actor);

        }

 

parser::operator[]有一个参数actor,就是解析成功以后调用的动作函数,是一个function object

 

返回模板类action的一个对象。

 

7.1    action template class

action模板类实际上是一个标准的装饰器(decorator)模式的实现。回想一下decorator的定义:继承一个类的接口,并给这个类动态透明的添加职责。

 

 

对于parser来说,它是完全无须知道action的存在的。action本身继承自parser,实现了parse接口,在parse中,在调用了parser本身的parse功能以后,以parse_result为参数调用actor.operator()(result)

 

 

 

看看action::parse的实现:

 

        template <typename ScannerT>

        typename parser_result<self_t, ScannerT>::type

        parse(ScannerT const& scan) const

        {

            typedef typename ScannerT::iterator_t iterator_t;

            typedef typename parser_result<self_t, ScannerT>::type result_t;

 

            scan.at_end(); // allow skipper to take effect

            iterator_t save = scan.first;

//调用subject(parser)parse方法做解析工作。

            result_t hit = this->subject().parse(scan);

//如果解析成功,执行actor动作。通过调用scan.do_action方法实现,具体实现见后。

            if (hit)

            {

                typename result_t::return_t val = hit.value();

                scan.do_action(actor, val, save, scan.first);

            }

            return hit;

        }

 

7.2    scanner::do_action

 

可以看出,actionparser添加的职责是调用scanner::do_action来实现的,可以回忆一下scanneraction_policy 实际上,scanner是通过继承action_policy类来继承do_action方法的。

 

 

    struct action_policy

    {

        template <typename ActorT, typename AttrT, typename IteratorT>

        void

        do_action(

            ActorT const&       actor,

            AttrT&              val,

            IteratorT const&    first,

            IteratorT const&    last) const

        {

            attributed_action_policy<AttrT>::call(actor, val, first, last);

        }

};

 

调用流转到了模板类attributed_action_policy,这个模板类有两个特化版本:

 

// 对于有Attributeparser而言,(比如primitives)可以推导出确定AttrT,调用这个版本。最终调用actor.operator()(val)。这个时候,需要提供的actor是接受一个确定类型参数(parser解析得到的结果类型)function object

    template <typename AttrT>

    struct attributed_action_policy

    {

        template <typename ActorT, typename IteratorT>

        static void

        call(

            ActorT const& actor,

            AttrT& val,

            IteratorT const&,

            IteratorT const&)

        {

            actor(val);

        }

    };

 

//对于没有Attributeparser(比如composite)AttrT=nil_t,调用这个版本,这个时候调用actor.operator(first, last);这个时候,需要提供的actor是接受一对迭代器的function object

    template <>

    struct attributed_action_policy<nil_t>

    {

        template <typename ActorT, typename IteratorT>

        static void

        call(

            ActorT const& actor,

            nil_t,

            IteratorT const& first,

            IteratorT const& last)

        {

            actor(first, last);

        }

    };

 

 

7.3    actors

 

 

 

spirit中定义了很多actors,这个actor都实现了operator(AttrT)或是operator(IteratorT, IteratorT)

 

spirit实现了5actor

 

 

实际上,这5actor都是模板类,都有一个模板参数ActionT,而且都从ActionT继承。actorActionT的功能完全正交;actor的功能是决定如何操作三类对象,而ActionT提供实际的操作方式。

 

actor要操作的三类对象有:

1.  目的对象(actor操作的对象):这个对象一般作为actor的成员

2.  源对象(parse的结果):这个对象一般作为operator()函数的参数

3.  其他对象(这些对象作为function object的附加参数):这些对象一般作为actor的成员

 

通过继承模板参数类的方式:

template <typename ActionT>

struct any_actor : public ActionT { /*…*/ };

 

ActionT的功能混入(mixin) actor中;通过用不同的ActionT实例化actor类,使actor得到不同的操作能力。各种ActionT与各种actor之间的任意混合,我们只需实现nactormActionT,就能得到n*mactor<ActionT>类。

 

 

 

1.  ref_actor:只持有目的对象,在operator()中忽略源对象。适合混入只操作一个单一引用的ActionT,比如increment_action

2.  ref_value_actor:最为常用,持有目的对象,并在operator()中引用源对象;适合混入标准ActionT,操作两个引用对象。比如assign_action

3.  ref_const_ref_actor:持有目的和其他对象,在operator()忽略源对象。当然源对象也可以作为其他对象使用,不过需要在构造的时候传入,并不是在operator()中引用。混入的ActionT需要接受两个引用参数。

4.  ref_const_ref_value_actor:持有目的对象和其他对象,并且在operator()中引用源对象,混入的ActionT接受三个参数。

5.  ref_const_ref_const_ref_actor:持有目的对象和两个其他对象,但是在operator()忽略源对象,混入的ActionT需接受三个参数。

 
boost.spirit -- operators and composite parser:【上一篇】
boost.spirit -- subrules:【下一篇】
【相关文章】
  • boost.spirit -- operators and composite parser
  • Counting Objects in C++ -----by Scott Meyers
  • mysql存储过程学习笔记--常用函数
  • 内核空间和用户空间通信 -- 调用用户空间程序
  • sigaction函数 - 改变信号行为
  • 数据库系统概念读书笔记(3)--关系模型
  • 《设计模式》之Java解读--适配器Adapter
  • Lucene in Action (中文)
  • 《设计模式》之Java解读--桥接Bridge
  • boost.spirit (2) -- parser
  • 【随机文章】
  • Oracle10新特性:临时表空间组(temporary tablespace group)
  • freeradius+mysql为华为防火墙做vpn用户验证
  • Java学习:一个基础的代理服务器类
  • telnet后很久才出现login画面,login后速度不慢,为什么?
  • ICE:Slice语言(六)--接口、操作和异常(一)
  • 主题: 类与类关系的UML图与代码表现
  • GIS数据建库基本思想(上)
  • RAID:Redundant Arrays of Independent Disks
  • 进行设计时要在什么范围内考虑统一的设计?
  • Oracle数据库RMAN备份与灾难恢复在寒区旱区特色数据库的应用
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.