1/*=============================================================================
2    Copyright (c) 2002-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_LISTS_IPP
10#define BOOST_SPIRIT_LISTS_IPP
11
12///////////////////////////////////////////////////////////////////////////////
13#include <boost/spirit/home/classic/meta/refactoring.hpp>
14
15///////////////////////////////////////////////////////////////////////////////
16namespace boost { namespace spirit {
17
18BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
19
20///////////////////////////////////////////////////////////////////////////////
21//
22//  list_parser_type class implementation
23//
24///////////////////////////////////////////////////////////////////////////////
25struct no_list_endtoken { typedef no_list_endtoken embed_t; };
26
27namespace impl {
28
29///////////////////////////////////////////////////////////////////////////////
30//
31//  Refactor the original list item parser
32//
33///////////////////////////////////////////////////////////////////////////////
34
35    //  match list with 'extended' syntax
36    template <typename EndT>
37    struct select_list_parse_refactor {
38
39        template <
40            typename ParserT, typename ScannerT,
41            typename ItemT, typename DelimT
42        >
43        static typename parser_result<ParserT, ScannerT>::type
44        parse(ScannerT const& scan, ParserT const& /*p*/,
45            ItemT const &item, DelimT const &delim, EndT const &end)
46        {
47            typedef refactor_action_gen<refactor_unary_gen<> > refactor_t;
48            const refactor_t refactor_item_d = refactor_t(refactor_unary_d);
49
50            return (
51                    refactor_item_d[item - (end | delim)]
52                >> *(delim >> refactor_item_d[item - (end | delim)])
53                >> !(delim >> end)
54            ).parse(scan);
55        }
56    };
57
58    //  match list with 'normal' syntax (without an 'end' parser)
59    template <>
60    struct select_list_parse_refactor<no_list_endtoken> {
61
62        template <
63            typename ParserT, typename ScannerT,
64            typename ItemT, typename DelimT
65        >
66        static typename parser_result<ParserT, ScannerT>::type
67        parse(ScannerT const& scan, ParserT const& /*p*/,
68            ItemT const &item, DelimT const &delim, no_list_endtoken const&)
69        {
70            typedef refactor_action_gen<refactor_unary_gen<> > refactor_t;
71            const refactor_t refactor_item_d = refactor_t(refactor_unary_d);
72
73            return (
74                    refactor_item_d[item - delim]
75                >> *(delim >> refactor_item_d[item - delim])
76            ).parse(scan);
77        }
78    };
79
80///////////////////////////////////////////////////////////////////////////////
81//
82//  Do not refactor the original list item parser.
83//
84///////////////////////////////////////////////////////////////////////////////
85
86    //  match list with 'extended' syntax
87    template <typename EndT>
88    struct select_list_parse_no_refactor {
89
90        template <
91            typename ParserT, typename ScannerT,
92            typename ItemT, typename DelimT
93        >
94        static typename parser_result<ParserT, ScannerT>::type
95        parse(ScannerT const& scan, ParserT const& /*p*/,
96            ItemT const &item, DelimT const &delim, EndT const &end)
97        {
98            return (
99                    (item - (end | delim))
100                >> *(delim >> (item - (end | delim)))
101                >> !(delim >> end)
102            ).parse(scan);
103        }
104    };
105
106    //  match list with 'normal' syntax (without an 'end' parser)
107    template <>
108    struct select_list_parse_no_refactor<no_list_endtoken> {
109
110        template <
111            typename ParserT, typename ScannerT,
112            typename ItemT, typename DelimT
113        >
114        static typename parser_result<ParserT, ScannerT>::type
115        parse(ScannerT const& scan, ParserT const& /*p*/,
116            ItemT const &item, DelimT const &delim, no_list_endtoken const&)
117        {
118            return (
119                    (item - delim)
120                >> *(delim >> (item - delim))
121            ).parse(scan);
122        }
123    };
124
125    // the refactoring is handled by the refactoring parsers, so here there
126    // is no need to pay attention to these issues.
127
128    template <typename CategoryT>
129    struct list_parser_type {
130
131        template <
132            typename ParserT, typename ScannerT,
133            typename ItemT, typename DelimT, typename EndT
134        >
135        static typename parser_result<ParserT, ScannerT>::type
136        parse(ScannerT const& scan, ParserT const& p,
137              ItemT const &item, DelimT const &delim, EndT const &end)
138        {
139            return select_list_parse_refactor<EndT>::
140                parse(scan, p, item, delim, end);
141        }
142    };
143
144    template <>
145    struct list_parser_type<plain_parser_category> {
146
147        template <
148            typename ParserT, typename ScannerT,
149            typename ItemT, typename DelimT, typename EndT
150        >
151        static typename parser_result<ParserT, ScannerT>::type
152        parse(ScannerT const& scan, ParserT const& p,
153              ItemT const &item, DelimT const &delim, EndT const &end)
154        {
155            return select_list_parse_no_refactor<EndT>::
156                parse(scan, p, item, delim, end);
157        }
158    };
159
160}   // namespace impl
161
162///////////////////////////////////////////////////////////////////////////////
163BOOST_SPIRIT_CLASSIC_NAMESPACE_END
164
165}} // namespace boost::spirit
166
167#endif
168
169