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可以是:
Description Action
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(4)
- boost之spirit学习-mini_c(1)
- boost之spirit学习-mini_c(2)
- boost之spirit学习-mini_c(3)
- boost之spirit学习-mini_c(5)
- boost之spirit学习
- Boost.Spirit x3学习笔记
- boost之词法解析器spirit
- boost之词法解析器spirit
- boost之词法解析器spirit
- 学习boost库中的spirit,实现简单的解析文件。
- boost.spirit -- parser
- boost.spirit -- scanner
- boost.spirit -- directives
- boost.spirit -- rule
- boost.spirit -- grammar
- boost.spirit -- subrules
- boost.spirit -- action
- Linux命令行技巧
- 开始学HTML5-第一天
- OpenCV二值化函数Threshold
- 五个免费的轻量级Linux发行版
- 通过上下文context操作文件
- boost之spirit学习-mini_c(4)
- 成功不易
- hibernate批量处理
- hibernate之manyToMany查询错误
- 抽象工厂模式
- C中的静态数据区、代码区、堆、栈
- java的Error和Exception的区别联系
- 最近需要完成的事情
- 软件工厂是否真的可能存在?