C++ 使用简单C风格结构化输入的Spirit Qi解析问题

C++ 使用简单C风格结构化输入的Spirit Qi解析问题,c++,parsing,boost,boost-spirit,boost-spirit-qi,C++,Parsing,Boost,Boost Spirit,Boost Spirit Qi,我正在尝试为一些游戏数据设置一个基本的解析器,它使用一种熟悉且非常简单的“C风格”格式。基本上,命名带括号的“结构”,然后将参数和嵌套的“结构”放入其中。它将解析如下内容: Name0 { Name1 { Param0 *= 2 Param2 = "lol" } Param0 = 1 Param1 = "test" Name2 { } } Name3 { Param0 = "test" } 然而,它甚至在“test{}”的简单输入测试上都失败了,更不用说像我上面的例子

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

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

 Name2 { }
}

Name3 {
 Param0 = "test"
}
然而,它甚至在“test{}”的简单输入测试上都失败了,更不用说像我上面的例子那样高级了。结构设置为使用fusion,这似乎足够直截了当,我怀疑这是问题所在。我目前没有使用几个规则,我的大多数规则都未经测试,因为它在
根目录中尝试第一个
类别
规则时失败。这是我在输入“Test{}”时遇到的错误:


未给出运算符


我想你的
节点
规则会吃掉结束的
}
规则,所以
分类
规则不会成功。

也许你可以选择使用信息文件格式增强属性。@MikeM属性树中的信息解析器看起来非常有趣,基本上就是我现在正在做的事情。我当前的格式不是最终的格式,我正在考虑添加更复杂的东西(还没有真正决定如何做),所以我不确定信息解析器是否会处理它们。。。所以我还是很好奇是否能修好这个,以防万一。但是,是的,非常好的建议!编辑:啊,实际上,它不支持修改现有的值,比如*=Ah,所以第一个
category
规则可能会进入“Test{”,然后它进入
节点
并尝试另一个
category
规则……但是
category
只忽略“{”字符,所以它吃了“}”就死了?
param
不忽略“}“要么。。。尽管这很棘手。你能减去一个以上的东西吗,因为目前我从
param
中的
char\uu
中减去了我的符号表。。。如果允许的话,我还没有机会测试它,哈哈。
规则-(sub1 | sub2 | sub3)
减去更多。是的,
}
被吃掉了,没有任何东西可以关闭
类别。由于您使用了
,因此
>
会出现异常,解析将不会成功。好吧,这解决了第一个问题,嵌套类别工作正常!。。。但后来我尝试了
param
,结果又失败了。我得做个实验,但我注意到一件奇怪的事。My
node%=类别|参数规则会根据顺序(如果我将
param
category
放在第一位)极大地更改其错误和调试输出。似乎如果
类别
是第一个,它会尝试将
节点
解释为
类别
(根据调试输出),当失败时,它会放弃,甚至不会研究将其用作
参数
?顺序很重要吗?顺序很重要,首先使用您编写的规则,但如果失败,解析器将返回并尝试下一个规则。但是如果使用
得到异常,解析器将完全停止。那么,当您要向用户提供解析器错误时,应该使用
。使用
>
您只会看到它无法被解析,而不是为什么。
Error! Expecting <sequence>"{"<node> here: ""
 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
     );
  }
 };
 struct Operators : qi::symbols<char, Operator>
 {
  Operators()
  {
   add
    ("=", Operator::equal)
    ("+=", Operator::plusequal)
    ("-=", Operator::minusequal)
    ("*=", Operator::timesequal)
    ("/=", Operator::divideequal)
    ;
  }
 } operators;