簡體   English   中英

Boost Spirit像語法一樣解析XML

[英]Boost Spirit parsing XML like grammar

我有以下代碼要修改,但我對Boost-spirit完全陌生。 我知道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_("\"{}= \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");

}

這是我嘗試解析的格式:

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_("\"{}= \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));
}

它包含了很多令人驚訝的東西

  • 冗余空白檢查,而船長已執行此操作
  • skip[]lexeme[]清楚地表明該規則已使用Skipper進行了聲明(如果未聲明,則所有規則都隱式地為“ lexemes”)
  • 格式化!

    • 當然,使用名稱空間會有所幫助。
    • qi :: lit僅在存在歧義或超載分辨率需要時才需要
    • 許多冗余()
    • 一行中的所有內容都構成了難以理解的規則。
      所建議的布局還使通過注釋一些行來更容易地有選擇地調試編譯問題。
  • BOOST_SPIRIT_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_("\"{}= \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打印的內容:

<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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM