秘笈19 解析输入
在前一个秘笈中,我们编写了一个简单的日期解析器。试想一下,过一段时间,任务已经改变。现在,我们需要编写支持多种输入格式并加上时区偏移的日期和时间的解析器。所以,现在我们的解析器应该理解以下输入:

准备
我们将使用Spirit库,在秘笈18中已经对它进行了描述。请在使用这个秘笈之前阅读它。
做法
1.我们从编写将保存一个解析结果的“日期–时间”结构开始:

2.现在,编写一个函数来设置时区偏移:

3.编写解析器可以被分解成编写几个简单的解析器,所以我们从编写一个时区偏移解析器开始。

4.编写其余的解析器以完成这个例子:

工作原理
这里有一个非常有趣的方法是boost::spirit::qi::rule<const char*, void()>。它擦除类型并允许在源文件编写解析器并将它们导出到头文件。例如:

但请记住,这个类意味着编译器的优化障碍,所以当它不是必需的时候,不要使用它。
还有更多
可以通过消除做类型擦除的rule<>对象让这个例子速度稍快。对于这个例子,在C++11中,可以仅使用auto关键字来替换它们。
Boost.Spirit库产生非常快的解析器,在官方网站上有一些性能指标,也有一些使用Boost.Spirit库的建议,其中之一是仅生成一个解析器一次,然后就只重用它(在这个例子中未显示出这一点)。
在timezone_parser中解析指定时区偏移的规则使用boost::phoenix::bind调用,这不是强制性的。然而,如果没有它,我们需要处理boost::fusion::vector<char, unsigned short, unsigned short>,其不如bind(&set_zone_offset, ref(ret), _1, _2, _3)对用户友好。
在解析大文件时,阅读秘笈86,因为对文件不正确的处理,可能会使你的程序减慢远不止解析那么多。
编译使用Boost.Spirit(或Boost.Fusion)库的代码可能要花费大量的时间,因为它含有数量庞大的模板实例。可以利用现代编译器试验Boost.Spirit库,它们提供了更快的编译时间。
参见
关于Boost.Spirit库值得写另一本书来介绍。少数几个秘笈不可能描述完它的所有功能,所以参考文档将帮助你获得更多关于它的信息。可在http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/index.html获得该文档。在那里,你会找到更多的例子、准备好的解析器以及如何直接在C++11代码中使用Boost编写词法分析器和代码生成器的信息。