如何抑制在boost :: spirit中跳过解析带引号的字符串?

时间:2014-02-01 02:15:01

标签: c++ boost boost-spirit boost-spirit-qi

我正在尝试使用boost :: spirit实现一个简单的解析器,其中(除其他外)接受双引号中的字符串,例如“你好,世界”。这是一个简化程序,说明了我的问题:

#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

namespace qi = boost::spirit::qi;

static void print(const std::vector<char>& v) {
   std::cout << std::string(v.begin(), v.end()) << '\n';
}

template<typename Iterator>
class Grammar : public qi::grammar<Iterator, boost::spirit::ascii::space_type> {
   typedef boost::spirit::ascii::space_type space_type;
   qi::rule<Iterator, space_type> start;
   qi::rule<Iterator, std::vector<char>()> string;
   qi::rule<Iterator, char()> unescapedChar;

public:
   Grammar() : Grammar::base_type(start) {
      start = string[&print];
      string %= qi::lexeme['"' >> qi::no_skip[*unescapedChar] >> '"'];
      unescapedChar %= qi::char_ - qi::lit('"');
   }
};

int main() {
   const std::string s("\"how now brown cow\"");
   boost::iostreams::filtering_istream fs(boost::make_iterator_range(s.begin(), s.end()));;

   typedef boost::spirit::istream_iterator iterator;
   qi::phrase_parse(
      iterator(fs), iterator(),
      Grammar<iterator>(),
      boost::spirit::ascii::space);

   return 0;
}

在此程序中,unescapedChar规则定义字符串中的允许字符(除双引号外的任何内容),string规则是双引号内的unescapedChar的Kleene星。

传递"how now brown cow"(引号作为字符串的一部分)时,此程序的输出为hownowbrowncowstd::vector<char>的{​​{1}}属性缺少所有空格。我希望空格在解析结果中。

stringunescapedChar规则声明均未指定跳过类型。我还尝试单独和一起使用stringlexeme指令(如上所示)。我试过提升1.49并提升1.55。在每种情况下,输出都没有嵌入空格。

在我的实际解析器中,我确实想要跳过空格,而不是在带引号的字符串中。我做错了什么?

1 个答案:

答案 0 :(得分:4)

我认为你的问题是跳过空白的输入流

请参阅http://en.cppreference.com/w/cpp/io/manip/skipws

添加

fs.unsetf(std::ios::skipws);

解决问题

查看 Live on Coliru