【问题标题】:Spirit Qi parsing issue with simple C-style structured input使用简单 C 样式结构化输入的 Spirit Qi 解析问题
【发布时间】:2014-02-17 17:51:16
【问题描述】:

我正在尝试为一些使用熟悉且非常简单的“C 样式”格式的游戏数据设置基本解析器。基本上,命名支撑的“结构”,然后将参数和嵌套的“结构”放入其中。它会解析如下内容:

Name0
{
 Name1
 {
  Param0 *= 2
  Param2 = "lol"
 }
 Param0 = 1
 Param1 = "test"

 Name2 { }
}

Name3 {
 Param0 = "test"
}

但是,即使是“Test {}”的简单输入测试,它也失败了,更不用说像我上面的例子那样先进的东西了。这些结构设置为使用融合,这似乎很简单,我怀疑这是问题所在。我目前没有使用几个规则,而且我的大部分规则都未经测试,因为它在尝试root 中的第一个category 规则时失败。这是我输入“Test {}”时遇到的错误:

Error! Expecting <sequence>"{"<node> here: ""

这是 Parser 类:

 template<typename Iterator>
 struct Parser : qi::grammar<Iterator, std::vector<Category>(), ascii::space_type>
 {
  qi::rule<Iterator, std::vector<Category>(), ascii::space_type> root;

  qi::rule<Iterator, Category(), ascii::space_type> category;
  qi::rule<Iterator, Param(), ascii::space_type> param;

  qi::rule<Iterator, Node(), ascii::space_type> node;

  qi::rule<Iterator, Value(), ascii::space_type> value;

  qi::rule<Iterator, char()> escape;
  qi::rule<Iterator, std::string()> quotedstring;
  qi::rule<Iterator, std::string()> normalstring;

  qi::rule<Iterator> comment;
  qi::rule<Iterator> commentblock;

  Parser() : Parser::base_type(root, "root")
  {
   using namespace qi;

   using ascii::char_;

   using phoenix::construct;
   using phoenix::val;

   escape %= '\\' > char_("\\\"");
   quotedstring %= '"' >> *((char_ - '"') | escape) > '"';
   normalstring %= *(char_ - qi::eol);

   comment = "//" >> *(char_ - qi::eol);
   commentblock = "/*" >> *(char_ - "*/") > "*/";

   node %= category | param; //comment? comment block? holding off for now

   value %= normalstring | float_;

   param %=
    lexeme[+(char_ - operators)]
    > operators
    > value
    > qi::eol;

   category %=
    lexeme[+(char_ - '{')] //won't this grab all whitespace around the tag too?
    > '{'
    >> *node
    > '}';

    root %= *category;

    root.name("root");

    category.name("category");
    param.name("param");

    node.name("node");

    value.name("value");

    escape.name("escape");
    quotedstring.name("quotedstring");
    normalstring.name("normalstring");

    comment.name("comment");
    commentblock.name("commentblock");

    debug(root);
    debug(category);
    debug(param);
    debug(node);
    debug(value);
    debug(escape);
    debug(quotedstring);
    debug(normalstring);
    debug(comment);
    debug(commentblock);

    on_error<fail>
     (
     root,
     std::cout
     << val("Error! Expecting ")
     << _4
     << val(" here: \"")
     << construct<std::string>(_3, _2)
     << val("\"")
     << std::endl
     );
  }
 };

还有一件不相关的事情,是否可以在 on_successon_error 调用中使用 C++11 lambda?我查看了on_error 函数,它似乎将其参数模板化为规则类型,这意味着必须为每个规则类型(基本上每个规则)定义一个 lambda。那是对的吗?太糟糕了,那些phoenix lambdas太不透明了,我什至不知道如何提取行号并将其放入结构中。

编辑:

这是operators 表:

 struct Operators : qi::symbols<char, Operator>
 {
  Operators()
  {
   add
    ("=", Operator::equal)
    ("+=", Operator::plusequal)
    ("-=", Operator::minusequal)
    ("*=", Operator::timesequal)
    ("/=", Operator::divideequal)
    ;
  }
 } operators;

【问题讨论】:

  • 也许 boost property_tee with info 文件格式是你的一个选择。
  • @MikeM 属性树中的信息解析器看起来很有趣,基本上就是我现在正在做的。我当前的格式不是最终格式,我正在考虑添加更复杂的东西(还没有真正决定如何去做),所以我不确定 INFO Parser 是否会处理它们......所以我我仍然对解决这个问题感到好奇,以防万一。但是,非常好的建议!编辑:啊,实际上,它不支持使用 *= 修改现有值

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


【解决方案1】:

operators 没有给出。

我猜你的 node 规则吃掉了关闭的 } 所以 catagory 规则不能成功。

【讨论】:

  • 啊,所以也许第一个category 规则到达“测试{”,然后它进入node 并尝试另一个category 规则...但是category 只忽略了'{ ' 字符,所以它吃掉了 '}' 然后死了? param 也不会忽略 '}' ......虽然这很棘手。你能减去一个以上的东西吗,因为目前我从param 中的char_ 中减去我的符号表......如果这甚至被允许,我还没有机会测试它,哈哈。
  • rule - (sub1|sub2|sub3) 减去更多。是的,} 被吃掉了,没有什么可以关闭category。由于您使用&gt;,您会收到&gt;&gt; 的异常,解析不会成功。
  • 好吧,这解决了第一个问题并且嵌套类别有效!...但后来我尝试param,事情又失败了。我必须进行实验,但我注意到一件奇怪的事情。我的node %= category | param; 规则根据顺序极大地改变了它的错误和调试输出(如果我把paramcategory 放在第一位)。似乎如果category 是第一个,它会尝试将node 解释为category(根据调试输出),当失败时就放弃并且甚至不调查将其用作param ?顺序应该重要吗?
  • 顺序很重要,首先使用您首先编写的规则,但如果失败,解析器会返回并尝试下一条规则。但是如果遇到异常,通过使用&gt;,解析器会完全停止。
  • 嗯,&gt; 应该被使用,当你想给用户解析器错误时。使用&gt;&gt;,您只会看到它无法解析,而不是为什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多