1

Boost.Spiritを使用してxml解析を拡張し、xml属性の解析を追加したいと思います。

ここにライブラリからの例と私からのいくつかの変更があります:

template <typename Iterator>
struct mini_xml_grammar
: qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
{
    mini_xml_grammar()
    : mini_xml_grammar::base_type(xml, "xml")
    {
        using qi::lit;
        using qi::lexeme;
        using qi::attr;
        using qi::on_error;
        using qi::fail;
        using ascii::char_;
        using ascii::string;
        using ascii::alnum;
        using ascii::space;

        using namespace qi::labels;

        using phoenix::construct;
        using phoenix::val;


        text %= lexeme[+(char_ - '<')];
        node %= xml | text;


        start_tag %=
        '<'
        >>  !lit('/')
        >   lexeme[+(char_ - '>')]
        >   '>'
        ;

        end_tag =
        "</"
        >   string(_r1)
        >   '>'
        ;

        xml %=
        start_tag[_a = _1]
        >   *node
        >   end_tag(_a)
        ;

        xml.name("xml");
        node.name("node");
        text.name("text");
        start_tag.name("start_tag");
        end_tag.name("end_tag");

        on_error<fail>
        (
         xml
         , std::cout
         << val("Error! Expecting ")
         << _4                               // what failed?
         << val(" here: \"")
         << construct<std::string>(_3, _2)   // iterators to error-pos, end
         << val("\"")
         << std::endl
         );
    }

    qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
    qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
    qi::rule<Iterator, std::string(), ascii::space_type> text;
    qi::rule<Iterator, std::string(), ascii::space_type> attribute;
    qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
    qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
};

これを試しましたが、「宣言されていない識別子'eps'の使用」というエラーでコンパイルされません。

        xml %= 
        start_tag[_a = _1] 
        > attribute 
        > (  "/>" > eps
            |  ">" > *node > end_tag(_a) 
            )
        ;

誰かがそれを行う方法を知っていますか?xml属性を解析する機能を追加するにはどうすればよいですか?

4

1 に答える 1

2

eps識別子は、使用する他の多くの識別子と同様に、qi名前空間で定義されます。usingその他は、コンストラクターの上部にあるステートメントを使用してグローバル名前空間に取り込まれます。同じことをしてくださいeps

using qi::eps;

これを解決すると、XMLの構文と文法を正しく表現しているかどうかという大きな問題が発生します。あなたがそれを正しく持っているようには見えません。あなたはこれを持っています:

xml %= 
      start_tag[_a = _1]
    > attribute
    > (   "/>" > eps
        | ">" > *node > end_tag(_a)
      )
    ;

しかし、それは正しくありません。属性はタグの一部であり、タグに続くものではありません。start_tag空のタグを処理できるように、appartを壊したかったようです。これを行う場合は、empty_tag代わりにルールを作成してから、に変更xmlしますempty_tag | (start_tag > *node > end_tag)。これが、W3C言語の推奨事項の方法です。

[39]  element   ::= EmptyElemTag
                    | STag content ETag

しかし、今のところそれについて心配する必要はありません。あなたが述べたタスクはパーサーに属性を追加することであることを忘れないでください。他の不足している機能に気を取られないでください。後で取り組むべきものはたくさんあります。

W3Cドキュメントについて触れました。あなたはそれを頻繁に参照する必要があります。言語を定義し、文法も表示します。Spiritの設計目標の1つは、文法定義のように見えるようにすることでした。独自のコードでW3C文法を模倣してみることで、これを活用してください。W3Cは、次のように開始タグを定義します。

[40]  STag      ::= '<' Name (S Attribute)* S? '>'
[41]  Attribute ::= Name Eq AttValue    

したがって、次のようにコードを記述します。

start_tag %=
    // Can't use operator> for "expect" because empty_tag
    // will be the same up to the final line.
       '<'
    >> !lit('/')
    >> name
    >> *attribute
    >> '>'
    ;

name %= ...; // see below

attribute %=
      name
    > '='
    > attribute_value
    ;

仕様では、属性値の構文を定義しています。

[10]  AttValue  ::= '"' ([^<&"] | Reference)* '"'
                    |  "'" ([^<&'] | Reference)* "'"

エンティティ参照についてはまだ心配していません。空のタグと同様に、現在のコードはすでにそれらをサポートしていないため、属性の一部として今すぐ追加することは重要ではありません。これにより、次のことをattribute_value簡単に定義できます。

attribute_value %=
      '"' > *(char_ - char_("<&\"")) > '"'
    | '\'' > *(char_ - char_("<&'")) > '\''
    ;

定義はまだ派手なものであるname必要はありません。Unicodeの全範囲の文字を処理するため、仕様は複雑ですが、パーサー全体でUnicode文字を処理する方法を理解するときに、より単純なものから始めて、後でそれに戻ることができます。

name %=
    lexeme[char_("a-zA-Z:_") >> *char_("-a-zA-Z0-9:_")]
    ;

これらの変更により、XML属性を解析できるようになります。ただし、結果をSpirit属性として抽出することは別の問題であり(プログラムの残りの部分で特定のタグの属性の名前と値を知ることができます)、今はそれについて説明する準備ができていません。

于 2012-02-27T23:59:35.887 に答える