0

私はこれを単純に解析し、Boost::Spirit で xml 志向の構造を構成しようとしています。

One{
    Two{
        Three{
        }
    }
}

また、コードは次のように構成されています。

精神的なものを保持するための構造体の定義:

struct config;
typedef boost::variant< boost::recursive_wrapper<config> , std::string > config_node;

struct config
{
    std::string name;
    std::vector<config_node> children; 
};


BOOST_FUSION_ADAPT_STRUCT(
    config,
    (std::string, name)
    (std::vector<config_node>, children)
)

(恥知らずな xml のイントロから盗んだ)

ルールの宣言 (パーサー クラスで)

qi::rule<Iterator, config(), qi::locals<std::string>, ascii::space_type> cfg;
qi::rule<Iterator, config_node(), ascii::space_type> node;
qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;

パーサー 'parse' メソッドでのルールの定義。

    node = cfg;
    start_tag =  +(char_ -'{') >> '{';
    end_tag = char_('}');

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

_a と _1 は boost::phoenix 変数です。

このルールは、上に貼り付けられた小さな切り抜きに対して機能しますが、次のように変更すると:

One{
    Two{
    }
    Three{
    }
}

(他のグループ内のグループではなく、同じスコープ内の 2 つのグループ) パーサーが失敗します。理由がわかりません。

4

1 に答える 1

2

今後の参考のために、コードはBoost のチュートリアル (別名「恥知らずに盗まれたもの」) のmini_xml2.cppの簡略化されたバージョンのように見えます。

例を機能させるには、次の行を変更する必要があります。

start_tag =  +(char_ -'{') >> '{';

start_tag = +(char_ -'{' - '}') >> '{';

今ではかなり自明です:)パーサーが a を解析するときはいつでも、それはsstart_tagを探し始めます(部分のため)。は正当なであるため、1 つとして認識される可能性がありますが、認識されるべきではありません。node>> *node}start_tag


ところで、コードには、修正を検討する可能性のある冗長性がいくつかあります。例えば:

元の mini_xml2.cpp の例でend_tagは、開いたタグと同じタグを閉じることをチェックする関数として機能しました (したがって、署名void(std::string))。あなたはもっと良いでしょう

cfg %=  start_tag[_a = _1]
>> *node
>> "}";

mini_xml2.cpp の例のノードは多態的であるためboost::variant、訪問者と共に使用されました。あなたの例では、これも冗長です。正直、ラインがどうなってるのか気になる

node = cfg

nodeタイプがあるため、コンパイル中に問題は発生しませんでしたboost::variant。参考までに、元の例では、この行は次のとおりでした。

node %= xml | text;

オペレーターは結果を として読み取る%=ため、RHS のタイプを正しく「推測」しました。|boost::variant

于 2013-02-19T22:38:01.540 に答える