📄 parser.hpp
字号:
/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifndef CPCD_PARSER_HPP#define CPCD_PARSER_HPP#include "Vector.hpp"#include "Properties.hpp"#include "InputStream.hpp"#include "NdbOut.hpp"class ParserImpl;template<class T> struct ParserRow;//#define PARSER_DEBUG#ifdef PARSER_DEBUG#define DEBUG(x) \ ndbout_c("%s:%d:%s", __FILE__, __LINE__, x);#else #define DEBUG(x)#endif/** * A generic parser */template<class T>class Parser {public: /** * Status for parser */ enum ParserStatus { Ok = 0, Eof = 1, NoLine = 2, EmptyLine = 3, UnknownCommand = 4, UnknownArgument = 5, TypeMismatch = 6, InvalidArgumentFormat = 7, UnknownArgumentType = 8, CommandWithoutFunction = 9, ArgumentGivenTwice = 10, ExternalStop = 11, MissingMandatoryArgument = 12 }; /** * Context for parse */ struct Context { ParserStatus m_status; const ParserRow<T> * m_currentCmd; const ParserRow<T> * m_currentArg; char * m_currentToken; char m_tokenBuffer[512]; Vector<const ParserRow<T> *> m_aliasUsed; }; /** * Initialize parser */ Parser(const ParserRow<T> rows[], class InputStream & in = Stdin, bool breakOnCommand = false, bool breakOnEmptyLine = true, bool breakOnInvalidArg = false); ~Parser(); /** * Run parser */ bool run(Context &, T &, volatile bool * stop = 0) const; /** * Parse only one entry and return Properties object representing * the message */ const Properties *parse(Context &, T &); bool getBreakOnCommand() const; void setBreakOnCommand(bool v); bool getBreakOnEmptyLine() const; void setBreakOnEmptyLine(bool v); bool getBreakOnInvalidArg() const; void setBreakOnInvalidArg(bool v); private: ParserImpl * impl;};template<class T>struct ParserRow {public: enum Type { Cmd, Arg, CmdAlias, ArgAlias }; enum ArgType { String, Int, Properties }; enum ArgRequired { Mandatory, Optional }; enum ArgMinMax { CheckMinMax, IgnoreMinMax }; const char * name; const char * realName; Type type; ArgType argType; ArgRequired argRequired; ArgMinMax argMinMax; int minVal; int maxVal; void (T::* function)(typename Parser<T>::Context & ctx, const class Properties& args); const char * description; void *user_value;};/** * The void* equivalent implementation */class ParserImpl {public: class Dummy {}; typedef ParserRow<Dummy> DummyRow; typedef Parser<Dummy>::Context Context; ParserImpl(const DummyRow rows[], class InputStream & in, bool b_cmd, bool b_empty, bool b_iarg); ~ParserImpl(); bool run(Context *ctx, const class Properties **, volatile bool *) const ; static const DummyRow* matchCommand(Context*, const char*, const DummyRow*); static const DummyRow* matchArg(Context*, const char *, const DummyRow *); static bool parseArg(Context*, char*, const DummyRow*, Properties*); static bool checkMandatory(Context*, const Properties*);private: const DummyRow * const m_rows; class ParseInputStream & input; bool m_breakOnEmpty; bool m_breakOnCmd; bool m_breakOnInvalidArg;};template<class T>inlineParser<T>::Parser(const ParserRow<T> rows[], class InputStream & in, bool b_cmd, bool b_empty, bool b_iarg){ impl = new ParserImpl((ParserImpl::DummyRow *)rows, in, b_cmd, b_empty, b_iarg);}template<class T>inlineParser<T>::~Parser(){ delete impl;}template<class T>inlineboolParser<T>::run(Context & ctx, T & t, volatile bool * stop) const { const Properties * p; DEBUG("Executing Parser<T>::run"); if(impl->run((ParserImpl::Context*)&ctx, &p, stop)){ const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type if(cmd == 0){ /** * Should happen if run returns true */ abort(); } for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){ const ParserRow<T> * alias = ctx.m_aliasUsed[i]; if(alias->function != 0){ /** * Report alias usage with callback (if specified by user) */ DEBUG("Alias usage with callback"); (t.* alias->function)(ctx, * p); } } if(cmd->function == 0){ ctx.m_status = CommandWithoutFunction; DEBUG("CommandWithoutFunction"); delete p; return false; } (t.* cmd->function)(ctx, * p); // Call the function delete p; return true; } DEBUG(""); return false;}template<class T>inlineconst Properties *Parser<T>::parse(Context &ctx, T &t) { const Properties * p; volatile bool stop = false; DEBUG("Executing Parser<T>::parse"); if(impl->run((ParserImpl::Context*)&ctx, &p, &stop)){ const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type if(cmd == 0){ /** * Should happen if run returns true */ abort(); } for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){ const ParserRow<T> * alias = ctx.m_aliasUsed[i]; if(alias->function != 0){ /** * Report alias usage with callback (if specified by user) */ DEBUG("Alias usage with callback"); (t.* alias->function)(ctx, * p); } } if(cmd->function == 0){ DEBUG("CommandWithoutFunction"); ctx.m_status = CommandWithoutFunction; return p; } return p; } DEBUG(""); return NULL;}template<class T>inlinebool Parser<T>::getBreakOnCommand() const{ return impl->m_breakOnCmd;}template<class T>inlinevoidParser<T>::setBreakOnCommand(bool v){ impl->m_breakOnCmd = v;}template<class T>inlineboolParser<T>::getBreakOnEmptyLine() const{ return impl->m_breakOnEmpty;}template<class T>inlinevoidParser<T>::setBreakOnEmptyLine(bool v){ impl->m_breakOnEmpty = v;}template<class T>inlineboolParser<T>::getBreakOnInvalidArg() const{ return impl->m_breakOnInvalidArg;}template<class T>inlinevoidParser<T>::setBreakOnInvalidArg(bool v){ impl->m_breakOnInvalidArg = v;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -