我是 Spirit 和 Boost 的新手。我正在尝试解析 VRML 文件的一部分,如下所示:
point
[
#coordinates written in meters.
-3.425386e-001 -1.681608e-001 0.000000e+000,
-3.425386e-001 -1.642545e-001 0.000000e+000,
-3.425386e-001 -1.603483e-001 0.000000e+000,
以#开头的注释是可选的。
我写了一个语法,效果很好,但是解析过程需要很长时间。我想优化它以运行得更快。我的代码如下所示:
struct Point
{
double a;
double b;
double c;
Point() : a(0.0), b(0.0), c(0.0){}
};
BOOST_FUSION_ADAPT_STRUCT
(
Point,
(double, a)
(double, b)
(double, c)
)
namespace qi = boost::spirit::qi;
namespace repo = boost::spirit::repository;
template <typename Iterator>
struct PointParser :
public qi::grammar<Iterator, std::vector<Point>(), qi::space_type>
{
PointParser() : PointParser::base_type(start, "PointGrammar")
{
singlePoint = qi::double_>>qi::double_>>qi::double_>>*qi::lit(",");
comment = qi::lit("#")>>*(qi::char_("a-zA-Z.") - qi::eol);
prefix = repo::seek[qi::lexeme[qi::skip[qi::lit("point")>>qi::lit("[")>>*comment]]];
start %= prefix>>qi::repeat[singlePoint];
//BOOST_SPIRIT_DEBUG_NODES((prefix)(comment)(singlePoint)(start));
}
qi::rule<Iterator, Point(), qi::space_type> singlePoint;
qi::rule<Iterator, qi::space_type> comment;
qi::rule<Iterator, qi::space_type> prefix;
qi::rule<Iterator, std::vector<Point>(), qi::space_type> start;
};
我打算解析的部分位于输入文本的中间,因此我需要跳过文本部分才能找到它。我使用repo::seek实现了它。这是最好的方法吗?
我按以下方式运行解析器:
std::vector<Point> points;
typedef PointParser<std::string::const_iterator> pointParser;
pointParser g2;
auto start = ch::high_resolution_clock::now();
bool r = phrase_parse(Data.begin(), Data.end(), g2, qi::space, points);
auto end = ch::high_resolution_clock::now();
auto duration = ch::duration_cast<boost::chrono::milliseconds>(end - start).count();
解析输入文本中的大约 80k 条目大约需要 2.5 秒,这对于我的需要来说相当慢。我的问题是有没有办法以更优化的方式编写解析规则以使其(更快)更快?我一般如何改进这个实现?
我是Spirit的新手,所以非常感谢一些解释。