1/*=============================================================================
2    Copyright (c) 1998-2003 Joel de Guzman
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#if !defined(BOOST_SPIRIT_SKIPPER_IPP)
10#define BOOST_SPIRIT_SKIPPER_IPP
11
12///////////////////////////////////////////////////////////////////////////////
13namespace boost { namespace spirit {
14
15BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
16
17    struct space_parser;
18    template <typename BaseT>
19    struct no_skipper_iteration_policy;
20
21    namespace impl
22    {
23        template <typename ST, typename ScannerT, typename BaseT>
24        inline void
25        skipper_skip(
26            ST const& s,
27            ScannerT const& scan,
28            skipper_iteration_policy<BaseT> const&)
29        {
30            typedef scanner_policies<
31                no_skipper_iteration_policy<
32                    BOOST_DEDUCED_TYPENAME ScannerT::iteration_policy_t>,
33                BOOST_DEDUCED_TYPENAME ScannerT::match_policy_t,
34                BOOST_DEDUCED_TYPENAME ScannerT::action_policy_t
35            > policies_t;
36
37            scanner<BOOST_DEDUCED_TYPENAME ScannerT::iterator_t, policies_t>
38                scan2(scan.first, scan.last, policies_t(scan));
39            typedef typename ScannerT::iterator_t iterator_t;
40
41            for (;;)
42            {
43                iterator_t save = scan.first;
44                if (!s.parse(scan2))
45                {
46                    scan.first = save;
47                    break;
48                }
49            }
50        }
51
52        template <typename ST, typename ScannerT, typename BaseT>
53        inline void
54        skipper_skip(
55            ST const& s,
56            ScannerT const& scan,
57            no_skipper_iteration_policy<BaseT> const&)
58        {
59            for (;;)
60            {
61                typedef typename ScannerT::iterator_t iterator_t;
62                iterator_t save = scan.first;
63                if (!s.parse(scan))
64                {
65                    scan.first = save;
66                    break;
67                }
68            }
69        }
70
71        template <typename ST, typename ScannerT>
72        inline void
73        skipper_skip(
74            ST const& s,
75            ScannerT const& scan,
76            iteration_policy const&)
77        {
78            for (;;)
79            {
80                typedef typename ScannerT::iterator_t iterator_t;
81                iterator_t save = scan.first;
82                if (!s.parse(scan))
83                {
84                    scan.first = save;
85                    break;
86                }
87            }
88        }
89
90        template <typename SkipT>
91        struct phrase_parser
92        {
93            template <typename IteratorT, typename ParserT>
94            static parse_info<IteratorT>
95            parse(
96                IteratorT const&    first_,
97                IteratorT const&    last,
98                ParserT const&      p,
99                SkipT const&        skip)
100            {
101                typedef skip_parser_iteration_policy<SkipT> it_policy_t;
102                typedef scanner_policies<it_policy_t> scan_policies_t;
103                typedef scanner<IteratorT, scan_policies_t> scanner_t;
104
105                it_policy_t iter_policy(skip);
106                scan_policies_t policies(iter_policy);
107                IteratorT first = first_;
108                scanner_t scan(first, last, policies);
109                match<nil_t> hit = p.parse(scan);
110                return parse_info<IteratorT>(
111                    first, hit, hit && (first == last),
112                    hit.length());
113            }
114        };
115
116        template <>
117        struct phrase_parser<space_parser>
118        {
119            template <typename IteratorT, typename ParserT>
120            static parse_info<IteratorT>
121            parse(
122                IteratorT const&    first_,
123                IteratorT const&    last,
124                ParserT const&      p,
125                space_parser const&)
126            {
127                typedef skipper_iteration_policy<> it_policy_t;
128                typedef scanner_policies<it_policy_t> scan_policies_t;
129                typedef scanner<IteratorT, scan_policies_t> scanner_t;
130
131                IteratorT first = first_;
132                scanner_t scan(first, last);
133                match<nil_t> hit = p.parse(scan);
134                return parse_info<IteratorT>(
135                    first, hit, hit && (first == last),
136                    hit.length());
137            }
138        };
139    }
140
141    ///////////////////////////////////////////////////////////////////////////
142    //
143    //  Free parse functions using the skippers
144    //
145    ///////////////////////////////////////////////////////////////////////////
146    template <typename IteratorT, typename ParserT, typename SkipT>
147    inline parse_info<IteratorT>
148    parse(
149        IteratorT const&        first,
150        IteratorT const&        last,
151        parser<ParserT> const&  p,
152        parser<SkipT> const&    skip)
153    {
154        return impl::phrase_parser<SkipT>::
155            parse(first, last, p.derived(), skip.derived());
156    }
157
158    ///////////////////////////////////////////////////////////////////////////
159    //
160    //  Parse function for null terminated strings using the skippers
161    //
162    ///////////////////////////////////////////////////////////////////////////
163    template <typename CharT, typename ParserT, typename SkipT>
164    inline parse_info<CharT const*>
165    parse(
166        CharT const*            str,
167        parser<ParserT> const&  p,
168        parser<SkipT> const&    skip)
169    {
170        CharT const* last = str;
171        while (*last)
172            last++;
173        return parse(str, last, p, skip);
174    }
175
176BOOST_SPIRIT_CLASSIC_NAMESPACE_END
177
178}} // namespace boost::spirit
179
180#endif
181
182