basic_parser.hh

Go 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 //
Top of page
Christian Holm (home page)
Last update Fri Jul 8 12:58:03 2005
Created by DoxyGen 1.4.3-20050530