1/*=============================================================================
2    Copyright (c) 2003 Hartmut Kaiser
3    http://spirit.sourceforge.net/
4
5    Use, modification and distribution is subject to the Boost Software
6    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7    http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#ifndef BOOST_SPIRIT_SELECT_IPP
10#define BOOST_SPIRIT_SELECT_IPP
11
12#include <boost/spirit/home/classic/core/parser.hpp>
13#include <boost/spirit/home/classic/core/composite/composite.hpp>
14#include <boost/spirit/home/classic/meta/as_parser.hpp>
15
16///////////////////////////////////////////////////////////////////////////////
17namespace boost { namespace spirit {
18
19BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
20
21///////////////////////////////////////////////////////////////////////////////
22namespace impl {
23
24///////////////////////////////////////////////////////////////////////////////
25template <typename ParserT>
26struct as_embedded_parser : public as_parser<ParserT>
27{
28    typedef typename as_parser<ParserT>::type::derived_t::embed_t type;
29};
30
31///////////////////////////////////////////////////////////////////////////////
32
33// no implementation here to catch unknown BehaviourT template arguments
34template <typename ResultT, typename BehaviourT>
35struct select_match_gen;
36
37// implementation for the select_default_no_fail behaviour
38template <typename ResultT>
39struct select_match_gen<ResultT, select_default_no_fail> {
40
41    template <typename ScannerT>
42    static ResultT
43    do_ (ScannerT const &scan)
44    {
45        return scan.create_match(0, -1, scan.first, scan.first);
46    }
47};
48
49// implementation for the select_default_fail behaviour
50template <typename ResultT>
51struct select_match_gen<ResultT, select_default_fail> {
52
53    template <typename ScannerT>
54    static ResultT
55    do_ (ScannerT const &scan)
56    {
57        return scan.no_match();
58    }
59};
60
61///////////////////////////////////////////////////////////////////////////////
62template <int N, typename ResultT, typename TupleT, typename BehaviourT>
63struct parse_tuple_element {
64
65    BOOST_STATIC_CONSTANT(int, index = (TupleT::length - N));
66
67    template <typename ScannerT>
68    static ResultT
69    do_(TupleT const &t, ScannerT const &scan)
70    {
71        typedef typename ::phoenix::tuple_element<index, TupleT>::type parser_t;
72        typedef typename ScannerT::iterator_t                       iterator_t;
73        typedef typename parser_result<parser_t, ScannerT>::type    result_t;
74
75    iterator_t save(scan.first);
76    result_t result(t[::phoenix::tuple_index<index>()].parse(scan));
77
78        if (result) {
79            return scan.create_match(result.length(), TupleT::length - N,
80                save, scan.first);
81        }
82        scan.first = save;    // reset the input stream
83        return parse_tuple_element<N-1, ResultT, TupleT, BehaviourT>::
84            do_(t, scan);
85    }
86};
87
88template <typename ResultT, typename TupleT, typename BehaviourT>
89struct parse_tuple_element<1, ResultT, TupleT, BehaviourT> {
90
91    BOOST_STATIC_CONSTANT(int, index = (TupleT::length - 1));
92
93    template <typename ScannerT>
94    static ResultT
95    do_(TupleT const &t, ScannerT const &scan)
96    {
97        typedef typename ::phoenix::tuple_element<index, TupleT>::type  parser_t;
98        typedef typename ScannerT::iterator_t                       iterator_t;
99        typedef typename parser_result<parser_t, ScannerT>::type    result_t;
100
101    iterator_t save(scan.first);
102    result_t result(t[::phoenix::tuple_index<index>()].parse(scan));
103
104        if (result) {
105            return scan.create_match(result.length(), TupleT::length - 1,
106                save, scan.first);
107        }
108        scan.first = save;    // reset the input stream
109        return select_match_gen<ResultT, BehaviourT>::do_(scan);
110    }
111};
112
113///////////////////////////////////////////////////////////////////////////////
114}   // namespace impl
115
116BOOST_SPIRIT_CLASSIC_NAMESPACE_END
117
118}}  // namespace boost::spirit
119
120#endif  // BOOST_SPIRIT_SELECT_IPP
121