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 */
31 #include <boost/regex.hpp>
32 #include <boost/spirit.hpp>
33 #include <boost/spirit/utility/grammar_def.hpp>
34 #include <boost/spirit/actor.hpp>
35 #include <boost/bind.hpp>
36 #include <boost/function.hpp>
37 #include <boost/ref.hpp>
39 ///////////////////////////////ih.p////////////////////////////////////////
47 template <class T, class Value>
48 void act(T & ref, Value const & value) const
49 { ref += T(1, value); }
51 template <class T, class Iterator>
52 void act(T & ref, Iterator const & f, Iterator const & l) const
57 inline boost::spirit::ref_value_actor<T, append_action>
60 return boost::spirit::ref_value_actor<T, append_action>(ref);
63 template <class T, class Value>
64 inline boost::spirit::ref_const_ref_actor<T, Value, append_action>
65 append_a(T & ref, Value const & value)
67 return boost::spirit::ref_const_ref_actor<T, Value, append_action>(ref, value);
70 template <class ParseDispatcher>
71 struct CommandGrammar : boost::spirit::grammar<CommandGrammar<ParseDispatcher> >
73 ///////////////////////////////////////////////////////////////////////////
76 enum { CommandParser, SkipParser };
78 ///////////////////////////////////////////////////////////////////////////
79 // The parse context (variables needed while parsing)
83 std::vector<std::string> path;
89 ///////////////////////////////////////////////////////////////////////////
90 // Dispatching semantic actions
92 ParseDispatcher & dispatcher;
96 Dispatch_actor(boost::function<void ()> fn_) : fn (fn_) {}
98 template <class Value>
99 void operator()(Value const & value) const
102 template <class Iterator>
103 void operator()(Iterator const & f, Iterator const & l) const
106 boost::function<void ()> fn;
109 template <class Callback>
110 Dispatch_actor dispatch(Callback cb) const
111 { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher))); }
113 template <class Callback, class Arg>
114 Dispatch_actor dispatch(Callback cb, Arg const & arg) const
115 { return Dispatch_actor(boost::bind(cb, boost::ref(dispatcher), arg)); }
117 ///////////////////////////////////////////////////////////////////////////
119 CommandGrammar(ParseDispatcher & d, Context & c)
120 : context(c), dispatcher(d) {}
122 template <class Scanner>
124 : public boost::spirit::grammar_def< boost::spirit::rule<Scanner>,
125 boost::spirit::rule<Scanner> >
127 boost::spirit::rule<Scanner> command, path, argument, word, string, hexstring, token;
128 boost::spirit::rule<Scanner> punctuation, hexbyte, balanced_tokens, simple_argument;
129 boost::spirit::rule<Scanner> complex_argument, builtin, skip;
131 boost::spirit::chset<> special_p, punctuation_p, space_p, invalid_p, word_p;
133 boost::spirit::distinct_parser<> keyword_p;
135 definition(CommandGrammar const & self) :
137 // Characters with a special meaning within the parser
138 // and characters reserved for future extensions
139 special_p ("/(){};"),
141 // Characters which are returned as punctuation tokens
142 punctuation_p (",="),
144 // Whitespace characters (we don't want newlines in there)
147 // Invalid characters: All chars below \x20 (space) which are not space_p
148 // (don't put a \0 in the chset<> argument *string* ...)
150 boost::spirit::chset<>('\0') | boost::spirit::chset<>("\x01-\x20") - space_p ),
152 // Valid word characters
154 boost::spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p),
156 // Keywords must not be followed by a word char or '/'
157 keyword_p ( word_p | boost::spirit::ch_p('/') )
160 using namespace boost::spirit;
161 typedef ParseDispatcher PD;
166 >> eps_p [ self.dispatch(&PD::builtin_cd,
167 boost::ref(self.context.path)) ]
170 >> eps_p [ self.dispatch(&PD::builtin_cd,
171 boost::ref(self.context.path)) ]
176 | path [ self.dispatch(&PD::beginCommand,
177 boost::ref(self.context.path)) ]
180 >> eps_p [ self.dispatch(&PD::endCommand) ]
184 = simple_argument [ self.dispatch(&PD::pushArgument,
185 boost::ref(self.context.str)) ]
189 simple_argument // All these return their value in context.str
195 complex_argument // Argument consists of multiple tokens
196 = ch_p('(') [ self.dispatch(&PD::openGroup) ]
198 >> ch_p(')') [ self.dispatch(&PD::closeGroup) ]
201 string // Returns value in context.str
202 = eps_p [ clear_a(self.context.str) ]
206 >> * ( ( lex_escape_ch_p[ assign_a(self.context.ch) ]
208 ) [ append_a(self.context.str,
215 hexstring // Returns value in context.str
216 = eps_p [ clear_a(self.context.str) ]
217 >> confix_p( "x\"", * hexbyte, '"' )
220 path // Returns value in context.path
221 = eps_p [ clear_a(self.context.path) ]
222 >> ( ! ch_p('/') [ push_back_a(self.context.path, "") ] )
223 >> ( word [ push_back_a(self.context.path) ]
225 >> ( ! ch_p('/') [ push_back_a(self.context.path,"") ] )
229 = ch_p('(') [ self.dispatch(&PD::pushPunctuation, "(") ]
231 >> ch_p(')') [ self.dispatch(&PD::pushPunctuation, ")") ]
235 = simple_argument [ self.dispatch(&PD::pushWord,
236 boost::ref(self.context.str)) ]
237 | punctuation [ self.dispatch(&PD::pushPunctuation,
238 boost::ref(self.context.str)) ]
242 punctuation // Returns value in context.str
243 = punctuation_p [ assign_a(self.context.str) ]
246 word // Returns value in context.str
247 = lexeme_d[ + word_p ] [ assign_a(self.context.str) ]
251 = uint_parser<char, 16, 2, 2>()
252 [ append_a(self.context.str) ]
260 BOOST_SPIRIT_DEBUG_TRACE_RULE(command,1);
261 BOOST_SPIRIT_DEBUG_TRACE_RULE(path,1);
262 BOOST_SPIRIT_DEBUG_TRACE_RULE(argument,1);
263 BOOST_SPIRIT_DEBUG_TRACE_RULE(word,1);
264 BOOST_SPIRIT_DEBUG_TRACE_RULE(string,1);
265 BOOST_SPIRIT_DEBUG_TRACE_RULE(hexstring,1);
266 BOOST_SPIRIT_DEBUG_TRACE_RULE(token,1);
267 BOOST_SPIRIT_DEBUG_TRACE_RULE(punctuation,1);
268 BOOST_SPIRIT_DEBUG_TRACE_RULE(hexbyte,1);
269 BOOST_SPIRIT_DEBUG_TRACE_RULE(balanced_tokens,1);
270 BOOST_SPIRIT_DEBUG_TRACE_RULE(simple_argument,1);
271 BOOST_SPIRIT_DEBUG_TRACE_RULE(complex_argument,1);
272 BOOST_SPIRIT_DEBUG_TRACE_RULE(builtin,1);
275 command, // CommandParser
285 ///////////////////////////////ih.e////////////////////////////////////////
292 // comment-column: 40
293 // c-file-style: "senf"
294 // indent-tabs-mode: nil
295 // ispell-local-dictionary: "american"
296 // compile-command: "scons -u test"