boost之spirit学习-mini_c(4)

来源:互联网 发布:jdk 7u1 windows 7.0 编辑:程序博客网 时间:2024/05/29 11:56

今天看看error_handler.hpp,先把这些周边的东西搞清楚。

    ///////////////////////////////////////////////////////////////////////////////    //  The error handler    ///////////////////////////////////////////////////////////////////////////////    template <typename Iterator>    struct error_handler    {           template <typename, typename, typename>        struct result { typedef void type; };        error_handler(Iterator first, Iterator last)          : first(first), last(last) {}        //...        Iterator first;        Iterator last;        std::vector<Iterator> iters;    };

error_handler.hpp比较简单,只定义了error_handler一个模板类。包含三个成员变量:first、last和iters。first和last代表要解析的字符串的起始位置。iters比较奇怪,它在error_handler里定义,但在error_handler里一次都没用。翻翻其它代码,发现这个iters由annotation类使用,annotation类保存对这个iters数组的引用。每次出现一个需要标记的语法对象,annotation类就在iters里记录下该对象的位置,而对象的id就是iters数组的下标。从而通过对象id可以直接查到对象对代码中的确切位置。

struct result是为了boost::result_of准备的。error_handler是个函数对象,因此它的返回值需要通过这种特殊方法标记。


        template <typename Message, typename What>        void operator()(            Message const& message,            What const& what,            Iterator err_pos) const        {            int line;            Iterator line_start = get_pos(err_pos, line);            if (err_pos != last)            {                std::cout << message << what << " line " << line << ':' << std::endl;                std::cout << get_line(line_start) << std::endl;                for (; line_start != err_pos; ++line_start)                    std::cout << ' ';                std::cout << '^' << std::endl;            }            else            {                std::cout << "Unexpected end of file. ";                std::cout << message << what << " line " << line << std::endl;            }        }

上面这个函数是函数对象方法的实现。message和what的类型都是泛型的。大概就是通过出错的位置找到出错行的起始位置和行号,再判断出错位置是否达到待解析字符串末尾。根据情况给出不同的提示。

        Iterator get_pos(Iterator err_pos, int& line) const        {            line = 1;            Iterator i = first;            Iterator line_start = first;            while (i != err_pos)            {                bool eol = false;                if (i != err_pos && *i == '\r') // CR                {                    eol = true;                    line_start = ++i;                }                if (i != err_pos && *i == '\n') // LF                {                    eol = true;                    line_start = ++i;                }                if (eol)                    ++line;                else                    ++i;            }            return line_start;        }


        Iterator get_pos(Iterator err_pos, int& line) const        {            line = 1;            Iterator i = first;            Iterator line_start = first;            while (i != err_pos)            {                bool eol = false;                if (i != err_pos && *i == '\r') // CR                {                    eol = true;                    line_start = ++i;                }                if (i != err_pos && *i == '\n') // LF                {                    eol = true;                    line_start = ++i;                }                if (eol)                    ++line;                else                    ++i;            }            return line_start;        }

        Iterator get_pos(Iterator err_pos, int& line) const        {            line = 1;            Iterator i = first;            Iterator line_start = first;            while (i != err_pos)            {                bool eol = false;                if (i != err_pos && *i == '\r') // CR                {                    eol = true;                    line_start = ++i;                }                if (i != err_pos && *i == '\n') // LF                {                    eol = true;                    line_start = ++i;                }                if (eol)                    ++line;                else                    ++i;            }            return line_start;        }


根据出错位置找出出错行的起始位置和行号。从头开始一个字符一个字符地找,很简单。

        std::string get_line(Iterator err_pos) const        {            Iterator i = err_pos;            // position i to the next EOL            while (i != last && (*i != '\r' && *i != '\n'))                ++i;            return std::string(err_pos, i);        }


获取从出错位置开始到出错行末的字符串。也很简单。


error_handler用于定义rule出错时的处理。定义出错处理的函数:

on_error<Action>(rule, handler)

其中Action可以是:

Action

Description

fail

Quit and fail. Return a no_match.

retry

Attempt error recovery, possibly moving the iterator position.

accept

Force success, moving the iterator position appropriately.

rethrow

Rethrows the error.

handler可以是函数或函数对象(error_handler类即用于此处),接受4个参数:

Arg

Description

first

The position of the iterator when the rule with the handler was entered.

last

The end of input.

error-pos

The actual position of the iterator where the error occured.

what

What failed: a string describing the failure.


但error_handler只接受3个参数。因此中间需要用类似boost::bind的技巧转换一下。

bind(error_handler, "Erorr! Expecting ", _4, _3)

但mini_c里用的是boost::phoenix::function,具体情况下回分解


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 不知道怀孕喝了止咳糖浆怎么办? 小孩刮头发的备皮刀割住手怎么办? 天梭手表里面的刻度掉了怎么办 国战天下手游帐号丢失怎么办 肺力咳合剂一次喝了50多了怎么办 头孢和藿香正气水一起吃了怎么办 小儿胃蛋自酶合剂吃多了怎么办 刚出生的婴儿很容易被惊醒怎么办 1个多月的宝宝小腿不直怎么办 20个月宝宝腿不直小腿外八怎么办 小孩手青枝骨骨折拆石膏还弯怎么办 宝宝喝柴胡注射剂有不良反应怎么办 九个月宝宝便秘拉不出来怎么办 一岁四个月的宝宝便秘怎么办 热血三国3要塞打不过去怎么办 清香木夏天有黄叶和掉叶怎么办 生完宝宝妊娠纹还在继续疯长怎么办 陌陌不能最小化观看直播视频怎么办 苏州园区公积金密码忘记了怎么办 房产企业申请破产买的房子怎么办 被业务员骗了买了保险怎么办 孩子特别害怕老师严厉的批评怎么办 4k电视看有线电视不清晰怎么办 移动9.9流量4g网用完了怎么办 东方头条验证码已经被注册了怎么办 打王者两个人吵架被夹在中间怎么办 顾客拿过期的食品过来投诉怎么办 老婆总是埋怨我父母我该怎么办? 代款公司如果使用暴力追债怎么办 法院拍卖款分配有疑意怎么办 法院拍卖买到的房子里有户口怎么办 新注册手机邮箱不和电脑同步怎么办 移动4g盒当月流量封顶怎么办 昆仑加油卡密码忘记了怎么办 昆仑银行e盾密码忘记了怎么办 中石化加油卡密码忘记了怎么办 壳牌加油卡密码忘了怎么办 中国石化加油卡密码忘了怎么办 中石化加油卡密码忘了怎么办 中石化加油卡需要密码忘了怎么办 求不熟领导办事送礼不收怎么办