忍者ブログ
ゲーム関連の話題に絞っていましたが、全然書かないのでいろいろ解禁してみたり。
[16]  [15]  [14]  [13]  [12]  [11
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

今回は組み込み関数に対応する引数に応じて後々のルールを変更する方法と言うことでひとつ。

#include <iostream>
#include <string>

#pragma warning(push)
#pragma warning(disable:4100) //引数は関数の本体部で 1 度も参照されません。
#pragma warning(disable:4512) //代入演算子を生成できません。
#pragma warning(disable:4819) //ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。
#pragma warning(disable:4127) //条件式が定数です。

#include <boost/spirit/include/qi_action.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi_lexeme.hpp>
#include <boost/spirit/include/qi_operator.hpp>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_rule.hpp>

#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_string.hpp>
#include <boost/spirit/include/qi_numeric.hpp>

#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>

#pragma warning(pop)

#pragma warning(disable:4503) //装飾された名前の長さが限界を越えました。

template<typename String, typename Skipper>
struct Parser : boost::spirit::qi::grammar<typename String::const_iterator, Skipper>{
    typedef typename String::const_iterator Iterator;
   
    boost::spirit::qi::rule<Iterator, Skipper> func1;
    boost::spirit::qi::rule<Iterator, Skipper> func2;
    boost::spirit::qi::symbols<char, boost::spirit::qi::rule<Iterator, Skipper>> funcs;
   
    boost::spirit::qi::rule<Iterator, Skipper> statement;
    boost::spirit::qi::rule<Iterator, boost::spirit::qi::locals<boost::spirit::qi::rule<Iterator, Skipper>>, Skipper> statement2;

    Parser() : Parser::base_type(statement){
        //文法定義
        {
            using namespace boost::spirit;
            using namespace boost::spirit::ascii;
            using namespace boost::spirit::labels;
            namespace phoenix = boost::phoenix;

            //テストコード

            func1 = '(' >> int_ >> ')';
            func2 = '(' >> char_ >> "," >> char_ >> ')';
            funcs.add
                ("func1", func1)
                ("func2", func2)
                ;
            statement2 = (funcs[_a = _1] >> lazy(_a));
            statement = statement2;
        }
    }
};

template<typename String>
struct SkipParser : boost::spirit::qi::grammar<typename String::const_iterator>{
    typedef typename String::const_iterator Iterator;

    SkipParser() : SkipParser::base_type(comment){
        using namespace boost::spirit;

        comment  = boost::spirit::ascii::space
            | ("//" >> *(qi::char_ - '\n') >> '\n')
            | ("/*" >> *(qi::char_ - "*/") >> "*/");
    }

    boost::spirit::qi::rule<Iterator> comment;
};

int main(void)
{
    namespace phoenix = boost::phoenix;

    typedef SkipParser<std::string> SkipperType;
    typedef Parser<std::string, SkipperType> ParserType;
    SkipperType skipper;

    ParserType parser;

    std::string str;
    while (getline(std::cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        std::string::const_iterator it = str.begin();
        std::string::const_iterator end = str.end();

        bool result = phrase_parse(it, end, parser, skipper);

        if (result && it == end)
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded\n";
            std::cout << str << " Parses OK: " << std::endl;
        }
        else if(result)
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded\n";
            std::cout << std::string(str.begin(), it) << " Parses OK: " << std::endl;
            std::cout << std::string(it, end) << " amari" << std::endl;
        }
        else
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "-------------------------\n";
        }
    }

    return 0;
}

symbolsさんを使います。
boost::spirit::qi::symbols<char, boost::spirit::qi::rule<Iterator, Skipper>> funcs;
コレは、前者の値に対応して後者を返すルールを簡単に作れるもの……です。多分。
今回は関数名と対応するルールで作りましたが、もっとわかりやすい例としては
boost::spirit::qi::symbols<char, int> nums;

nums.add
    ("one", 1)
    ("two", 2)
    ("three", 3)
    ;

とかして英語と数字のマッピングなんかも出来ちゃいます。多分。

あと、この部分
func1 = '(' >> int_ >> ')';
func2 = '(' >> char_ >> "," >> char_ >> ')';
funcs.add
    ("func1", func1)
    ("func2", func2)
    ;
statement2 = (funcs[_a = _1] >> lazy(_a));
statement = statement2;
を、こんな感じ
statement = statement2;
statement2 = (funcs[_a = _1] >> lazy(_a));
funcs.add
    ("func1", func1)
    ("func2", func2)
    ;

func1 = '(' >> int_ >> ')';
func2 = '(' >> char_ >> "," >> char_ >> ')';

にすると、うまく動きません。実行時エラー起こします。
設定の順番が大事みたいです。

さらに、この部分
statement2 = (funcs[_a = _1] >> lazy(_a));
statement = statement2;

を、こんな感じ
statement = (funcs[_a = _1] >> lazy(_a));

にしたい場合、
struct Parser : boost::spirit::qi::grammar<typename String::const_iterator, boost::spirit::qi::locals<boost::spirit::qi::rule<typename String::const_iterator, Skipper>>, Skipper>{

    <中略>

    boost::spirit::qi::rule<Iterator, boost::spirit::qi::locals<boost::spirit::qi::rule<Iterator, Skipper>>, Skipper> statement;

ってしないとダメみたいです。

とりあえず今日はこんなところで。
PR
この記事にコメントする
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
この記事へのトラックバック
この記事にトラックバックする:
Twitter
Twitter Update
ブログ内検索
カレンダー
05 2025/06 07
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
最新コメント
最新トラックバック
プロフィール
HN:
100poisha
性別:
非公開
アクセス解析
Copyright © 100poishaのブログ All Rights Reserved.
Designed by north sound
Powered by Ninja Blog

忍者ブログ [PR]