4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Parse internal header */
30 #include <boost/regex.hpp>
31 #include <boost/spirit.hpp>
32 #include <boost/spirit/utility/regex.hpp>
33 #include <boost/spirit/actor.hpp>
34 #include <boost/bind.hpp>
35 #include <boost/function.hpp>
36 #include <boost/ref.hpp>
38 ///////////////////////////////ih.p////////////////////////////////////////
46 template <class T, class Value>
47 void act(T & ref, Value const & value) const
48 { ref += T(1, value); }
50 template <class T, class Iterator>
51 void act(T & ref, Iterator const & f, Iterator const & l) const
56 inline boost::spirit::ref_value_actor<T, append_action>
59 return boost::spirit::ref_value_actor<T, append_action>(ref);
62 template <class T, class Value>
63 inline boost::spirit::ref_const_ref_actor<T, Value, append_action>
64 append_a(T & ref, Value const & value)
66 return boost::spirit::ref_const_ref_actor<T, Value, append_action>(ref, value);
69 template <class ParseDispatcher>
70 struct CommandGrammar : boost::spirit::grammar<CommandGrammar<ParseDispatcher> >
72 ///////////////////////////////////////////////////////////////////////////
73 // The parse context (variables needed while parsing)
82 ///////////////////////////////////////////////////////////////////////////
83 // Dispatching semantic actions
85 ParseDispatcher & dispatcher;
89 Dispatch_actor(boost::function<void ()> fn_) : fn (fn_) {}
91 template <class Value>
92 void operator()(Value const & value) const
95 template <class Iterator>
96 void operator()(Iterator const & f, Iterator const & l) const
99 boost::function<void ()> fn;
102 template <class Callback>
103 Dispatch_actor dispatch(Callback cb) const
104 { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher))); }
106 template <class Callback, class Arg>
107 Dispatch_actor dispatch(Callback cb, Arg const & arg) const
108 { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg)); }
110 ///////////////////////////////////////////////////////////////////////////
112 CommandGrammar(ParseDispatcher & d, Context & c)
113 : context(c), dispatcher(d) {}
115 template <class Scanner>
118 boost::spirit::rule<Scanner> command, path, argument, word, string, hexstring, token;
119 boost::spirit::rule<Scanner> punctuation, hexbyte, balanced_tokens, simple_argument;
120 boost::spirit::rule<Scanner> complex_argument;
122 definition(CommandGrammar const & self) {
123 using namespace boost::spirit;
124 typedef ParseDispatcher PD;
127 = path [ self.dispatch(&PD::beginCommand,
128 boost::cref(self.context.str)) ]
131 >> eps_p [ self.dispatch(&PD::endCommand) ]
135 = simple_argument [ self.dispatch(&PD::pushArgument,
136 boost::cref(self.context.str)) ]
140 simple_argument // All these return their value in context.str
146 complex_argument // Argument consists of multiple tokens
147 = ch_p('(') [ self.dispatch(&PD::openGroup) ]
149 >> ch_p(')') [ self.dispatch(&PD::closeGroup) ]
152 string // Returns value in context.str
153 = eps_p [ clear_a(self.context.str) ]
157 >> * ( ( lex_escape_ch_p[ assign_a(self.context.ch) ]
159 ) [ append_a(self.context.str,
166 hexstring // Returns value in context.str
167 = eps_p [ clear_a(self.context.str) ]
168 >> confix_p( "x\"", * hexbyte, '"' )
171 path // Returns value in context.str
172 = eps_p [ clear_a(self.context.str) ]
173 >> ( ! ch_p('/') [ append_a(self.context.str) ]
175 >> ( word [ append_a(self.context.str) ]
176 % ch_p('/') [ append_a(self.context.str) ]
181 = ch_p('(') [ self.dispatch(&PD::pushPunctuation, "(") ]
183 >> ch_p(')') [ self.dispatch(&PD::pushPunctuation, ")") ]
187 = simple_argument [ self.dispatch(&PD::pushWord,
188 boost::cref(self.context.str)) ]
189 | punctuation [ self.dispatch(&PD::pushPunctuation,
190 boost::cref(self.context.str)) ]
194 punctuation // Returns value in context.str
195 = regex_p("[,=]") [ assign_a(self.context.str) ]
199 = regex_p("[^ \t\n\r;,=(){}/\"]+")
203 = uint_parser<char, 16, 2, 2>()
204 [ append_a(self.context.str) ]
207 BOOST_SPIRIT_DEBUG_RULE(command);
208 BOOST_SPIRIT_DEBUG_RULE(path);
209 BOOST_SPIRIT_DEBUG_RULE(argument);
210 BOOST_SPIRIT_DEBUG_RULE(word);
211 BOOST_SPIRIT_DEBUG_RULE(string);
212 BOOST_SPIRIT_DEBUG_RULE(hexstring);
213 BOOST_SPIRIT_DEBUG_RULE(token);
214 BOOST_SPIRIT_DEBUG_RULE(punctuation);
215 BOOST_SPIRIT_DEBUG_RULE(hexbyte);
216 BOOST_SPIRIT_DEBUG_RULE(balanced_tokens);
217 BOOST_SPIRIT_DEBUG_RULE(simple_argument);
218 BOOST_SPIRIT_DEBUG_RULE(complex_argument);
221 boost::spirit::rule<Scanner> const & start() const { return command; }
226 : public boost::spirit::grammar<SkipGrammar>
228 template <class Scanner>
231 boost::spirit::rule<Scanner> rule;
233 definition(SkipGrammar const & self) {
235 = boost::spirit::regex_p("[ \t]+")
236 | boost::spirit::comment_p('#')
240 boost::spirit::rule<Scanner> const & start() const { return rule; }
246 ///////////////////////////////ih.e////////////////////////////////////////
253 // comment-column: 40
254 // c-file-style: "senf"
255 // indent-tabs-mode: nil
256 // ispell-local-dictionary: "american"
257 // compile-command: "scons -u test"