Parser.hpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #ifndef CPCD_PARSER_HPP
  14. #define CPCD_PARSER_HPP
  15. #include "Vector.hpp"
  16. #include "Properties.hpp"
  17. #include "InputStream.hpp"
  18. #include "NdbOut.hpp"
  19. class ParserImpl;
  20. template<class T> struct ParserRow;
  21. //#define PARSER_DEBUG
  22. #ifdef PARSER_DEBUG
  23. #define DEBUG(x) 
  24.   ndbout_c("%s:%d:%s", __FILE__, __LINE__, x);
  25. #else 
  26. #define DEBUG(x)
  27. #endif
  28. /**
  29.  * A generic parser
  30.  */
  31. template<class T>
  32. class Parser {
  33. public:
  34.   /**
  35.    * Status for parser
  36.    */
  37.   enum ParserStatus {
  38.     Ok                     = 0,
  39.     Eof                    = 1,
  40.     NoLine                 = 2,
  41.     EmptyLine              = 3,
  42.     UnknownCommand         = 4,
  43.     UnknownArgument        = 5,
  44.     TypeMismatch           = 6,
  45.     InvalidArgumentFormat  = 7,
  46.     UnknownArgumentType    = 8,
  47.     CommandWithoutFunction = 9,
  48.     ArgumentGivenTwice     = 10,
  49.     ExternalStop           = 11,
  50.     MissingMandatoryArgument = 12
  51.   };
  52.   /**
  53.    * Context for parse
  54.    */
  55.   struct Context {
  56.     ParserStatus m_status;
  57.     const ParserRow<T> * m_currentCmd;
  58.     const ParserRow<T> * m_currentArg;
  59.     char * m_currentToken;
  60.     char m_tokenBuffer[512];
  61.     Vector<const ParserRow<T> *> m_aliasUsed;
  62.   };
  63.   
  64.   /**
  65.    * Initialize parser
  66.    */
  67.   Parser(const ParserRow<T> rows[], class InputStream & in = Stdin,
  68.  bool breakOnCommand = false, 
  69.  bool breakOnEmptyLine = true, 
  70.  bool breakOnInvalidArg = false);
  71.   ~Parser();
  72.   
  73.   /**
  74.    * Run parser
  75.    */
  76.   bool run(Context &, T &, volatile bool * stop = 0) const;
  77.   /**
  78.    * Parse only one entry and return Properties object representing
  79.    * the message
  80.    */
  81.   const Properties *parse(Context &, T &);
  82.   bool getBreakOnCommand() const;
  83.   void setBreakOnCommand(bool v);
  84.   
  85.   bool getBreakOnEmptyLine() const;
  86.   void setBreakOnEmptyLine(bool v);
  87.   bool getBreakOnInvalidArg() const;
  88.   void setBreakOnInvalidArg(bool v);
  89.   
  90. private:
  91.   ParserImpl * impl;
  92. };
  93. template<class T>
  94. struct ParserRow {
  95. public:
  96.   enum Type { Cmd, Arg, CmdAlias, ArgAlias };
  97.   enum ArgType { String, Int, Properties };
  98.   enum ArgRequired { Mandatory, Optional };
  99.   enum ArgMinMax { CheckMinMax, IgnoreMinMax };
  100.   
  101.   const char * name;
  102.   const char * realName; 
  103.   Type type;
  104.   ArgType argType;
  105.   ArgRequired argRequired;
  106.   ArgMinMax argMinMax;
  107.   int minVal;
  108.   int maxVal;
  109.   void (T::* function)(typename Parser<T>::Context & ctx, 
  110.        const class Properties& args);
  111.   const char * description;
  112.   void *user_value;
  113. };
  114. /**
  115.  * The void* equivalent implementation
  116.  */
  117. class ParserImpl {
  118. public:
  119.   class Dummy {};
  120.   typedef ParserRow<Dummy> DummyRow;
  121.   typedef Parser<Dummy>::Context Context;
  122.   
  123.   ParserImpl(const DummyRow rows[], class InputStream & in,
  124.      bool b_cmd, bool b_empty, bool b_iarg);
  125.   ~ParserImpl();
  126.   
  127.   bool run(Context *ctx, const class Properties **, volatile bool *) const ;
  128.   
  129.   static const DummyRow* matchCommand(Context*, const char*, const DummyRow*);
  130.   static const DummyRow* matchArg(Context*, const char *, const DummyRow *);
  131.   static bool parseArg(Context*, char*, const DummyRow*, Properties*);
  132.   static bool checkMandatory(Context*, const Properties*);
  133. private:
  134.   const DummyRow * const m_rows;
  135.   class ParseInputStream & input;
  136.   bool m_breakOnEmpty;
  137.   bool m_breakOnCmd;
  138.   bool m_breakOnInvalidArg;
  139. };
  140. template<class T>
  141. inline
  142. Parser<T>::Parser(const ParserRow<T> rows[], class InputStream & in,
  143.   bool b_cmd, bool b_empty, bool b_iarg){
  144.   impl = new ParserImpl((ParserImpl::DummyRow *)rows, in,
  145. b_cmd, b_empty, b_iarg);
  146. }
  147. template<class T>
  148. inline
  149. Parser<T>::~Parser(){
  150.   delete impl;
  151. }
  152. template<class T>
  153. inline
  154. bool
  155. Parser<T>::run(Context & ctx, T & t, volatile bool * stop) const {
  156.   const Properties * p;
  157.   DEBUG("Executing Parser<T>::run");
  158.   if(impl->run((ParserImpl::Context*)&ctx, &p, stop)){
  159.     const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
  160.     if(cmd == 0){
  161.       /**
  162.        * Should happen if run returns true
  163.        */
  164.       abort();
  165.     }
  166.     for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
  167.       const ParserRow<T> * alias = ctx.m_aliasUsed[i];
  168.       if(alias->function != 0){
  169. /**
  170.  * Report alias usage with callback (if specified by user)
  171.  */
  172. DEBUG("Alias usage with callback");
  173. (t.* alias->function)(ctx, * p);
  174.       }
  175.     }
  176.     if(cmd->function == 0){
  177.       ctx.m_status = CommandWithoutFunction;
  178.       DEBUG("CommandWithoutFunction");
  179.       delete p;
  180.       return false;
  181.     }
  182.     (t.* cmd->function)(ctx, * p); // Call the function
  183.     delete p;
  184.     return true;
  185.   }
  186.   DEBUG("");
  187.   return false;
  188. }
  189. template<class T>
  190. inline
  191. const Properties *
  192. Parser<T>::parse(Context &ctx, T &t) {
  193.   const Properties * p;
  194.   volatile bool stop = false;
  195.   DEBUG("Executing Parser<T>::parse");
  196.   if(impl->run((ParserImpl::Context*)&ctx, &p, &stop)){
  197.     const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
  198.     if(cmd == 0){
  199.       /**
  200.        * Should happen if run returns true
  201.        */
  202.       abort();
  203.     }
  204.     for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
  205.       const ParserRow<T> * alias = ctx.m_aliasUsed[i];
  206.       if(alias->function != 0){
  207. /**
  208.  * Report alias usage with callback (if specified by user)
  209.  */
  210. DEBUG("Alias usage with callback");
  211. (t.* alias->function)(ctx, * p);
  212.       }
  213.     }
  214.     if(cmd->function == 0){
  215.       DEBUG("CommandWithoutFunction");
  216.       ctx.m_status = CommandWithoutFunction;
  217.       return p;
  218.     }
  219.     return p;
  220.   }
  221.   DEBUG("");
  222.   return NULL;
  223. }
  224. template<class T>
  225. inline
  226. bool 
  227. Parser<T>::getBreakOnCommand() const{
  228.   return impl->m_breakOnCmd;
  229. }
  230. template<class T>
  231. inline
  232. void
  233. Parser<T>::setBreakOnCommand(bool v){
  234.   impl->m_breakOnCmd = v;
  235. }
  236. template<class T>
  237. inline
  238. bool
  239. Parser<T>::getBreakOnEmptyLine() const{
  240.   return impl->m_breakOnEmpty;
  241. }
  242. template<class T>
  243. inline
  244. void
  245. Parser<T>::setBreakOnEmptyLine(bool v){
  246.   impl->m_breakOnEmpty = v;
  247. }
  248. template<class T>
  249. inline
  250. bool
  251. Parser<T>::getBreakOnInvalidArg() const{
  252.   return impl->m_breakOnInvalidArg;
  253. }
  254. template<class T>
  255. inline
  256. void
  257. Parser<T>::setBreakOnInvalidArg(bool v){
  258.   impl->m_breakOnInvalidArg = v;
  259. }
  260. #endif