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 public header */
29 /** \defgroup console_parser The parser
31 The console/config library defines a simple language used to interact with the console or to
32 configure the application. The parser is not concerned about interpreting commands or
33 arguments, checking that a command exists or managing directories. The parser just takes the
38 \section console_language The Language
40 The config/console language is used in configuration files and interactively at the
41 console. Some features of the language are more useful in config files, others at the
42 interactive console but the language is the same in both cases.
44 Let's start with a sample of the config/console language. The following is written as a
47 # My someserver configuration file
53 accept senf::log::Debug IMPORTANT;
54 accept server::ServerLog CRITICAL;
57 provide serverlog senf::log::FileTarget "/var/log/server.log";
59 reject senf::log::Debug senf::Console::Server NOTICE;
60 accept senf::log::Debug NOTICE;
61 accept server::ServerLog;
65 /server/stuffing (UDPPacket x"01 02 03 04");
66 /server/allow_hosts 10.1.2.3 # our internal server
67 10.2.3.4 10.4.3.5 # client workstations
70 /help/infoUrl "http://senf.j32.de/src/doc";
73 The interactive syntax is the same with some notes:
74 \li All commands must be complete on a single line. This includes grouping constructs which must
75 be closed on the same line they are opened.
76 \li The last ';' is optional. However, multiple commands may be entered on a single line when
77 they are separated by ';'.
78 \li An empty line on the interactive console will repeat the last command.
80 The language consists of a small number of syntactic entities:
82 \subsection console_special_chars Special characters
84 These are characters, which have a special meaning. Some are used internally, others are just
85 returned as punctuation tokens
88 <tr><td>/</td><td>path component separator</td></tr>
89 <tr><td>( )</td><td>argument grouping</td></tr>
90 <tr><td>{ }</td><td>directory grouping</td></tr>
91 <tr><td>;</td><td>command terminator</td></tr>
92 <tr><td>, =</td><td>punctuation tokens</td></tr>
95 \subsection console_basic Basic elements
97 A <b>word</b> is \e any sequence of consecutive characters which does not include any special
98 character. Examples for words are thus
101 jens@fokus.fraunhofer.de
106 The following are \e not valid words:
112 A <b>string literal</b> is just that: A double-quoted string (C/C++ style) possibly with
113 embedded escape chars:
119 A <b>hex-string literal</b> is used to represent binary data. It looks like a string which has
120 only hexadecimal bytes or whitespace as contents (comments and newlines are Ok when not read
121 from the interactive console)
129 A <b>token</b> is a \e word, \e string or \e hex-string, or a single special character (that's
130 true, any special character is allowed as a token). '(' and ')' must be properly nested.
132 A <b>path</b> is a sequence of \e words separated by '/' (and optional whitespace). A path may
133 have an optional initial and/or a terminating '/'.
140 \subsection console_statements Statements
142 There are several types of statements:
143 \li The bulk of all statements are \e path statements
144 \li There are some \e built-in statements which are mostly useful at the interactive console
145 \li A special form of statement is the <em>directory group</em>
147 A <b>path</b> statement consists of a (possibly relative) path followed by any number of
148 arguments and terminated with a ';' (or end-of-input)
150 /path/to/command arg1 "arg2" (complex=(1 2) another) ;
152 Every argument is either
153 \li A single word, string or hex-string
154 \li or a parenthesized list of tokens.
156 So above command has three arguments: 'arg1', 'arg2' (a single token each) and one argument with
157 the 7 tokens 'complex', '=', '(', '1', '2', ')', 'another'. The interpretation of the arguments
158 is completely up to the command.
160 A <b>built-in</b> statement is one of
163 <tr><td>\c cd \e path</td><td>Change current directory</td></tr>
164 <tr><td>\c ls [ \e path ]</td><td>List contents of \e path or current directory</td></tr>
165 <tr><td>\c exit</td><td>Exit interactive console</td></tr>
166 <tr><td>\c help [ \e path ]</td><td>Show help for \e path or current directory</td></tr>
169 A <b>directory group</b> statement is a block of statements all executed relatively to a fixed
177 At the beginning of the block, the current directory is saved and the directory is changed to
178 the given directory. All commands are executed and at the end of the block, the saved directory
181 \section console_parse_api The parser API
183 The senf::console::CommandParser is responsible for taking text input and turning it into a
184 sequence of senf::console::ParseCommandInfo structures. The structures are returned by passing
185 them successively to a callback function.
187 Every statement is returned as a senf::console::ParseCommandInfo instance. Directory groups are
188 handled specially: They are divided into two special built-in commands called PUSHD and POPD.
194 #include <boost/utility.hpp>
195 #include <boost/scoped_ptr.hpp>
196 #include <boost/range/iterator_range.hpp>
197 #include <boost/iterator/iterator_facade.hpp>
198 #include <boost/function.hpp>
200 //#include "Parse.mpp"
201 ///////////////////////////////hh.p////////////////////////////////////////
206 namespace detail { struct ParserAccess; }
208 /** \brief Single argument token
210 All command arguments are split into tokens by the parser. Each token is returned as an
211 ArgumentToken instance.
213 \ingroup console_parser
219 PathSeparator = 0x0001,
220 ArgumentGroupOpen = 0x0002,
221 ArgumentGroupClose = 0x0004,
222 DirectoryGroupOpen = 0x0008,
223 DirectoryGroupClose = 0x0010,
224 CommandTerminator = 0x0020,
225 OtherPunctuation = 0x0040,
226 BasicString = 0x0080,
232 ArgumentGrouper = ArgumentGroupOpen
233 | ArgumentGroupClose,
235 DirectoryGrouper = DirectoryGroupOpen
236 | DirectoryGroupClose,
238 Punctuation = DirectoryGroupOpen
239 | DirectoryGroupClose
247 SimpleArgument = Word
252 std::string const & value() const; ///< String value of token
253 /**< This value is properly unquoted */
255 TokenType type() const; ///< Token type
257 bool is(unsigned tokens) const; ///< Check, whether tokens type matches \a tokens
258 /**< \a tokens is a bit-mask of token types to check. */
263 ArgumentToken(TokenType type, std::string token);
268 friend class detail::ParserAccess;
271 /** \brief Single parsed console command
273 Every command parsed is returned in a ParseCommandInfo instance. This information is purely
274 taken from the parser, no semantic information is attached at this point, the config/console
275 node tree is not involved in any why. ParseCommandInfo consist of
277 \li the type of command: built-in or normal command represented by a possibly relative path
278 into the command tree.
280 \li the arguments. Every argument consists of a range of ArgumentToken instances.
282 \ingroup console_parser
284 class ParseCommandInfo
286 typedef std::vector<ArgumentToken> Tokens;
287 typedef std::vector<std::string> CommandPath;
288 class ArgumentIterator;
291 typedef CommandPath::const_iterator path_iterator;
292 typedef Tokens::const_iterator token_iterator;
293 typedef ArgumentIterator argument_iterator;
294 typedef Tokens::size_type size_type;
296 typedef boost::iterator_range<path_iterator> CommandPathRange;
297 typedef boost::iterator_range<argument_iterator> ArgumentsRange;
298 typedef boost::iterator_range<token_iterator> TokensRange;
300 enum BuiltinCommand { NoBuiltin,
308 BuiltinCommand builtin() const; ///< Command type
309 /**< \returns \c NoBuiltin, if the command is an ordinary
310 command, otherwise the id of the built-in command */
311 CommandPathRange commandPath() const; ///< Command path
312 /**< This is the path to the command if it is not a built-in
313 command. Every element of the returned range
314 constitutes one path element. If the first element is
315 empty, the path is an absolute path, otherwise it is
316 relative. If the last element is an empty string, the
317 path ends with a '/' char. */
318 ArgumentsRange arguments() const; ///< Command arguments
319 /**< The returned range contains one TokensRange for each
321 TokensRange tokens() const; ///< All argument tokens
322 /**< The returned range contains \e all argument tokens in a
323 single range not divided into separate arguments. */
328 void setBuiltin(BuiltinCommand builtin);
329 void setCommand(std::vector<std::string> & commandPath);
330 void addToken(ArgumentToken const & token);
334 std::vector<std::string> commandPath_;
335 BuiltinCommand builtin_;
338 friend class detail::ParserAccess;
341 class ParseCommandInfo::ArgumentIterator
342 : public boost::iterator_facade< ParseCommandInfo::ArgumentIterator,
343 ParseCommandInfo::TokensRange,
344 boost::bidirectional_traversal_tag,
345 ParseCommandInfo::TokensRange >
350 ArgumentIterator(ParseCommandInfo::TokensRange::iterator i);
352 reference dereference() const;
353 bool equal(ArgumentIterator const & other) const;
357 mutable ParseCommandInfo::TokensRange::iterator b_;
358 mutable ParseCommandInfo::TokensRange::iterator e_;
360 void setRange() const;
362 friend class boost::iterator_core_access;
363 friend class ParseCommandInfo;
366 /**< \brief Output ParseCommandInfo instance
367 \related ParseCommandInfo
369 std::ostream & operator<<(std::ostream & stream, ParseCommandInfo const & info);
371 /** \brief Parse commands
373 This class implements a parser for the console/config language. It supports parsing strings
374 as well as files. For every parsed command, a callback function is called.
376 \implementation The implementation is based on Boost.Spirit. See the file \ref Parse.ih for
377 the formal language grammar.
379 \implementation Parsing an arbitrary iostream is not supported since arbitrary streams are
380 not seekable. If this is needed, it can however be provided using stream iterators and
381 some special iterator adaptors from Boost.Spirit. However, the amount of backtracking
382 needs to be analyzed before this is viable.
384 \todo Implement more detailed error reporting and error recovery.
386 \ingroup console_parser
392 ///////////////////////////////////////////////////////////////////////////
395 typedef boost::function<void (ParseCommandInfo const &)> Callback;
397 ///////////////////////////////////////////////////////////////////////////
398 ///\name Structors and default members
405 ///////////////////////////////////////////////////////////////////////////
407 bool parse(std::string command, Callback cb); ///< Parse string
408 bool parseFile(std::string filename, Callback cb); ///< Parse file
409 /**< \throws SystemException if the file cannot be
417 boost::scoped_ptr<Impl> impl_;
422 ///////////////////////////////hh.e////////////////////////////////////////
424 //#include "Parse.ct"
425 //#include "Parse.cti"
432 // comment-column: 40
433 // c-file-style: "senf"
434 // indent-tabs-mode: nil
435 // ispell-local-dictionary: "american"
436 // compile-command: "scons -u test"