Boost Spirit解析类似XML的语法

Boost Spirit parsing XML like grammar

本文关键字:XML 语法 Spirit Boost      更新时间:2023-10-16

我有下面一段代码想修改修复程序,但我对提升精神是全新的。我知道RE,但不知道如何在精神上做到这一点。

这就是解析器。

Parser() : Parser::base_type(root)
{
    braces  = lit('{') >> *(iso8859_1::space) >> lit('}');
    str     = lexeme[lit('"') >> raw[*(~iso8859_1::char_('"'))] >> lit('"')];
    tolleaf = raw[+(~iso8859_1::char_(""{}= trn"))];
    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");
}

这就是我试图解析的格式:

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
}
}

问题是双{{。如果我只有一个

blahblah=
{
    value=
    {
        2
    }
}

它运行良好。

我知道这个

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

必须改变,但我不确定如何改变。

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

查看Coliru直播

Parser() : Parser::base_type(root)
{
    using namespace qi::iso8859_1;
    braces  = 
        '{' >> qi::eps >> '}'
        ;
    str     = qi::lexeme [
             '"'
          >> *~char_('"')
          >> '"'
        ]
        ;
    tolleaf = qi::lexeme [
            +(~char_(""{}= trn"))
        ]
        ;
    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));
}

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

  • 冗余的空白检查,而队长已经这样做了
  • skip[]lexeme[]的存在清楚地表明规则是使用Skipper声明的(如果不是,则所有规则都是隐含的"lexemes")
  • 格式化!

    • 当然,使用名称空间会有所帮助
    • qi::只有当存在歧义或过载解决方案需要时,才需要点亮
    • 许多冗余()
    • 一条线上的每件事都会产生令人费解的规则
      建议的布局还使选择性地调试编译问题变得更容易,只需注释一些行
  • 用于调试的BOOstrongPIRIT_DEBUG*宏。见完整工作样品下方的输出

注意我没有查看实际语法。这看起来也可以改进,但我没有时间尝试和理解预期的语法。然而,正如您所看到的,它解析了您在问题中显示的片段:

完整代码

#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_(""{}= trn"))
            ]
            ;
        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 successn";
        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;
}

输出

这是BOOstrongPIRIT_DEBUG打印的内容:

<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=1n</try>
              <fail/>
            </str>
            <taglist>
              <try>{n    province_id=1n</try>
              <str>
                <try>n    province_id=1n </try>
                <fail/>
              </str>
              <tolleaf>
                <try>province_id=1n    in</try>
                <success>=1n    index=0n    t</success>
                <attributes>[]</attributes>
              </tolleaf>
              <str>
                <try>=1n    index=0n    t</try>
                <fail/>
              </str>
              <tolleaf>
                <try>=1n    index=0n    t</try>
                <fail/>
              </tolleaf>
              <fail/>
            </taglist>
            <objlist>
              <try>{n    province_id=1n</try>
              <object>
                <try>n    province_id=1n </try>
                <fail/>
              </object>
              <fail/>
            </objlist>
            <object>
              <try>{n    province_id=1n</try>
              <root>
                <try>n    province_id=1n </try>
                <assign>
                  <try>n    province_id=1n </try>
                  <leaf>
                    <try>n    province_id=1n </try>
                    <success>=1n    index=0n    t</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>1n    index=0n    ty</try>
                    <success>n    index=0n    typ</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>n    index=0n    typ</success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>n    index=0n    typ</try>
                  <leaf>
                    <try>n    index=0n    typ</try>
                    <success>=0n    type=9n    }n</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>0n    type=9n    }n </try>
                    <success>n    type=9n    }n  </success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>n    type=9n    }n  </success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>n    type=9n    }n  </try>
                  <leaf>
                    <try>n    type=9n    }n  </try>
                    <success>=9n    }n    count=1</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>9n    }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=1750n}nn</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=1750n}nn</try>
                    <fail/>
                  </str>
                  <fail/>
                </assign>
                <braces>
                  <try>n    }n    count=175</try>
                  <fail/>
                </braces>
                <fail/>
              </root>
              <success>n    count=1750n}nn{</success>
              <attributes>[]</attributes>
            </object>
            <success>n    count=1750n}nn{</success>
            <attributes>[]</attributes>
          </assign>
          <assign>
            <try>n    count=1750n}nn{</try>
            <leaf>
              <try>n    count=1750n}nn{</try>
              <success>=1750n}nn{n    provi</success>
              <attributes>[]</attributes>
            </leaf>
            <leaf>
              <try>1750n}nn{n    provin</try>
              <success>n}nn{n    province_p</success>
              <attributes>[]</attributes>
            </leaf>
            <success>n}nn{n    province_p</success>
            <attributes>[]</attributes>
          </assign>
          <assign>
            <try>n}nn{n    province_p</try>
            <leaf>
              <try>n}nn{n    province_p</try>
              <fail/>
            </leaf>
            <str>
              <try>}nn{n    province_po</try>
              <fail/>
            </str>
            <fail/>
          </assign>
          <braces>
            <try>n}nn{n    province_p</try>
            <fail/>
          </braces>
          <success>n}nn{n    province_p</success>
          <attributes>[]</attributes>
        </root>
        <root>
          <try>n}nn{n    province_p</try>
          <assign>
            <try>n}nn{n    province_p</try>
            <leaf>
              <try>n}nn{n    province_p</try>
              <fail/>
            </leaf>
            <str>
              <try>}nn{n    province_po</try>
              <fail/>
            </str>
            <fail/>
          </assign>
          <braces>
            <try>n}nn{n    province_p</try>
            <fail/>
          </braces>
          <fail/>
        </root>
        <success>nn{n    province_pop</success>
        <attributes>[]</attributes>
      </object>
      <object>
        <try>nn{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=1n</try>
              <fail/>
            </str>
            <taglist>
              <try>{n    province_id=1n</try>
              <str>
                <try>n    province_id=1n </try>
                <fail/>
              </str>
              <tolleaf>
                <try>province_id=1n    in</try>
                <success>=1n    index=1n    t</success>
                <attributes>[]</attributes>
              </tolleaf>
              <str>
                <try>=1n    index=1n    t</try>
                <fail/>
              </str>
              <tolleaf>
                <try>=1n    index=1n    t</try>
                <fail/>
              </tolleaf>
              <fail/>
            </taglist>
            <objlist>
              <try>{n    province_id=1n</try>
              <object>
                <try>n    province_id=1n </try>
                <fail/>
              </object>
              <fail/>
            </objlist>
            <object>
              <try>{n    province_id=1n</try>
              <root>
                <try>n    province_id=1n </try>
                <assign>
                  <try>n    province_id=1n </try>
                  <leaf>
                    <try>n    province_id=1n </try>
                    <success>=1n    index=1n    t</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>1n    index=1n    ty</try>
                    <success>n    index=1n    typ</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>n    index=1n    typ</success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>n    index=1n    typ</try>
                  <leaf>
                    <try>n    index=1n    typ</try>
                    <success>=1n    type=9n    }n</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>1n    type=9n    }n </try>
                    <success>n    type=9n    }n  </success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>n    type=9n    }n  </success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>n    type=9n    }n  </try>
                  <leaf>
                    <try>n    type=9n    }n  </try>
                    <success>=9n    }n    count=3</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <leaf>
                    <try>9n    }n    count=34</try>
                    <success>n    }n    count=34n</success>
                    <attributes>[]</attributes>
                  </leaf>
                  <success>n    }n    count=34n</success>
                  <attributes>[]</attributes>
                </assign>
                <assign>
                  <try>n    }n    count=34n</try>
                  <leaf>
                    <try>n    }n    count=34n</try>
                    <fail/>
                  </leaf>
                  <str>
                    <try>}n    count=34n}n}n</try>
                    <fail/>
                  </str>
                  <fail/>
                </assign>
                <braces>
                  <try>n    }n    count=34n</try>
                  <fail/>
                </braces>
                <success>n    }n    count=34n</success>
                <attributes>[]</attributes>
              </root>
              <root>
                <try>n    }n    count=34n</try>
                <assign>
                  <try>n    }n    count=34n</try>
                  <leaf>
                    <try>n    }n    count=34n</try>
                    <fail/>
                  </leaf>
                  <str>
                    <try>}n    count=34n}n}n</try>
                    <fail/>
                  </str>
                  <fail/>
                </assign>
                <braces>
                  <try>n    }n    count=34n</try>
                  <fail/>
                </braces>
                <fail/>
              </root>
              <success>n    count=34n}n}n</success>
              <attributes>[]</attributes>
            </object>
            <success>n    count=34n}n}n</success>
            <attributes>[]</attributes>
          </assign>
          <assign>
            <try>n    count=34n}n}n</try>
            <leaf>
              <try>n    count=34n}n}n</try>
              <success>=34n}n}n</success>
              <attributes>[]</attributes>
            </leaf>
            <leaf>
              <try>34n}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