Boost 试图编译Spirit.Qi解析器的问题

Boost 试图编译Spirit.Qi解析器的问题,boost,boost-spirit,boost-spirit-qi,boost-fusion,Boost,Boost Spirit,Boost Spirit Qi,Boost Fusion,下面是一个完全独立的示例。问题似乎是第84-89行-如果这些行被注释掉,那么示例将编译。我试图解析的是文件的每一行,其中有五个以冒号分隔的项,最后三个项是可选的。单个函数获取一个boost::filesystem::file,使用boost.interprocess将其吸入并解析 我希望它解析的示例: a:1 a:2:c a:3::d a:4:::e a:4:c:d:e 结果应该存储在向量中,并且文件行是一个包含五个成员的结构,最后三个是可选的。以下是代码和错误: 代码 我已经回答了Spirit

下面是一个完全独立的示例。问题似乎是第84-89行-如果这些行被注释掉,那么示例将编译。我试图解析的是文件的每一行,其中有五个以冒号分隔的项,最后三个项是可选的。单个函数获取一个
boost::filesystem::file
,使用
boost.interprocess
将其吸入并解析

我希望它解析的示例:

a:1

a:2:c

a:3::d

a:4:::e

a:4:c:d:e

结果应该存储在
向量中
,并且
文件行
是一个包含五个成员的结构,最后三个是可选的。以下是代码和错误:

代码
我已经回答了Spirit邮件列表,但是为了完整起见,让我把它贴在这里


你的例子远非微不足道。我看不出您为什么在代码中留下进程间、文件系统或业力引用。这只会让每个愿意帮助的人都更难诊断。此外,在那里的某个地方有一个不匹配的括号。我假设您没有关闭
+(char-(':'| eol)

好的,让我们仔细看看。这是您的(简化)语法。它不再有用,但在属性方面,它的行为应该与原始语法相同:

*(+char_ >> -(*char_ >> (eol | -(*char_ >> (eol | -(':' >> +char_))))))
此语法的公开(传播属性)为:

vector<
  tuple<
    std::vector<char>,
    optional<
      tuple<
        std::vector<char>,
        variant<
          char,
          optional<
            tuple<
              std::vector<char>,
              variant<
                char,
                optional<
                  std::vector<char>
                >
              >
            >
          >
        >
      >
    >
  >
>
漂亮吧

如果你进一步思考,你会意识到,写作

foo >> (eol | -bar) >> *eol
相当于:

foo >> -bar >> *eol
这使它更加简化:

rule<char const*, file_line()> f = 
    *eol >> e1 >> u >> -(':' >> e2 >> -(':' >> e2 >> -(':' >> e3) ) ) >> *eol;

或者b)使用语义操作来设置属性的元素(我会这么做)。

我已经将其余的错误消息粘贴在这里,以防有人想看到:这就是Hartmut和Spirit都很棒的原因。非常感谢,我没想到会有这么简洁的答案。Hartmut在IRC上也给了我类似的东西,这解释了大量关于属性传播的工作原理:。这也解释了精神是多么的聪明。
rule<char const*, std::string()> e1 = +~char_(":\r\n");
rule<char const*, std::string()> e2 = *~char_(":\r\n");
rule<char const*, std::string()> e3 = +~char_("\r\n");
rule<char const*, ushort()> u = ':' >> ushort_;
rule<char const*, file_line()> fline = 
    *eol >> e1 >> u
         >> -(':' >> e2 >> (eol | -(':' >> e2 >> (eol | -(':' >> e3))))) >> *eol;
*fline
foo >> (eol | -bar) >> *eol
foo >> -bar >> *eol
rule<char const*, file_line()> f = 
    *eol >> e1 >> u >> -(':' >> e2 >> -(':' >> e2 >> -(':' >> e3) ) ) >> *eol;
struct file_line
{
  std::string a;
  unsigned short b;
  boost::optional<
    fusion::vector<
      std::string, 
      boost::optional<
        fusion::vector<std::string, boost::optional<std::string> >
      >
    >
  > c;
};