1 /*=============================================================================
2     Copyright (c) 2001-2003 Daniel Nuffer
3     http://spirit.sourceforge.net/
4 
5   Distributed under the Boost Software License, Version 1.0. (See accompanying
6   file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #ifndef BOOST_SPIRIT_ESCAPE_CHAR_HPP
9 #define BOOST_SPIRIT_ESCAPE_CHAR_HPP
10 
11 ///////////////////////////////////////////////////////////////////////////////
12 #include <string>
13 #include <iterator>
14 #include <cctype>
15 #include <boost/limits.hpp>
16 
17 #include <boost/spirit/home/classic/namespace.hpp>
18 #include <boost/spirit/home/classic/debug.hpp>
19 
20 #include <boost/spirit/home/classic/utility/escape_char_fwd.hpp>
21 #include <boost/spirit/home/classic/utility/impl/escape_char.ipp>
22 
23 ///////////////////////////////////////////////////////////////////////////////
24 namespace boost { namespace spirit {
25 
26 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
27 
28 ///////////////////////////////////////////////////////////////////////////////
29 //
30 //  escape_char_action class
31 //
32 //      Links an escape char parser with a user defined semantic action.
33 //      The semantic action may be a function or a functor. A function
34 //      should be compatible with the interface:
35 //
36 //          void f(CharT ch);
37 //
38 //      A functor should have a member operator() with a compatible signature
39 //      as above. The matching character is passed into the function/functor.
40 //      This is the default class that character parsers use when dealing with
41 //      the construct:
42 //
43 //          p[f]
44 //
45 //      where p is a parser and f is a function or functor.
46 //
47 ///////////////////////////////////////////////////////////////////////////////
48 template <
49     typename ParserT, typename ActionT,
50     unsigned long Flags, typename CharT
51 >
52 struct escape_char_action
53 :   public unary<ParserT,
54         parser<escape_char_action<ParserT, ActionT, Flags, CharT> > >
55 {
56     typedef escape_char_action
57         <ParserT, ActionT, Flags, CharT>        self_t;
58     typedef action_parser_category              parser_category_t;
59     typedef unary<ParserT, parser<self_t> >     base_t;
60 
61     template <typename ScannerT>
62     struct result
63     {
64         typedef typename match_result<ScannerT, CharT>::type type;
65     };
66 
escape_char_actionboost::spirit::escape_char_action67     escape_char_action(ParserT const& p, ActionT const& a)
68     : base_t(p), actor(a) {}
69 
70     template <typename ScannerT>
71     typename parser_result<self_t, ScannerT>::type
parseboost::spirit::escape_char_action72     parse(ScannerT const& scan) const
73     {
74         return impl::escape_char_action_parse<Flags, CharT>::
75             parse(scan, *this);
76     }
77 
predicateboost::spirit::escape_char_action78     ActionT const& predicate() const { return actor; }
79 
80 private:
81 
82     ActionT actor;
83 };
84 
85 ///////////////////////////////////////////////////////////////////////////////
86 //
87 //  escape_char_parser class
88 //
89 //      The escape_char_parser helps in conjunction with the escape_char_action
90 //      template class (see above) in parsing escaped characters. There are two
91 //      different variants of this parser: one for parsing C style escaped
92 //      characters and one for parsing LEX style escaped characters.
93 //
94 //      The C style escaped character parser is generated, when the template
95 //      parameter 'Flags' is equal to 'c_escapes' (a constant defined in the
96 //      file impl/escape_char.ipp). This parser recognizes all valid C escape
97 //      character sequences: '\t', '\b', '\f', '\n', '\r', '\"', '\'', '\\'
98 //      and the numeric style escapes '\120' (octal) and '\x2f' (hexadecimal)
99 //      and converts these to their character equivalent, for instance the
100 //      sequence of a backslash and a 'b' is parsed as the character '\b'.
101 //      All other escaped characters are rejected by this parser.
102 //
103 //      The LEX style escaped character parser is generated, when the template
104 //      parameter 'Flags' is equal to 'lex_escapes' (a constant defined in the
105 //      file impl/escape_char.ipp). This parser recognizes all the C style
106 //      escaped character sequences (as described above) and additionally
107 //      does not reject all other escape sequences. All not mentioned escape
108 //      sequences are converted by the parser to the plain character, for
109 //      instance '\a' will be parsed as 'a'.
110 //
111 //      All not escaped characters are parsed without modification.
112 //
113 ///////////////////////////////////////////////////////////////////////////////
114 
115 template <unsigned long Flags, typename CharT>
116 struct escape_char_action_parser_gen;
117 
118 template <unsigned long Flags, typename CharT>
119 struct escape_char_parser :
120     public parser<escape_char_parser<Flags, CharT> > {
121 
122     // only the values c_escapes and lex_escapes are valid for Flags
123     BOOST_STATIC_ASSERT(Flags == c_escapes || Flags == lex_escapes);
124 
125     typedef escape_char_parser<Flags, CharT> self_t;
126     typedef
127         escape_char_action_parser_gen<Flags, CharT>
128         action_parser_generator_t;
129 
130     template <typename ScannerT>
131     struct result {
132 
133         typedef typename match_result<ScannerT, CharT>::type type;
134     };
135 
136     template <typename ActionT>
137     escape_char_action<self_t, ActionT, Flags, CharT>
operator []boost::spirit::escape_char_parser138     operator[](ActionT const& actor) const
139     {
140         return escape_char_action<self_t, ActionT, Flags, CharT>(*this, actor);
141     }
142 
143     template <typename ScannerT>
144     typename parser_result<self_t, ScannerT>::type
parseboost::spirit::escape_char_parser145     parse(ScannerT const &scan) const
146     {
147         return impl::escape_char_parse<CharT>::parse(scan, *this);
148     }
149 };
150 
151 template <unsigned long Flags, typename CharT>
152 struct escape_char_action_parser_gen {
153 
154     template <typename ParserT, typename ActionT>
155     static escape_char_action<ParserT, ActionT, Flags, CharT>
generateboost::spirit::escape_char_action_parser_gen156     generate (ParserT const &p, ActionT const &actor)
157     {
158         typedef
159             escape_char_action<ParserT, ActionT, Flags, CharT>
160             action_parser_t;
161         return action_parser_t(p, actor);
162     }
163 };
164 
165 ///////////////////////////////////////////////////////////////////////////////
166 //
167 //  predefined escape_char_parser objects
168 //
169 //      These objects should be used for generating correct escaped character
170 //      parsers.
171 //
172 ///////////////////////////////////////////////////////////////////////////////
173 const escape_char_parser<lex_escapes> lex_escape_ch_p =
174     escape_char_parser<lex_escapes>();
175 
176 const escape_char_parser<c_escapes> c_escape_ch_p =
177     escape_char_parser<c_escapes>();
178 
179 ///////////////////////////////////////////////////////////////////////////////
180 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
181 
182 }} // namespace BOOST_SPIRIT_CLASSIC_NS
183 
184 #endif
185