Boost Spirit像语法一样解析XML [英] Boost Spirit parsing XML like grammar

查看:63
本文介绍了Boost Spirit像语法一样解析XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码要修改,但是我对Boost-spirit完全陌生. 我知道RE是精打细算的,但不知道该怎么做.

I've got the following piece of code I want to modify fix, but I am totally new to boost-spirit. I know RE's but not how to exactly do them in spirit.

这是解析器.

Parser() : Parser::base_type(root)
{
    braces  = lit('{') >> *(iso8859_1::space) >> lit('}');
    str     = lexeme[lit('"') >> raw[*(~iso8859_1::char_('"'))] >> lit('"')];
    tolleaf = raw[+(~iso8859_1::char_("\"{}= \t\r\n"))];
    leaf    = raw[+(iso8859_1::alnum | iso8859_1::char_("-._:"))];
    taglist = lit('{') >> omit[*(iso8859_1::space)] >> lexeme[( ( str | skip[tolleaf] ) % *(iso8859_1::space) )] >> omit[*(iso8859_1::space)] >> lit('}');
    object  = raw[lit('{') >> *(root) >> *(iso8859_1::space) >> lit('}')];
    objlist = raw[lit('{') >> *( *(iso8859_1::space) >> object[&pushObj] ) >> *(iso8859_1::space) >> lit('}')];
    assign  = raw[(*(iso8859_1::space) >> ( leaf[&setLHS] | str[&setLHS]) >> *(iso8859_1::space) >> lit('=')
        >> *(iso8859_1::space) 
        >> ( leaf[&setRHSleaf] | str[&setRHSleaf] | taglist[&setRHStaglist] | objlist[&setRHSobjlist] | object[&setRHSobject] ) 
        >> *(iso8859_1::space))];
    root    = +(assign | braces);

    str.name("str");
    leaf.name("leaf");
    taglist.name("taglist");
    object.name("object");
    objlist.name("objlist");
    assign.name("assign");
    braces.name("braces");
    root.name("root");

}

这是我尝试解析的格式:

And this is the format I'm trying to parse:

employees=
{
{
    province_pop_id=
    {
    province_id=1
    index=0
    type=9
    }
    count=1750
}

{
    province_pop_id=
    {
    province_id=1
    index=1
    type=9
    }
    count=34
}
}

问题是双重{{.如果我只有

The problem is the double {{. If I just have a

blahblah=
{
    value=
    {
        2
    }
}

它工作正常.

我知道这个

 objlist = raw[lit('{') >> *( *(iso8859_1::space) >> object[&pushObj] ) >> *(iso8859_1::space) >> lit('}')];

需要更改,但是我不确定如何更改.

has to be changed, but I'm not sure how.

推荐答案

所以,为了向您展示我的意思,我已经清理了语法.

So, just to show you what I meant, I've cleaned up the grammar.

查看 在Coliru上直播

See it Live on Coliru

Parser() : Parser::base_type(root)
{
    using namespace qi::iso8859_1;

    braces  = 
        '{' >> qi::eps >> '}'
        ;
    str     = qi::lexeme [
             '"'
          >> *~char_('"')
          >> '"'
        ]
        ;
    tolleaf = qi::lexeme [
            +(~char_("\"{}= \t\r\n"))
        ]
        ;
    leaf    = qi::lexeme [
            +(alnum | char_("-._:"))
        ]
        ;
    taglist = 
           '{'
        >> -str % tolleaf
        >> '}'
        ;
    object  = 
             '{'
          >> *root
          >> '}'
        ;
    objlist = 
             '{'
          >> *object
          >> '}'
        ;
    assign  = 
             (leaf | str)
          >> '='
          >> (leaf | str | taglist | objlist | object) 
        ;
    root    = 
        +(assign | braces)
        ;

    BOOST_SPIRIT_DEBUG_NODES((root)(braces)(str)(tolleaf)(leaf)(taglist)(objlist)(object)(assign));
}

它包含了很多令人惊讶的东西

It contained quite a few surprising things

  • 冗余空白检查,而船长已经执行了此操作
  • skip[]lexeme[]的存在清楚地表明该规则已使用Skipper声明(如果未声明,则所有规则都隐式地为"lexemes")
  • 格式化!

  • Redundant whitespace checking, while a skipper already does this
  • The presence of skip[] and lexeme[] clearly suggests that the rules have been declared using a Skipper (if not, all rules are implicitely "lexemes")
  • Formatting!

  • 当然,使用名称空间会有所帮助.
  • qi :: lit仅在存在歧义或需要重载解决方案时才需要
  • 许多多余()
  • 单行中的所有内容都会产生难以理解的规则.
    建议的布局还使通过注释某些行来选择性地调试编译问题变得更加容易

BOOST_SPIRIT_DEBUG *宏用于调试.请参阅完整工作示例下方的输出

BOOST_SPIRIT_DEBUG* macros for debugging. See the output below the fully working sample

注意:我查看了实际的语法.看起来这也可以改进,但是我没有时间尝试去理解预期的语法.但是,您可以看到它解析了您在问题中显示的代码段:

Note I've NOT looked at the actual grammar. It looks like this could be improved, too, but I don't have the time to try and understand the intended grammar. However, as you can see it parses the snippet you showed in the question:

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi        = boost::spirit::qi;

template <typename It, typename Skipper = qi::iso8859_1::space_type>
    struct Parser : qi::grammar<It, Skipper>
{
    Parser() : Parser::base_type(root)
    {
        using namespace qi::iso8859_1;

        braces  = 
            '{' >> qi::eps >> '}'
            ;
        str     = qi::lexeme [
                 '"'
              >> *~char_('"')
              >> '"'
            ]
            ;
        tolleaf = qi::lexeme [
                +(~char_("\"{}= \t\r\n"))
            ]
            ;
        leaf    = qi::lexeme [
                +(alnum | char_("-._:"))
            ]
            ;
        taglist = 
               '{'
            >> -str % tolleaf
            >> '}'
            ;
        object  = 
                 '{'
              >> *root
              >> '}'
            ;
        objlist = 
                 '{'
              >> *object
              >> '}'
            ;
        assign  = 
                 (leaf | str)
              >> '='
              >> (leaf | str | taglist | objlist | object) 
            ;
        root    = 
            +(assign | braces)
            ;

        BOOST_SPIRIT_DEBUG_NODES((root)(braces)(str)(tolleaf)(leaf)(taglist)(objlist)(object)(assign));
    }

  private:
    qi::rule<It, Skipper> root, braces, str, tolleaf, leaf, taglist, objlist, object, assign;
};

int main()
{
    typedef boost::spirit::istream_iterator It;
    std::cin.unsetf(std::ios::skipws);
    It f(std::cin), l;

    namespace iso8859_1 = qi::iso8859_1;
    Parser<It, iso8859_1::space_type> p;

    try
    {
        bool ok = qi::phrase_parse(f,l,p,iso8859_1::space);
        if (ok)   std::cout << "parse success\n";
        else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

        if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
        return ok;
    } catch(const qi::expectation_failure<It>& e)
    {
        std::string frag(e.first, e.last);
        std::cerr << e.what() << "'" << frag << "'\n";
    }

    return false;
}

输出

这是BOOST_SPIRIT_DEBUG打印的内容:

Output

This is what BOOST_SPIRIT_DEBUG prints:

<root>
  <try>employees=\n{\n{\n    p</try>
  <assign>
    <try>employees=\n{\n{\n    p</try>
    <leaf>
      <try>employees=\n{\n{\n    p</try>
      <success>=\n{\n{\n    province_p</success>
      <attributes>[]</attributes>
    </leaf>
    <leaf>
      <try>\n{\n{\n    province_po</try>
      <fail/>
    </leaf>
    <str>
      <try>{\n{\n    province_pop</try>
      <fail/>
    </str>
    <taglist>
      <try>{\n{\n    province_pop</try>
      <str>
        <try>\n{\n    province_pop_</try>
        <fail/>
      </str>
      <tolleaf>
        <try>{\n    province_pop_i</try>
        <fail/>
      </tolleaf>
      <fail/>
    </taglist>
    <objlist>
      <try>{\n{\n    province_pop</try>
      <object>
        <try>\n{\n    province_pop_</try>
        <root>
          <try>\n    province_pop_id</try>
          <assign>
            <try>\n    province_pop_id</try>
            <leaf>
              <try>\n    province_pop_id</try>
              <success>=\n    {\n    province</success>
              <attributes>[]</attributes>
            </leaf>
            <leaf>
              <try>\n    {\n    province_</try>
              <fail/>
            </leaf>
            <str>
              <try>{\n    province_id=1\n</try>
              <fail/>
            </str>
            <taglist>
              <try>{\n    province_id=1\n</try>
              <str>
                <try>\n    province_id=1\n </try>
                <fail/>
              </str>
              <tolleaf>
                <try>province_id=1\n    in</try>
                <success>=1\n    index=0\n    t</success>
                <attributes>[]</attributes>
              </tolleaf>
              <str>
                <try>=1\n    index=0\n    t</try>
                <fail/>
              </str>
              <tolleaf>
                <try>=1\n    index=0\n    t</try>
                <fail/>
              </tolleaf>
              <fail/>
            </taglist>
            <objlist>
              <try>{\n    province_id=1\n</try>
              <object>
                <try>\n    province_id=1\n </try>
                <fail/>
              </object>
              <fail/>
            </objlist>
            <object>
              <try>{\n    province_id=1\n</try>
              <root>
                <try>\n    province_id=1\n </try>
                <assign>
                  <try>\n    province_id=1\n </try>
                  <leaf>
                    <try>\n    province_id=1\n </try>
                    <success>=1\n    index=0\n    t</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>1\n    index=0\n    ty</try>
                    <success>\n    index=0\n    typ</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>\n    index=0\n    typ</success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>\n    index=0\n    typ</try>
                  <leaf>
                    <try>\n    index=0\n    typ</try>
                    <success>=0\n    type=9\n    }\n</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>0\n    type=9\n    }\n </try>
                    <success>\n    type=9\n    }\n  </success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>\n    type=9\n    }\n  </success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>\n    type=9\n    }\n  </try>
                  <leaf>
                    <try>\n    type=9\n    }\n  </try>
                    <success>=9\n    }\n    count=1</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>9\n    }\n    count=17</try>
                    <success>\n    }\n    count=175</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>\n    }\n    count=175</success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>\n    }\n    count=175</try>
                  <leaf>
                    <try>\n    }\n    count=175</try>
                    <fail/>
                  </leaf>
                  <str>
                    <try>}\n    count=1750\n}\n\n</try>
                    <fail/>
                  </str>
                  <fail/>
                </assign>
                <braces>
                  <try>\n    }\n    count=175</try>
                  <fail/>
                </braces>
                <success>\n    }\n    count=175</success>
                <attributes>[]</attributes>
              </root>
              <root>
                <try>\n    }\n    count=175</try>
                <assign>
                  <try>\n    }\n    count=175</try>
                  <leaf>
                    <try>\n    }\n    count=175</try>
                    <fail/>
                  </leaf>
                  <str>
                    <try>}\n    count=1750\n}\n\n</try>
                    <fail/>
                  </str>
                  <fail/>
                </assign>
                <braces>
                  <try>\n    }\n    count=175</try>
                  <fail/>
                </braces>
                <fail/>
              </root>
              <success>\n    count=1750\n}\n\n{</success>
              <attributes>[]</attributes>
            </object>
            <success>\n    count=1750\n}\n\n{</success>
            <attributes>[]</attributes>
          </assign>
          <assign>
            <try>\n    count=1750\n}\n\n{</try>
            <leaf>
              <try>\n    count=1750\n}\n\n{</try>
              <success>=1750\n}\n\n{\n    provi</success>
              <attributes>[]</attributes>
            </leaf>
            <leaf>
              <try>1750\n}\n\n{\n    provin</try>
              <success>\n}\n\n{\n    province_p</success>
              <attributes>[]</attributes>
            </leaf>
            <success>\n}\n\n{\n    province_p</success>
            <attributes>[]</attributes>
          </assign>
          <assign>
            <try>\n}\n\n{\n    province_p</try>
            <leaf>
              <try>\n}\n\n{\n    province_p</try>
              <fail/>
            </leaf>
            <str>
              <try>}\n\n{\n    province_po</try>
              <fail/>
            </str>
            <fail/>
          </assign>
          <braces>
            <try>\n}\n\n{\n    province_p</try>
            <fail/>
          </braces>
          <success>\n}\n\n{\n    province_p</success>
          <attributes>[]</attributes>
        </root>
        <root>
          <try>\n}\n\n{\n    province_p</try>
          <assign>
            <try>\n}\n\n{\n    province_p</try>
            <leaf>
              <try>\n}\n\n{\n    province_p</try>
              <fail/>
            </leaf>
            <str>
              <try>}\n\n{\n    province_po</try>
              <fail/>
            </str>
            <fail/>
          </assign>
          <braces>
            <try>\n}\n\n{\n    province_p</try>
            <fail/>
          </braces>
          <fail/>
        </root>
        <success>\n\n{\n    province_pop</success>
        <attributes>[]</attributes>
      </object>
      <object>
        <try>\n\n{\n    province_pop</try>
        <root>
          <try>\n    province_pop_id</try>
          <assign>
            <try>\n    province_pop_id</try>
            <leaf>
              <try>\n    province_pop_id</try>
              <success>=\n    {\n    province</success>
              <attributes>[]</attributes>
            </leaf>
            <leaf>
              <try>\n    {\n    province_</try>
              <fail/>
            </leaf>
            <str>
              <try>{\n    province_id=1\n</try>
              <fail/>
            </str>
            <taglist>
              <try>{\n    province_id=1\n</try>
              <str>
                <try>\n    province_id=1\n </try>
                <fail/>
              </str>
              <tolleaf>
                <try>province_id=1\n    in</try>
                <success>=1\n    index=1\n    t</success>
                <attributes>[]</attributes>
              </tolleaf>
              <str>
                <try>=1\n    index=1\n    t</try>
                <fail/>
              </str>
              <tolleaf>
                <try>=1\n    index=1\n    t</try>
                <fail/>
              </tolleaf>
              <fail/>
            </taglist>
            <objlist>
              <try>{\n    province_id=1\n</try>
              <object>
                <try>\n    province_id=1\n </try>
                <fail/>
              </object>
              <fail/>
            </objlist>
            <object>
              <try>{\n    province_id=1\n</try>
              <root>
                <try>\n    province_id=1\n </try>
                <assign>
                  <try>\n    province_id=1\n </try>
                  <leaf>
                    <try>\n    province_id=1\n </try>
                    <success>=1\n    index=1\n    t</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>1\n    index=1\n    ty</try>
                    <success>\n    index=1\n    typ</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>\n    index=1\n    typ</success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>\n    index=1\n    typ</try>
                  <leaf>
                    <try>\n    index=1\n    typ</try>
                    <success>=1\n    type=9\n    }\n</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>1\n    type=9\n    }\n </try>
                    <success>\n    type=9\n    }\n  </success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>\n    type=9\n    }\n  </success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>\n    type=9\n    }\n  </try>
                  <leaf>
                    <try>\n    type=9\n    }\n  </try>
                    <success>=9\n    }\n    count=3</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>9\n    }\n    count=34</try>
                    <success>\n    }\n    count=34\n</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>\n    }\n    count=34\n</success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>\n    }\n    count=34\n</try>
                  <leaf>
                    <try>\n    }\n    count=34\n</try>
                    <fail/>
                  </leaf>
                  <str>
                    <try>}\n    count=34\n}\n}\n</try>
                    <fail/>
                  </str>
                  <fail/>
                </assign>
                <braces>
                  <try>\n    }\n    count=34\n</try>
                  <fail/>
                </braces>
                <success>\n    }\n    count=34\n</success>
                <attributes>[]</attributes>
              </root>
              <root>
                <try>\n    }\n    count=34\n</try>
                <assign>
                  <try>\n    }\n    count=34\n</try>
                  <leaf>
                    <try>\n    }\n    count=34\n</try>
                    <fail/>
                  </leaf>
                  <str>
                    <try>}\n    count=34\n}\n}\n</try>
                    <fail/>
                  </str>
                  <fail/>
                </assign>
                <braces>
                  <try>\n    }\n    count=34\n</try>
                  <fail/>
                </braces>
                <fail/>
              </root>
              <success>\n    count=34\n}\n}\n</success>
              <attributes>[]</attributes>
            </object>
            <success>\n    count=34\n}\n}\n</success>
            <attributes>[]</attributes>
          </assign>
          <assign>
            <try>\n    count=34\n}\n}\n</try>
            <leaf>
              <try>\n    count=34\n}\n}\n</try>
              <success>=34\n}\n}\n</success>
              <attributes>[]</attributes>
            </leaf>
            <leaf>
              <try>34\n}\n}\n</try>
              <success>\n}\n}\n</success>
              <attributes>[]</attributes>
            </leaf>
            <success>\n}\n}\n</success>
            <attributes>[]</attributes>
          </assign>
          <assign>
            <try>\n}\n}\n</try>
            <leaf>
              <try>\n}\n}\n</try>
              <fail/>
            </leaf>
            <str>
              <try>}\n}\n</try>
              <fail/>
            </str>
            <fail/>
          </assign>
          <braces>
            <try>\n}\n}\n</try>
            <fail/>
          </braces>
          <success>\n}\n}\n</success>
          <attributes>[]</attributes>
        </root>
        <root>
          <try>\n}\n}\n</try>
          <assign>
            <try>\n}\n}\n</try>
            <leaf>
              <try>\n}\n}\n</try>
              <fail/>
            </leaf>
            <str>
              <try>}\n}\n</try>
              <fail/>
            </str>
            <fail/>
          </assign>
          <braces>
            <try>\n}\n}\n</try>
            <fail/>
          </braces>
          <fail/>
        </root>
        <success>\n}\n</success>
        <attributes>[]</attributes>
      </object>
      <object>
        <try>\n}\n</try>
        <fail/>
      </object>
      <success>\n</success>
      <attributes>[]</attributes>
    </objlist>
    <success>\n</success>
    <attributes>[]</attributes>
  </assign>
  <assign>
    <try>\n</try>
    <leaf>
      <try>\n</try>
      <fail/>
    </leaf>
    <str>
      <try></try>
      <fail/>
    </str>
    <fail/>
  </assign>
  <braces>
    <try>\n</try>
    <fail/>
  </braces>
  <success>\n</success>
  <attributes>[]</attributes>
</root>
parse success

这篇关于Boost Spirit像语法一样解析XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆