3

boost::spirit::qi::symbols のドキュメントの最初の段落に目を通すと、セマンティック アクションから qi::symbols にシンボルを追加するのはそれほど難しくないと思いました。残念ながら、私が想定していたほど簡単ではないようです。

次のテスト コードは、問題を示しています。

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;

typedef qi::symbols<char, unsigned int> constants_dictionary;

template <typename Iter> struct parser : public qi::grammar<Iter, qi::space_type> {

    parser(constants_dictionary &dict) : parser::base_type(start) {

        start = qi::lit("@") >> ((+qi::char_) >> qi::uint_)[dict.add(qi::_1, qi::_2)];
    }

    qi::rule<Iter> start;
};

int main() {
    constants_dictionary dict;
    parser<std::string::const_iterator> prsr(dict);
    std::string test = "@foo 3";
    parse(test.begin(), test.end(), prsr, qi::space);
}

VS2010 からの qi::_2 に関連する型エラーを示します。

C:\Users\k\Coding\dashCompiler\spirit_test.cpp(12) : error C2664: 'const boost::
spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::o
perator ()<boost::spirit::_1_type>(const Str &,const T &) const' : cannot conver
t parameter 2 from 'const boost::spirit::_2_type' to 'const unsigned int &'
        with
        [
            Char=char,
            T=unsigned int,
            Str=boost::spirit::_1_type
        ]
        Reason: cannot convert from 'const boost::spirit::_2_type' to 'const uns
igned int'
        No user-defined-conversion operator available that can perform this conv
ersion, or the operator cannot be called
        C:\Users\k\Coding\dashCompiler\spirit_test.cpp(10) : while compiling cla
ss template member function 'parser<Iter>::parser(constants_dictionary &)'
        with
        [
            Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
        ]
        C:\Users\k\Coding\dashCompiler\spirit_test.cpp(21) : see reference to cl
ass template instantiation 'parser<Iter>' being compiled
        with
        [
            Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
        ]

(厄介な VS2010 エラー スタイルの謝罪)

このテーブルにシンボルを追加 (および後で削除) するために使用する構文は何ですか?

4

1 に答える 1

6

この質問は以前に回答されています。ただし、投稿されたコードにはさまざまな問題があるため、1 つずつ修正して、エラー メッセージのページを不必要に見つめなくても済むようにします。

実際のコード (および出力の検証) はliveworkspace.org にあります。

ノート:

  1. セマンティック アクションは Phoenixアクターでなければなりません。

    • boost::bindphoenix::bindstd::bind
    • phoenix::lambda<>またphoenix::function<>
    • 関数ポインタまたはポリモーフィック呼び出し可能オブジェクト (ドキュメントに従って)

      phoenix::bind以下に示すように、(この特定のケースでは)お勧めします

  2. パーサーのスキッパーと開始ルールの間に不一致がありました
  3. qi::char_すべての文字を食べます。スキッパーと組み合わせると、(明らかに) 値の数字も によって食べられていたため、解析に失敗しました+qi::char_。に基づいて、多くのソリューションの1つを紹介しますqi::lexeme[+qi::graph]
  4. スキッパーを「バイパス」するために使用しますqi::lexeme(つまり、スキッパーがスキップしたために +qi::graph が空白をまたぐのを防ぐため)
  5. qi::parseスキッパーを取りません。そのために使用します(機能しているようqi::phrase_parseに見える理由は、末尾の「可変個引数」引数がパーサーの公開された属性にバインドされているためです。この場合は指定されていないため、)。qi::unused_type
  6. test.begin()and を にtest.end()直接 渡したい場合はqi::phrase_parse、const イテレータが必要であることを明確にする必要があります。より典型的な解決策は、明示的に型指定された変数 ( firstandlastなど)を導入することです。


#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

typedef qi::symbols<char, unsigned int> constants_dictionary;

template <typename Iter> struct parser : qi::grammar<Iter, qi::space_type> 
{
    parser(constants_dictionary &dict) : parser::base_type(start) 
    {
        start = qi::lit("@") >> (qi::lexeme [+qi::graph] >> qi::uint_)
            [ phx::bind(dict.add, qi::_1, qi::_2) ]
            ;
    }

    qi::rule<Iter, qi::space_type> start;
};

int main() {
    constants_dictionary dict;
    parser<std::string::const_iterator> prsr(dict);
    const std::string test = "@foo 3";

    if (qi::phrase_parse(test.begin(), test.end(), prsr, qi::space))
    {
        std::cout << "check: " << dict.at("foo") << "\n";
    }
}
于 2012-08-31T10:16:26.627 に答える