iup-stack/iup/srcmglplot/mgl2/parser.h

204 lines
9.6 KiB
C
Raw Permalink Normal View History

2023-02-20 16:44:45 +00:00
/***************************************************************************
* parser.h is part of Math Graphic Library
* Copyright (C) 2007-2016 Alexey Balakin <mathgl.abalakin@gmail.ru> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 3 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 Library 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 _MGL_PARSER_H_
#define _MGL_PARSER_H_
#ifdef __cplusplus
#include "mgl2/mgl.h"
#if MGL_HAVE_LTDL
#include <ltdl.h>
#endif
//-----------------------------------------------------------------------------
/// Structure for the command argument.
struct mglArg
{
int type; ///< Type of argument {0-data,1-string,2-number}
mglDataA *d; ///< Pointer to data (used if type==0)
std::wstring w; ///< String with parameters
std::string s; ///< String with parameters
mreal v; ///< Numerical value (used if type==2)
dual c; ///< Numerical complex value (used if type==2)
mglArg():type(-1),d(0),v(0),c(0.) {}
};
//-----------------------------------------------------------------------------
/// Structure for MGL command
struct mglCommand
{
const char *name; ///< Name of command
const char *desc; ///< Short command description (can be NULL)
const char *form; ///< Format of command arguments (can be NULL)
/// Function for executing (plotting)
int (*exec)(mglGraph *gr, long n, mglArg *a, const char *k, const char *opt);
/// Type of command: 0 - data plot, 1 - other plot,
/// 2 - setup, 3 - data handle, 4 - data create, 5 - subplot, 6 - program
/// 7 - 1d plot, 8 - 2d plot, 9 - 3d plot, 10 - dd plot, 11 - vector plot
/// 12 - axis, 13 - primitives, 14 - axis setup, 15 - text/legend, 16 - data transform
int type;
};
extern mglCommand mgls_base_cmd[];
//-----------------------------------------------------------------------------
/// Structure for the number handling (see mglParse class).
struct mglNum
{
mreal d; ///< Number itself
dual c;
std::wstring s; ///< Number name
mglNum(mreal val=0):d(val),c(val) {}
};
//-----------------------------------------------------------------------------
/// Structure for function name and position.
struct mglFunc
{
long pos;
int narg;
std::wstring func;
mglFunc(long p, const wchar_t *f);
mglFunc(const mglFunc &f):pos(f.pos),narg(f.narg),func(f.func) {}
mglFunc():pos(-1),narg(-1) {}
};
//-----------------------------------------------------------------------------
/// Structure for stack of functions and its arguments.
struct mglFnStack
{
long pos;
std::wstring par[10];
mglFnStack():pos(0) {}
};
//-----------------------------------------------------------------------------
/// Function for asking question in console mode
void MGL_EXPORT mgl_ask_gets(const wchar_t *quest, wchar_t *res);
//-----------------------------------------------------------------------------
/// Structure for the command argument (see mglGraph::Exec()).
class mglParser
{
friend void mgl_export(wchar_t *out, const wchar_t *in, int type);
public:
#if MGL_HAVE_LTDL
std::vector<lt_dlhandle> DllOpened; ///< Opened external DLL (keep )
#endif
std::vector<mglDataA*> DataList; ///< List with data and its names
std::vector<mglNum*> NumList; ///< List with numbers and its names
bool AllowDllCall; ///< Allow calls from external dynamic libraries
bool AllowSetSize; ///< Allow using setsize command
bool AllowFileIO; ///< Allow reading/saving files
volatile bool Stop; ///< Stop command was. Flag prevent further execution
mglCommand *Cmd; ///< Table of MGL commands (can be changed by user). It MUST be sorted by 'name'!!!
long InUse; ///< Smart pointer (number of users)
const mglBase *curGr; ///< Current grapher
mglParser(bool setsize=false);
virtual ~mglParser();
/// Find the command by the keyword name
const mglCommand *FindCommand(const char *name) const MGL_FUNC_PURE;
const mglCommand *FindCommand(const wchar_t *name) const MGL_FUNC_PURE;
/// Parse and execute the string of MGL script
inline int Parse(HMGL gr, const char *str, long pos=0)
{ mglGraph GR(gr); return Parse(&GR,str,pos); }
int Parse(mglGraph *gr, const char *str, long pos=0);
/// Parse and execute the unicode string of MGL script
inline int Parse(HMGL gr, const wchar_t *str, long pos=0)
{ mglGraph GR(gr); return Parse(&GR,str,pos); }
int Parse(mglGraph *gr, std::wstring str, long pos=0);
/// Execute MGL script file fname
inline void Execute(HMGL gr, FILE *fp, bool print=false)
{ mglGraph GR(gr); Execute(&GR,fp,print); }
void Execute(mglGraph *gr, FILE *fp, bool print=false);
/// Execute MGL script from array of lines
inline void Execute(HMGL gr, int num, const wchar_t **text)
{ mglGraph GR(gr); Execute(&GR,num,text); }
void Execute(mglGraph *gr, int num, const wchar_t **text);
/// Execute MGL script text with '\n' separated lines
inline void Execute(HMGL gr, const wchar_t *text)
{ mglGraph GR(gr); Execute(&GR,text); }
void Execute(mglGraph *gr, const wchar_t *text);
/// Execute MGL script text with '\n' separated lines
inline void Execute(HMGL gr, const char *text)
{ mglGraph GR(gr); Execute(&GR,text); }
void Execute(mglGraph *gr, const char *text);
/// Scan for functions (use NULL for reset)
void ScanFunc(const wchar_t *line);
/// Check if name is function and return its address (or 0 if no)
long IsFunc(const std::wstring &name, int *narg=0);
/// Find variable or return 0 if absent
mglDataA *FindVar(const char *name) MGL_FUNC_PURE;
mglDataA *FindVar(const wchar_t *name) MGL_FUNC_PURE;
/// Find variable or create it if absent
mglDataA *AddVar(const char *name);
mglDataA *AddVar(const wchar_t *name);
/// Find number or return 0 if absent
mglNum *FindNum(const char *name) MGL_FUNC_PURE;
mglNum *FindNum(const wchar_t *name) MGL_FUNC_PURE;
/// Find number or create it if absent
mglNum *AddNum(const char *name);
mglNum *AddNum(const wchar_t *name);
/// Add string for parameter $1, ..., $9
void AddParam(int n, const char *str);
void AddParam(int n, const wchar_t *str);
/// Add new MGL command(s) (last command MUST HAVE name[0]=0 !!!)
void AddCommand(mglCommand *cmd, int num=0);
/// Restore Once flag
inline void RestoreOnce() { Once = true; }
/// Delete variable by its name
void DeleteVar(const char *name);
void DeleteVar(const wchar_t *name);
/// Delete all data variables
void DeleteAll();
/// Set variant of argument(s) separated by '?' to be used
inline void SetVariant(int var=0) { Variant = var<=0?0:var; }
private:
// long parlen; ///< Length of parameter strings
std::wstring par[40]; ///< Parameter for substituting instead of $1, ..., $9
bool Once; ///< Flag for command which should be executed only once
bool Skip; ///< Flag that commands should be skiped (inside 'once' block)
int if_stack[40]; ///< Stack for if-else-endif commands
int if_pos; ///< position in if_stack
std::vector<mglFunc> func; ///< function names and position
std::vector<mglFnStack> fn_stack; ///< function calls stack
// int fn_pos; ///< position in function stack
int if_for[40]; ///< position in if_stack for for-cycle start
mglData *fval; ///< Values for for-cycle. Note that nx - number of elements, ny - next element, nz - address (or string number) of first cycle command
int for_stack[40]; ///< The order of for-variables
int for_addr; ///< Flag for saving address in variable (for_addr-1)
bool for_br; ///< Break is switched on (skip all comands until 'next')
unsigned Variant; ///< Select variant of argument(s) separated by '?'
/// Parse command
int Exec(mglGraph *gr, const wchar_t *com, long n, mglArg *a, const std::wstring &var, const wchar_t *opt);
/// Fill arguments a from strings
void FillArg(mglGraph *gr, int n, std::wstring *arg, mglArg *a);
/// PreExecute stage -- parse some commands and create variables
int PreExec(mglGraph *gr, long n, std::wstring *arg, mglArg *a);
/// Execute program-flow control commands
int FlowExec(mglGraph *gr, const std::wstring &com, long n, mglArg *a);
/// Parse and execute the unicode string of MGL script
int ParseDat(mglGraph *gr, std::wstring str, mglData &res);
/// Define '$' parameters or start for loop
int ParseDef(std::wstring &str);
/// Parse $N arguments
void PutArg(std::wstring &str, bool def);
/// In skip mode
bool inline ifskip() { return (if_pos>0 && !(if_stack[if_pos-1]&1)); }
bool inline skip() { return (Skip || ifskip() || for_br); }
bool CheckForName(const std::wstring &s); // check if name is valid for new data
};
//-----------------------------------------------------------------------------
#endif
#endif