|
basic_parser.hhGo to the documentation of this file.00001 // 00002 // $Id: basic_parser.hh,v 1.15 2005/03/09 17:19:43 cholm Exp $ 00003 // 00004 // basic_parser.hh 00005 // Copyright (C) 2002 Christian Holm Christensen <cholm@nbi.dk> 00006 // 00007 // This library is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public License 00009 // as published by the Free Software Foundation; either version 2.1 00010 // of the License, or (at your option) any later version. 00011 // 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 // Lesser General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public 00018 // License along with this library; if not, write to the Free 00019 // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 00020 // 02111-1307 USA 00021 // 00022 #ifndef YLMM_basic_parser 00023 #define YLMM_basic_parser 00024 #ifndef YLMM_basic_messenger 00025 # include <ylmm/basic_messenger.hh> 00026 #endif 00027 #ifndef YLMM_basic_location 00028 # include <ylmm/basic_location.hh> 00029 #endif 00030 00031 /** @file basic_parser.hh 00032 @author Christian Holm Christensen 00033 @date Mon Sep 30 00:08:22 2002 00034 @brief Declaration of parser ABC. */ 00035 00036 /** Namespace for all parser and scanner classes. */ 00037 namespace ylmm 00038 { 00039 //===================================================================== 00040 /** @class parser_base basic_parser.hh <ylmm/basic_parser.hh> 00041 @brief ABC for parser classes. 00042 00043 This defines the common interface for parser classes, that 00044 doesn't depend on the semantic and location type. It's 00045 interface can safely be used in the application or via some 00046 library. 00047 @param lock The type of thread syncronisation locks used in the 00048 application. Per default a single threaded locking mechanism 00049 (that is - no locks) is used. The application should pass the 00050 appropiate type here to make the use of this class thread safe. 00051 @ingroup yacc 00052 */ 00053 template<typename Lock=basic_lock> 00054 class parser_base 00055 { 00056 public: 00057 /** Type of thread locks */ 00058 typedef Lock lock_type; 00059 protected: 00060 basic_messenger<lock_type>* _messenger; /** The output handler */ 00061 /** Do-nothing CTOR. */ 00062 parser_base(); 00063 /** Do-nothing DTOR. */ 00064 virtual ~parser_base() {} 00065 public: 00066 //@{ 00067 /// @name Abstract interface 00068 /** Get whether the parser is tracing or not. 00069 This member function is implmented via yaccmm.hh. 00070 @return true if we're tracing the parse */ 00071 virtual bool tracing() const = 0; 00072 /** Set whether the parser is tracing or not. 00073 This member function is implmented via yaccmm.hh. 00074 @param t if true, trace the parse 00075 @return true if we're tracing the parse */ 00076 virtual bool tracing(bool t) = 0; 00077 /** The main function member. 00078 @param arg Optional parameter 00079 @return 0 on success, non-zero on failure */ 00080 virtual int parse(void* arg=0) = 0; 00081 /** Input member function. 00082 @param arg optinal argument. 00083 @return next token ID number */ 00084 virtual int scan(void* arg=0) = 0; 00085 //@} 00086 00087 //@{ 00088 /// @name Output handler 00089 /** Get the output handler 00090 @return The output handler used by this parser. */ 00091 virtual basic_messenger<lock_type>& messenger() const; 00092 /** Set and get the output handler 00093 @param o The output handler to use. 00094 @return The output handler used by this parser. */ 00095 virtual 00096 basic_messenger<lock_type>& messenger(basic_messenger<lock_type>& o); 00097 //@} 00098 00099 //@{ 00100 /// @name message handling 00101 /** Called on errors. 00102 When the generated parser detects a parse error, this member 00103 function is called. Per default, it simply outputs the error 00104 message to std::cerr, but user code can override this to do 00105 fallbacks, etc. 00106 @param msg Is the message from the parser. */ 00107 virtual void fatal(const char* msg); 00108 /** Error printing - service function. 00109 When the generated parser wants to output error information, 00110 this is the member function that will be invoked. Per default 00111 it outputs the message to standard error. 00112 @param message The message to print */ 00113 virtual void error(const char* message, ...); 00114 /** Message printing - service function. When the generated 00115 parser wants to output various information, this is the member 00116 function that will be invoked. Per default it outputs the 00117 message to standard output. Also, when the generated parser 00118 wants to output trace information, this is the member function 00119 that will be invoked. Per default it outputs the message to 00120 standard error. @param text The message to print */ 00121 virtual void message(const char* text, ...); 00122 //@} 00123 }; 00124 //__________________________________________________________________ 00125 template <typename L> 00126 inline 00127 parser_base<L>::parser_base() 00128 { 00129 _messenger = basic_messenger<L>::default_handler(); 00130 } 00131 //__________________________________________________________________ 00132 template <typename L> 00133 inline basic_messenger<L>& parser_base<L>::messenger() const 00134 { 00135 return *_messenger; 00136 } 00137 00138 //__________________________________________________________________ 00139 template <typename L> 00140 inline basic_messenger<L>& 00141 parser_base<L>::messenger(basic_messenger<lock_type>& output) 00142 { 00143 _messenger = &output; 00144 return *_messenger; 00145 } 00146 00147 //__________________________________________________________________ 00148 template <typename L> 00149 inline void parser_base<L>::error(const char* message, ...) 00150 { 00151 if (!_messenger) return; 00152 va_list ap; 00153 va_start(ap, message); 00154 _messenger->error(message, ap); 00155 va_end(ap); 00156 } 00157 //__________________________________________________________________ 00158 template <typename L> 00159 inline void parser_base<L>::message(const char* message, ...) 00160 { 00161 if (!_messenger) return; 00162 va_list ap; 00163 va_start(ap, message); 00164 _messenger->message(message, ap); 00165 va_end(ap); 00166 } 00167 //__________________________________________________________________ 00168 template <typename L> 00169 inline void parser_base<L>::fatal(const char* message) 00170 { 00171 if (!_messenger) return; 00172 _messenger->error(message); 00173 } 00174 00175 //===================================================================== 00176 /** @class basic_parser basic_parser.hh <ylmm/basic_parser.hh> 00177 @brief Basic parser implementation. 00178 00179 This templated class implements a parser, or rather, a specific 00180 instantation of this tempalte implmentes it. To use it, define 00181 the the processor macro @c YLMM_PARSER_CLASS to a specific 00182 instance of this template, or a sub-class ofa specific instance 00183 in your @b Yacc input file to. Note that the third argument, 00184 @p id can be used to disambiqutate two parsers with the same 00185 @p Token, @p Location pair. 00186 See also @ref parser_doc. 00187 @param Token the type of the tokens used in the grammar. 00188 @param Location the location type used, if applicable for the 00189 backend parser generator (Normal @b Yacc does not support that, 00190 but @b Bison does). 00191 @param id is an integer that uniquely identifies the class. 00192 @param lock The type of thread syncronisation locks used in the 00193 application. Per default a single threaded locking mechanism 00194 (that is - no locks) is used. The application should pass the 00195 appropiate type here to make the use of this class thread safe. 00196 @ingroup yacc 00197 */ 00198 template <typename Token, typename Location=basic_location, 00199 int id=0, typename Lock=basic_lock> 00200 class basic_parser : public parser_base<Lock> 00201 { 00202 public: 00203 /// Type of tokens 00204 typedef Token token_type; 00205 /// Type of locationss 00206 typedef Location location_type; 00207 /// The Id of the parser class 00208 enum { parser_id = id }; 00209 protected: 00210 typedef parser_base<Lock> base_type; 00211 token_type* _token; /** Address of the current token */ 00212 location_type* _location; /** The current location. */ 00213 public: 00214 /** Do-nothing CTOR. */ 00215 basic_parser() : _token(0), _location(0) {} 00216 /** Do-nothing DTOR. */ 00217 virtual ~basic_parser() { } 00218 00219 //@{ 00220 /// @name Debug handling 00221 /** Get whether the parser is tracing or not. 00222 This member function is implmented via yaccmm.hh. 00223 @return true if we're tracing the parse */ 00224 virtual bool tracing() const; 00225 /** Set whether the parser is tracing or not. 00226 This member function is implmented via yaccmm.hh. 00227 @param t if true, trace the parse 00228 @return true if we're tracing the parse */ 00229 virtual bool tracing(bool t); 00230 //@} 00231 00232 //@{ 00233 /// @name Location information 00234 /** Test if we need location information. 00235 @return true if we need location information */ 00236 virtual bool need_where() const { return _location != 0; } 00237 /** Get the location of next token to be parsed. 00238 @return The location of next token to be parsed. */ 00239 virtual location_type& where() { return *_location; } 00240 /** Set the location of next token to be parsed. 00241 Must be invoked from the the scanner. 00242 @param loc The location of the next token to be parsed. 00243 @return The location of next token to be parsed. */ 00244 virtual location_type& where(location_type& loc); 00245 /** Set the address of the location information 00246 @param loc the address of the location information */ 00247 void where_addr(location_type* loc) { _location = loc; } 00248 //@} 00249 00250 //@{ 00251 /// @name Token handling 00252 /** Get the next token to be parsed. 00253 @return The next token to be parsed. */ 00254 virtual token_type& token() const { return *_token; } 00255 /** Set the next token to be parsed. 00256 Must be invoked from the the scanner. 00257 @param token The next token to be parsed. 00258 @return The next token to be parsed. */ 00259 virtual token_type& token(token_type& token); 00260 /** Set the address of next token to be parsed. 00261 @param token The next address of the token to be parsed. */ 00262 void token_addr(token_type* token) { _token = token; } 00263 //@} 00264 00265 //@{ 00266 /// @name Scanning and parsing 00267 /** The main function member. 00268 This member function starts the parser. It should call the C 00269 function generated by Yacc. This member function is 00270 implmented via yaccmm.hh. 00271 @param arg user defined data 00272 @return return value of yyparse. */ 00273 virtual int parse(void* arg=0); 00274 /** Input member function. 00275 When the parser wants more input, it calls this member 00276 function to get one (or more) token(s). The member function 00277 must return the token id value, as well as set the current 00278 token (using the token member function) and possibly 00279 location information (using the location member 00280 function). One way of implementing this, is to use a @b Lex 00281 generated scanner with the ylmm::basic_scanner class, and call 00282 the member function ylmm::basic_scanner::next, passing it the 00283 proper arguments. 00284 @param arg A pointer to user defined data. 00285 @return token ID number. */ 00286 virtual int scan(void* arg=0) = 0; 00287 //@} 00288 00289 //@{ 00290 /// @name Message handling 00291 /** Print info on currently passed token. 00292 When tracing is enabled, then this member function is 00293 invoked when a message about a token is to be output. Per 00294 default it writes the lookahead number and the address of the 00295 token. 00296 @param lookahead The current lookahead. 00297 @param token The current token. */ 00298 virtual void trace(int lookahead, const token_type& token); 00299 //@} 00300 }; 00301 //__________________________________________________________________ 00302 template <typename T, typename L, int id, typename M> 00303 inline L& 00304 basic_parser<T,L,id,M>::where(location_type& loc) 00305 { 00306 *_location = loc; 00307 return *_location; 00308 } 00309 //__________________________________________________________________ 00310 template <typename T, typename L, int id, typename M> 00311 inline T& 00312 basic_parser<T,L,id,M>::token(token_type& token) 00313 { 00314 *_token = token; 00315 return *_token; 00316 } 00317 //__________________________________________________________________ 00318 template <typename T, typename L, int id, typename M> 00319 inline void 00320 basic_parser<T,L,id,M>::trace(int lookahead, 00321 const token_type& token) 00322 { 00323 if (!base_type::_messenger) return; 00324 base_type::_messenger->message_stream() << " " << lookahead 00325 << " [" << token << "]" 00326 << std::flush; 00327 } 00328 } 00329 00330 00331 #endif 00332 //____________________________________________________________________ 00333 // 00334 // EOF 00335 // Christian Holm (home page) Last update Fri Jul 8 12:58:03 2005 Created by DoxyGen 1.4.3-20050530 |