1 /*************************************************************************** 2 * parser.h is part of Math Graphic Library 3 * Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin@gmail.ru> * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU Lesser General Public License as * 7 * published by the Free Software Foundation; either version 3 of the * 8 * License, or (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU Lesser General Public * 16 * License along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 ***************************************************************************/ 20 #ifndef _MGL_PARSER_H_ 21 #define _MGL_PARSER_H_ 22 23 #ifdef __cplusplus 24 #include "mgl2/mgl.h" 25 #if MGL_HAVE_LTDL 26 #include <ltdl.h> 27 #endif 28 //----------------------------------------------------------------------------- 29 /// Structure for the command argument. 30 struct mglArg 31 { 32 int type; ///< Type of argument {0-data,1-string,2-number} 33 mglDataA *d; ///< Pointer to data (used if type==0) 34 mglString s; ///< String with parameters 35 mreal v; ///< Numerical value (used if type==2) 36 dual c; ///< Numerical complex value (used if type==2) mglArgmglArg37 mglArg():type(-1),d(0),v(0),c(0.) {} 38 }; 39 //----------------------------------------------------------------------------- 40 /// Structure for MGL command 41 struct mglCommand 42 { 43 const char *name; ///< Name of command 44 const char *desc; ///< Short command description (can be NULL) 45 const char *form; ///< Format of command arguments (can be NULL) 46 /// Function for executing (plotting) 47 int (*exec)(mglGraph *gr, long n, mglArg *a, const char *k, const char *opt); 48 /// Type of command: 0 - special plot, 1 - other plot, 49 /// 2 - setup, 3 - data handle, 4 - data create, 5 - subplot, 6 - program 50 /// 7 - 1d plot, 8 - 2d plot, 9 - 3d plot, 10 - dd plot, 11 - vector plot 51 /// 12 - axis, 13 - primitives, 14 - axis setup, 15 - text/legend, 16 - data transform 52 int type; 53 }; 54 extern mglCommand mgls_prg_cmd[], mgls_dat_cmd[], mgls_grf_cmd[], mgls_set_cmd[], mgls_prm_cmd[], mgls_rnd_cmd[]; 55 //----------------------------------------------------------------------------- 56 /// Structure for function name and position. 57 struct mglFunc 58 { 59 long pos; 60 int narg; 61 mglString func; 62 mglFunc(long p, const wchar_t *f); mglFuncmglFunc63 mglFunc(const mglFunc &f):pos(f.pos),narg(f.narg),func(f.func) {} mglFuncmglFunc64 mglFunc():pos(-1),narg(-1) {} 65 const mglFunc &operator=(const mglFunc &f) 66 { pos=f.pos; narg=f.narg; func=f.func; return f; } 67 }; 68 //----------------------------------------------------------------------------- 69 /// Structure for stack of functions and its arguments. 70 struct mglFnStack 71 { 72 long pos; ///< position to return 73 size_t stk; ///< stack at 'call' 74 mglString par[10]; ///< input parameters mglFnStackmglFnStack75 mglFnStack():pos(0),stk(0) {} 76 }; 77 //----------------------------------------------------------------------------- 78 /// Structure for stack of if|for|while. 79 #define MGL_ST_TRUE 0 // condition true 80 #define MGL_ST_FALSE 1 // condition false 81 #define MGL_ST_DONE 2 // condition done 82 #define MGL_ST_LOOP 4 // normal loop 83 #define MGL_ST_BREAK 8 // loop break 84 #define MGL_ST_STOP (MGL_ST_FALSE|MGL_ST_DONE|MGL_ST_BREAK) 85 #define MGL_ST_SKIP (MGL_ST_FALSE|MGL_ST_DONE) 86 struct mglPosStack 87 { 88 int pos; ///< position to return 89 mglData v; ///< data to iterate 90 long ind; ///< index in data array 91 int par; ///< for-parameter 92 unsigned state; ///< state of stack item 93 mglPosStack(int st=MGL_ST_LOOP):pos(-1),ind(0),par(-1),state(st) {} 94 }; 95 //----------------------------------------------------------------------------- 96 /// Function for asking question in console mode 97 void MGL_EXPORT mgl_ask_gets(const wchar_t *quest, wchar_t *res); 98 //----------------------------------------------------------------------------- 99 /// Structure for the command argument (see mglGraph::Exec()). 100 class mglParser 101 { 102 friend void mgl_export(wchar_t *out, const wchar_t *in, int type); 103 public: 104 #if MGL_HAVE_LTDL 105 std::vector<lt_dlhandle> DllOpened; ///< Opened external DLL (keep ) 106 #endif 107 std::vector<mglDataA*> DataList; ///< List with data and its names 108 std::vector<mglNum*> NumList; ///< List with numbers and its names 109 bool AllowDllCall; ///< Allow calls from external dynamic libraries 110 bool AllowSetSize; ///< Allow using setsize command 111 bool AllowFileIO; ///< Allow reading/saving files 112 volatile bool Stop; ///< Stop command was. Flag prevent further execution 113 mglCommand *Cmd; ///< Table of MGL commands (can be changed by user). It MUST be sorted by 'name'!!! 114 long InUse; ///< Smart pointer (number of users) 115 HMGL curGr; ///< Current grapher 116 int StarObhID; ///< staring object id 117 118 mglParser(bool setsize=false); 119 virtual ~mglParser(); 120 /// Find the command by the keyword name 121 const mglCommand *FindCommand(const char *name) const MGL_FUNC_PURE; 122 const mglCommand *FindCommand(const wchar_t *name) const MGL_FUNC_PURE; 123 /// Parse and execute the string of MGL script 124 inline int Parse(HMGL gr, const char *str, long pos=0) 125 { mglGraph GR(gr); return Parse(&GR,str,pos); } 126 int Parse(mglGraph *gr, const char *str, long pos=0); 127 /// Parse and execute the unicode string of MGL script 128 inline int Parse(HMGL gr, const wchar_t *str, long pos=0) 129 { mglGraph GR(gr); return Parse(&GR,str,pos); } 130 int Parse(mglGraph *gr, std::wstring str, long pos=0); 131 /// Execute MGL script file fname 132 inline void Execute(HMGL gr, FILE *fp, bool print=false) 133 { mglGraph GR(gr); Execute(&GR,fp,print); } 134 void Execute(mglGraph *gr, FILE *fp, bool print=false); 135 /// Execute MGL script from array of lines Execute(HMGL gr,int num,const wchar_t ** text)136 inline void Execute(HMGL gr, int num, const wchar_t **text) 137 { mglGraph GR(gr); Execute(&GR,num,text); } 138 void Execute(mglGraph *gr, int num, const wchar_t **text); 139 /// Execute MGL script text with '\n' separated lines Execute(HMGL gr,const wchar_t * text)140 inline void Execute(HMGL gr, const wchar_t *text) 141 { mglGraph GR(gr); Execute(&GR,text); } 142 void Execute(mglGraph *gr, const wchar_t *text); 143 /// Execute MGL script text with '\n' separated lines Execute(HMGL gr,const char * text)144 inline void Execute(HMGL gr, const char *text) 145 { mglGraph GR(gr); Execute(&GR,text); } 146 void Execute(mglGraph *gr, const char *text); 147 /// Scan for functions (use NULL for reset) 148 void ScanFunc(const wchar_t *line); 149 /// Check if name is function and return its address (or 0 if no) 150 long IsFunc(const wchar_t *name, int *narg=0); 151 /// Find variable or return 0 if absent 152 mglDataA *FindVar(const char *name) MGL_FUNC_PURE; 153 mglDataA *FindVar(const wchar_t *name) MGL_FUNC_PURE; 154 /// Find variable or create it if absent 155 mglDataA *AddVar(const char *name); 156 mglDataA *AddVar(const wchar_t *name); 157 /// Find number or return 0 if absent 158 mglNum *FindNum(const char *name) MGL_FUNC_PURE; 159 mglNum *FindNum(const wchar_t *name) MGL_FUNC_PURE; 160 /// Find number or create it if absent 161 mglNum *AddNum(const char *name); 162 mglNum *AddNum(const wchar_t *name); 163 /// Add string for parameter $1, ..., $9 164 void AddParam(int n, const char *str); 165 void AddParam(int n, const wchar_t *str); 166 /// Add new MGL command(s) (last command MUST HAVE name[0]=0 !!!) 167 void AddCommand(const mglCommand *cmd); 168 /// Restore Once flag RestoreOnce()169 inline void RestoreOnce() { Once = true; } 170 /// Delete variable by its name 171 void DeleteVar(const char *name); 172 void DeleteVar(const wchar_t *name); 173 /// Delete all data variables 174 void DeleteAll(); 175 /// Delete temporary data arrays DeleteTemp()176 inline void DeleteTemp() 177 { for(size_t i=0;i<DataList.size();i++) if(DataList[i] && DataList[i]->temp) 178 { mglDataA *u=DataList[i]; DataList[i]=0; delete u; } } 179 /// Set variant of argument(s) separated by '?' to be used 180 inline void SetVariant(int var=0) { Variant = var<=0?0:var; } 181 protected: 182 static mglCommand *BaseCmd; ///< Base table of MGL commands. It MUST be sorted by 'name'!!! 183 static void FillBaseCmd(); ///< Fill BaseCmd at initialization stage 184 185 ///< Test if condition is not-valid (n=1) or false (0) or true (1) TestCond(long m,const mglArg & a0,mglArg & a1,bool & cond)186 int TestCond(long m, const mglArg &a0, mglArg &a1, bool &cond) 187 { 188 int n = 1; 189 if(a0.type==2) { cond = a0.v!=0; n=0; } 190 else if(a0.type==0) 191 { n=0; cond = a0.d->FindAny((m>1 && a1.type==1) ? a1.s.s:"u"); } 192 return n; 193 } 194 private: 195 // long parlen; ///< Length of parameter strings 196 mglString par[40]; ///< Parameter for substituting instead of $1, ..., $9 197 bool Once; ///< Flag for command which should be executed only once 198 bool Skip; ///< Flag that commands should be skiped (inside 'once' block) 199 std::vector<mglPosStack> stack; ///< Stack of if|for|while commands 200 std::vector<mglFunc> func; ///< function names and position 201 std::vector<mglFnStack> fn_stack; ///< function calls stack 202 unsigned Variant; ///< Select variant of argument(s) separated by '?' 203 204 /// Parse command 205 int Exec(mglGraph *gr, const wchar_t *com, long n, mglArg *a, const std::wstring &var, const wchar_t *opt); 206 /// Fill arguments a from strings 207 void FillArg(mglGraph *gr, int n, std::wstring *arg, mglArg *a); 208 /// PreExecute stage -- parse some commands and create variables 209 int PreExec(mglGraph *gr, long n, std::wstring *arg, mglArg *a); 210 /// Execute program-flow control commands 211 int FlowExec(mglGraph *gr, const std::wstring &com, long n, mglArg *a); 212 /// Parse and execute the unicode string of MGL script 213 int ParseDat(mglGraph *gr, std::wstring str, mglData &res); 214 /// Define '$' parameters or start for loop 215 int ParseDef(std::wstring &str); 216 /// Parse $N arguments 217 void PutArg(std::wstring &str, bool def); 218 /// In skip mode ifskip()219 bool inline ifskip() 220 { return ( stack.size() && (stack.back().state & MGL_ST_SKIP) ); } skip()221 bool inline skip() 222 { return (Skip || (stack.size() && (stack.back().state & MGL_ST_STOP) )); } 223 bool CheckForName(const std::wstring &s); // check if name is valid for new data 224 }; 225 //----------------------------------------------------------------------------- 226 #endif 227 #endif 228