boost之spirit学习-mini_c(4)

原创 2012年03月28日 00:21:34

今天看看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,具体情况下回分解


相关文章推荐

boost之spirit学习-mini_c(2)

main.cpp就一个main函数,倒是直接明了 main函数大概的流程: 读代码文件 使用spirit将代码解析成抽象语法树 使用compiler把语法树编译成字节码 从编译后...
  • jjparch
  • jjparch
  • 2012年03月22日 19:50
  • 382

boost之spirit学习-mini_c(3)

前一章分析完了main.cpp,了解了mini_c的主流程。现在来看看抽象语法树的定义:ast.hpp 首先,为一些对象打上id,方便编译错误时由对象的id查找到出错的位置(这个是由anno...
  • jjparch
  • jjparch
  • 2012年03月23日 00:55
  • 896

boost之spirit学习-mini_c(5)

继续看看周边的小东西,从易到难。今天是annotation.hpp annotation.hpp里定义了一个类:annotation。 顾名思义,它是给抽象语法树里的对象做标注的。标注什么呢?...
  • jjparch
  • jjparch
  • 2012年03月29日 21:53
  • 286

Boost.Spirit x3学习笔记

为了能够在Visual Studio 2015 RC上运行,需要做如下修改 1、修改boost/spirit/home/x3/nonterminal/detail/rule.hpp中的has_on_e...

boost之spirit学习

最近一段时间对boost比较着迷。看了一些boost代码后惊叹C++居然可以写成这样。 C++强大的模板、运算符重载让C++拥有强大的灵活性,可以模仿很多其它语言的语法,在解决某个具体问题时可以...
  • jjparch
  • jjparch
  • 2012年03月22日 19:48
  • 514

boost 中spirit 连续解析 employee 成容器变量

#include #include #include #include #include #include #include #include #include #include ...

在msvc中使用Boost.Spirit.X3

http://www.cnblogs.com/IndignangAngel/p/5026269.html Preface “Examples of designs that meet ...

boost之词法解析器spirit

boost之词法解析器spirit http://blog.csdn.net/crazyhacking/article/details/37603075 摘要:解析...

boost库spirit

  • 2016年10月09日 22:03
  • 1.67MB
  • 下载

Boost.Spirit.Karma 自定义directive

需求:给定一个参数,若它为1,则不输出;若为1,则输出且追加乘法运算符。 分析:这个需求是很容易满足的,一个if语句就可以了。即便是用karma,只需要eps + alternative。这里主要研究...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:boost之spirit学习-mini_c(4)
举报原因:
原因补充:

(最多只允许输入30个字)