4

[私の説明と期待はまったく明確ではないようですので、投稿の最後にこの機能をどのように使用したいのかを正確に追加しました]

私は現在、boost qi を使用して文法に取り組んでいます。ベクトルの要素からルールを構築する必要があるため、ルールのループ構築がありました。単純な型で書き直しました。次のようになります。

#include <string>

// using boost 1.43.0
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_eps.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace bqi = boost::spirit::qi;

typedef const char* Iterator;

// function that you can find [here][1]
template<typename P> void test_phrase_parser(char const* input, P const& p, bool full_match = true);

int main()
{
    // my working rule type:
    bqi::rule<Iterator, std::string()> myLoopBuiltRule;
    std::vector<std::string> v;
    std::vector<std::string>::const_iterator iv;

    v.push_back("abc");
    v.push_back("def");
    v.push_back("ghi");
    v.push_back("jkl");

    myLoopBuiltRule = (! bqi::eps);
    for(iv = v.begin() ; iv != v.end() ; iv++)
    {
        myLoopBuiltRule =
                myLoopBuiltRule.copy()  [ bqi::_val = bqi::_1 ]
                | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]
                ;
    }
    debug(myLoopBuiltRule);

    char s[] = "  abc ";

    test_phrase_parser(s, myLoopBuiltRule);
}

(ここは対応するハイパーリンクに置き換えたくないので、関数 test_phrase_parser() を見つけるためのアドレスは次のとおりです: http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/ Spirit/qi/reference/basics.html )

すべては最善を尽くすためのものでした... 私がこのルールに反論しなければならなくなるまでは。新しいルール タイプは次のとおりです。

    // my not-anymore-working rule type:
    bqi::rule<Iterator, std::string(int*)> myLoopBuiltRule;

'int*' 型は単なる例です。私の実際のポインターは、はるかに複雑なクラスをアドレス指定していますが、それでも単なるポインターです。

それに応じて「for」ループを変更しました。

    for(iv = v.begin() ; iv != v.end() ; iv++)
    {
        myLoopBuiltRule =
                myLoopBuiltRule.copy()(bqi::_r1)    [ bqi::_val = bqi::_1 ]
                | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]
                ;
    }

test_phrase_parser() は int ポインターに与えられる値を推測できないため、新しいルールを追加する必要がありました。

bqi::rule<Iterator> myInitialRule;

for ループに続くすべてを変更します。

myInitialRule = myLoopBuiltRule((int*)NULL);

debug(myLoopBuiltRule);

char s[] = "  abc ";

test_phrase_parser(s, myInitialRule);

その後、すべてがクラッシュしました:

/home/sylvain.darras/software/repository/software/external/include/boost/boost_1_43_0/boost/spirit/home/qi/nonterminal/rule.hpp:199: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&)

それから私は夢中になって試しました:

myLoopBuiltRule =
        myLoopBuiltRule.copy(bqi::_r1)  [ bqi::_val = bqi::_1 ]
        | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]

-->

error: no matching function for call to ‘boost::spirit::qi::rule<const char*, std::string(int*), boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>::copy(const boost::phoenix::actor<boost::spirit::attribute<1> >&)’

それから私は怒って次のように書きました。

myLoopBuiltRule =
        myLoopBuiltRule(bqi::_r1)   [ bqi::_val = bqi::_1 ]
        | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]

構文的には完全に正しいのでコンパイルされますが、見事にスタックオーバーフローが発生し、楽しく、うまく、再帰的に、自分自身を死に至らしめます...

それから私は気を失ってタイプしました:

myLoopBuiltRule =
        jf jhsgf jshdg fjsdgh fjsg jhsdg jhg sjfg jsgh df

ご想像のとおり、これはコンパイルに失敗しました。

上記の小説を書く前に、私は Web でチェックアウトしましたが、同時に copy() と引数の受け渡しに関連するものを見つけられなかったと想像してください。誰かがすでにこの問題を経験していますか? 私は何かを逃しましたか?

どんな助けでも本当に感謝されることを確信してください。

PS: hkaiser に感謝します。知らず知らずのうちに、Google を介して私の boost::qi の問題の多くに答えてくれました (ただし、これは 1 つです)。


さらに詳しい情報:

私のパーサーの目的は、特定の言語 L で記述されたファイルを読み取ることです。私の投稿の目的は、私の「コンテキスト」を伝達することです (つまり、変数定義と特に定数値で、式を計算できます)。

私が扱う変数の型の数は少ないですが、必ず増えるので、これらの型をコンテナー クラスに保持しています。これらのマネージド型をループできます。

それでは、私が達成したいものの疑似アルゴリズムを考えてみましょう:

LTypeList myTypes;
LTypeList::const_iterator iTypes;

bqi::rule<Iterator, LType(LContext*)> myLoopBuiltRule;

myLoopBuiltRule = (! bqi::eps);
for(iTypes = myTypes.begin() ; iTypes != myTypes.end() ; iTypes++)
{
    myLoopBuiltRule =
        myLoopBuiltRule.copy()(bqi::_r1)    [ bqi::_val = bqi::_1 ]
        | iTypes->getRule()(bqi::_r1)           [ bqi::_val = bqi::_1 ]
}

これは初期化中に行われ、次に myLoopBuiltRule が使用され、異なる LContext* で再利用され、複数の型が解析されます。そして、一部の L 型は整数式である境界を持つことができ、これらの整数式は定数を表すことができるため、LContext を取り込んで式の値を計算できるようにするには、継承した属性が必要です (と思います)。

私の意図がより明確になったことを願っています。

4

1 に答える 1

2

いくつかの情報リンクを追加して、回答を拡張したことに注意してください。この特定のケースでは、 Nabialekのトリックを使用して、継承された属性を代わりに対応する属性に置き換えることができるという予感がありますqi::locals<>。時間があれば、後でデモンストレーションを行うかもしれません。

警告、問題の説明

特にプロト式ツリーとスピリット パーサー式をコピーする場合に問題があることに注意してください。内部は、含まれる完全な式の最後を超えて存続することは想定されていないため、ダングリング リファレンスが作成されます。2 秒で時速 0 マイルから 60マイルまで加速する BOOST_SPIRIT_AUTO をご覧ください。

また、オンザフライで(実行時に)ルールを構築/構成することに関係するこれらの回答も参照してください。

ナビアレク・トリック

一般に、実行時にルールを結合しないことを強くお勧めします。代わりに、実行時にルールに「代替案を追加」することを検討している場合は、qi::symbols<>代わりにいつでも使用できます。トリックは、ルールをシンボルテーブルに保存し、ルールqi::lazyを呼び出すために使用することです。特に、これはNabialek Trickとして知られています。

ここにおもちゃのコマンドライン引数パーサーがあります。これは、このイディオムを使用してランタイム定義のコマンドライン引数のセットと一致させる方法を示しています。

の制限、qi::lazy次は?

残念ながら、継承された引数qi::lazyをサポートしていません。例を参照してください

ここに記載されているように、カスタム パーサー コンポーネントを作成する方がよい場合があります。

後で、継承された引数を qi::locals で置き換えるサンプルを作成する時間を見つけようと思います。

于 2013-07-01T15:29:23.917 に答える