詳細:スキャナ

基本スキャナ API

scanner クラス
value_t typedef:スキャナが用いるイテレータの値の型
ref_t typedef:スキャナが用いるイテレータの参照型
bool at_end() const 入力が尽きていれば真を返す
value_t operator*() const 参照はがし/入力から value_t を取得する
scanner const& operator++() スキャナを前方に進める
IteratorT& first 現在の入力位置を指すイテレータ。参照で保持される
IteratorT const last 入力の末尾を指すイテレータ。値で保持される

スキャナの基本的な振る舞いはポリシーによって扱われる。 上の表に挙げられているスキャナの公開メンバ関数の実際の実行はスキャナポリシーによって実装されている。

三つのポリシーの組みがスキャナの振る舞いを司る。 これらのポリシーは煩わしいことなく Spirit を拡張することを可能とする。 スキャナポリシーは、潜在的に不安定化の要因となるコードの変更をすることなしに、中核機能を拡張できるようにする。 ライブラリ作成者は、構文解析処理を自分の要求に沿うよう詳細に調整するために、既存のものを上書きする独自のポリシーを提供してもよい。 コアレイヤーより上のレイヤーもこのポリシーを基礎とした機構の利点を得ることができる。 抽象構文木(abstract syntax tree)の生成、デバッガ、それにレキサが思い浮かぶ。

ポリシーには三つの組があり、それぞれ以下を司る:

iteration_policy

以下はイテレーションとフィルタリングを司るデフォルトのポリシーである:

    struct iteration_policy
    {
        template <typename ScannerT>
        void
        advance(ScannerT const& scan) const
        { ++scan.first; }

        template <typename ScannerT>
        bool at_end(ScannerT const& scan) const
        { return scan.first == scan.last; }

        template <typename T>
        T filter(T ch) const
        { return ch; }

        template <typename ScannerT>
        typename ScannerT::ref_t
        get(ScannerT const& scan) const
        { return *scan.first; }
    };
イテレーションポリシーとフィルタリングポリシー
advance イテレータを前方に進める
at_end 入力が尽きていれば真を返す
filter 入力から読み込まれた文字をフィルターする
get 入力から文字を読み込む

次のコード断片は、すべての文字を小文字に変換する単純なポリシーを示す:

    struct inhibit_case_iteration_policy : public iteration_policy
    {
        template <typename CharT>
        CharT filter(CharT ch) const
        { return std::tolower(ch); }
    };

match_policy

以下は、認識とマッチングを司るデフォルトのポリシーである:

    struct match_policy
    {
        template <typename T>
        struct result { typedef match<T> type; };

        const match<nil_t>
        no_match() const
        { return match<nil_t>(); }

        const match<nil_t>
        empty_match() const
        { return match<nil_t>(0, nil_t()); }

        template <typename AttrT, typename IteratorT>
        match<AttrT>
        create_match(
            unsigned            length,
            AttrT const&        val,
            IteratorT const&    /*first*/,
            IteratorT const&    /*last*/) const
        { return match<AttrT>(length, val); }

        template <typename MatchT, typename IteratorT>
        void
        group_match(
            MatchT&             /*m*/,
            parser_id const&    /*id*/,
            IteratorT const&    /*first*/,
            IteratorT const&    /*last*/) const {}

        template <typename Match1T, typename Match2T>
        void
        concat_match(Match1T& l, Match2T const& r) const
        { l.concat(r); }
    };
認識とマッチング
result 与えられた属性型に従ってマッチ型を返すメタ関数(詳細:パーサを参照)
no_match 失敗したマッチを作成する
empty_match 空のマッチを作成する。空のマッチは成功したεマッチ(マッチ長さ == 0)である。
create_match 与えられたマッチング長に応じたマッチ、属性、および入力のマッチ部を指すイテレータの組を作成する。
group_match 一致判定に成功した後に、ルールなどの非終端記号に対して後処理を許すために呼び出される。
concat_match 二つの一致判定オブジェクトを連結する。

action_policy

アクションポリシーはセマンティックアクションを扱うためのただ一つの関数を持つ:

    struct action_policy
    {
        template <typename ActorT, typename AttrT, typename IteratorT>
        void
        do_action(
            ActorT const&       actor,
            AttrT const&        val,
            IteratorT const&    first,
            IteratorT const&    last) const;
    };

デフォルトのアクションポリシーは、もし val 属性の型が nil_t ならば、以下に送られる:

    actor(first, last);

さもなくば以下のようになる:

    actor(val);

scanner_policies mixer

scanner_policies クラスは上述の三つのスキャナポリシークラスを一つに連結する:

    template <
        typename IterationPolicyT   = iteration_policy,
        typename MatchPolicyT       = match_policy,
        typename ActionPolicyT      = action_policy>
    struct scanner_policies;

この mixer クラスは三つのポリシー全てを継承する。 その後、この scanner_policies クラスはスキャナをパラメータ化するために用いられる:

    template <
        typename IteratorT = char const*,
        typename PoliciesT = scanner_policies<> >
    class scanner;

次にスキャナが PoliciesT を継承する。

ポリシーの再束縛

スキャナは異なるポリシーの組にいつでも再束縛されることができる。 スキャナはメンバ関数 change_policies(new_policies) を持つ。 新しいポリシーの組を与えると、このメンバ関数はその新しいポリシーの組を持った新しいスキャナを作成する。 再束縛されたスキャナの結果の型は次のメタ関数を呼ぶことによって取得できる:

    rebind_scanner_policies<ScannerT, PoliciesT>::type

イテレータの再束縛

スキャナは異なるイテレータ型にいつでも再束縛されることができる。 スキャナはメンバ関数 change_iterator(first, last) を持つ。 スキャナの保持するものと異なる型のイテレータの組を与えると、このメンバ関数はその新しいイテレータの組を持った新しいスキャナを作成する。 再束縛されたスキャナの結果の型は次のメタ関数を呼ぶことによって取得できる:

    rebind_scanner_iterator<ScannerT, IteratorT>::type


このドキュメントの対象: Boost Version 1.30.0
最新版ドキュメント(英語)