2

いくつかの入力を照合し、複雑なオブジェクトを構築してから、いくつかの小道具に応じて 2 つの方法で残りの入力を照合する必要があります。構築されたオブジェクトの。私は qi::eps(/ condition /) >> p1 |を試しました。p2しかし、結果は私にとって明らかです。簡略化されたコードhttp://liveworkspace.org/code/1NzThA $6

コード スニペットでは、入力から int_ に一致し、値 == 0 の場合は 'a' または 'b' と一致しようとしますが、'0b' 入力には問題ありません! ブレースで遊んでみましたが、うまくいきませんでした。

4

2 に答える 2

3

個人的には、セマンティック アクション (またはフェニックス) をこれほど軽視するつもりはありません。それは気の「精神」ではありません(しゃれ半ば意図)。

これは私の見解です:

rule<char const*, char()> r = 
   (omit [ int_(0) ] >> char_('a')) |
   (omit [ int_(1) ] >> char_('b'))
   ;

見る?ずっときれい。また、属性の自動伝播。http://liveworkspace.org/code/1T9h5で実際にご覧ください

出力:

ok: a
fail
fail
ok: b

完全なサンプル コード:

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

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

template <typename P>
inline
void test_parser(char const* input, P const& p, bool full_match = true)
{
    char const* f(input);
    char const* l(f + strlen(f));
    char result;
    if (qi::parse(f, l, p, result) && (!full_match || (f == l)))
        std::cout << "ok: " << result << std::endl;
    else
        std::cout << "fail" << std::endl;
}

int main()
{
   int p;
   using namespace qi;
   rule<char const*, char()> r = 
       (omit [ int_(0) ] >> char_('a')) |
       (omit [ int_(1) ] >> char_('b'))
       ;

   BOOST_SPIRIT_DEBUG_NODE(r);

   test_parser("0a", r); //should match
   test_parser("0b", r); //should not match
   test_parser("1a", r); //should not match
   test_parser("1b", r); //should match
}
于 2013-01-29T08:30:08.853 に答える
1

これがあなたのルールです:

qi::rule<char const*> r =
    qi::int_ [phoenix::ref(p) = qi::_1]
    >> (qi::eps(phoenix::ref(p) == 0)
        >> qi::char_('a') | qi::char_('b'))

つまり、「0a」または「b」で終わるものを受け入れます。これは、コード スニペットで得られる結果と一致します。

あなたの質問を完全には理解していないことを告白しますが、(コード スニペットのコメントで示されているように) ある種の「排他的または」ことを起こそうとする場合、このルールは不完全です。コメントで提示した回避策(実際には「回避策」というよりも「修正」のほうが多い)は1つの解決策ですがqi::lazy、フェニックスベースのQiローカルはすでに怠惰であるため必要ありませんが、正しい方向に進んでいます. これが別の(より読みやすい?)解決策です。

qi::rule<char const*> r =
    qi::int_ [phoenix::ref(p) = qi::_1]
    >> ((qi::eps(phoenix::ref(p) == 0) >> qi::char_('a')) | 
        (qi::eps(phoenix::ref(p) == 1) >> qi::char_('b')))
;

コメントに追加した locals<> を使用したい場合も問題ありませんが、参照を使用すると、文法の他の場所pに設定しないことを忘れない限り、コードのオーバーヘッドが少なくなります。pそのルールを再帰する文法を構築することになります:)

于 2013-01-28T10:07:11.010 に答える