Yate
yatescript.h
00001 /*
00002  * yatescript.h
00003  * Yet Another (Java)script library
00004  * This file is part of the YATE Project http://YATE.null.ro
00005  *
00006  * Yet Another Telephony Engine - a fully featured software PBX and IVR
00007  * Copyright (C) 2011 Null Team
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
00022  */
00023 
00024 #ifndef __YATESCRIPT_H
00025 #define __YATESCRIPT_H
00026 
00027 #include <yateclass.h>
00028 
00029 #ifdef _WINDOWS
00030 
00031 #ifdef LIBYSCRIPT_EXPORTS
00032 #define YSCRIPT_API __declspec(dllexport)
00033 #else
00034 #ifndef LIBYSCRIPT_STATIC
00035 #define YSCRIPT_API __declspec(dllimport)
00036 #endif
00037 #endif
00038 
00039 #endif /* _WINDOWS */
00040 
00041 #ifndef YSCRIPT_API
00042 #define YSCRIPT_API
00043 #endif
00044 
00048 namespace TelEngine {
00049 
00050 class ExpEvaluator;
00051 class ExpOperation;
00052 
00057 class YSCRIPT_API ExpExtender
00058 {
00059 public:
00063     virtual ~ExpExtender()
00064         { }
00065 
00070     virtual RefObject* refObj();
00071 
00079     virtual bool hasField(ObjList& stack, const String& name, GenObject* context) const;
00080 
00088     virtual NamedString* getField(ObjList& stack, const String& name, GenObject* context) const;
00089 
00098     virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context);
00099 
00107     virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context);
00108 
00116     virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
00117 };
00118 
00123 class YSCRIPT_API ExpEvaluator : public DebugEnabler
00124 {
00125 public:
00129     enum Parser {
00130         C,
00131         SQL,
00132     };
00133 
00137     enum Opcode {
00138         // FORTH style notation of effect on stack, C-syntax expression
00139         OpcNone = 0,// ( --- )
00140         OpcNull,    // ( --- A)
00141         OpcPush,    // ( --- A)
00142         OpcDrop,    // (A --- )
00143         OpcDup,     // (A --- A A)
00144         OpcSwap,    // (A B --- B A)
00145         OpcRot,     // (A B C --- B C A)
00146         OpcOver,    // (A B --- A B A)
00147         // Arithmetic operators
00148         OpcAdd,     // (A B --- A+B)
00149         OpcSub,     // (A B --- A-B)
00150         OpcMul,     // (A B --- A*B)
00151         OpcDiv,     // (A B --- A/B)
00152         OpcMod,     // (A B --- A%B)
00153         OpcNeg,     // (A --- -A)
00154         OpcIncPre,  // (A --- ++A)
00155         OpcDecPre,  // (A --- --A)
00156         OpcIncPost, // (A --- A++)
00157         OpcDecPost, // (A --- A--)
00158         // Bitwise logic operators
00159         OpcAnd,     // (A B --- A&B)
00160         OpcOr,      // (A B --- A|B)
00161         OpcXor,     // (A B --- A^B)
00162         OpcNot,     // (A --- ~A)
00163         OpcShl,     // (A B --- A<<B)
00164         OpcShr,     // (A B --- A>>B)
00165         // Boolean logic operators
00166         OpcLAnd,    // (A B --- A&&B)
00167         OpcLOr,     // (A B --- A||B)
00168         OpcLXor,    // (A B --- A^^B)
00169         OpcLNot,    // (A --- !A)
00170         // String concatenation
00171         OpcCat,     // (A B --- A.B)
00172         // String matching
00173         OpcReM,     // (A B --- Amatch/B/)
00174         OpcReIM,    // (A B --- Amatch_insensitive/B/)
00175         OpcReNm,    // (A B --- A!match/B/)
00176         OpcReINm,   // (A B --- A!match_insensitive/B/)
00177         OpcLike,    // (A B --- AlikeB)
00178         OpcILike,   // (A B --- Alike_insensitiveB)
00179         OpcNLike,   // (A B --- A!likeB)
00180         OpcNIlike,  // (A B --- A!like_insensitiveB)
00181         // Comparation operators
00182         OpcEq,      // (A B --- A==B)
00183         OpcNe,      // (A B --- A!=B)
00184         OpcGt,      // (A B --- A>B)
00185         OpcLt,      // (A B --- A<B)
00186         OpcGe,      // (A B --- A>=B)
00187         OpcLe,      // (A B --- A<=B)
00188         // Ternary conditional operator
00189         OpcCond,    // (A B C --- A?B:C)
00190         // Field naming operator
00191         OpcAs,      // (A B --- A[name=B])
00192         // Field replacement
00193         OpcField,   // (A --- A)
00194         // Call of function with N parameters
00195         OpcFunc,    // (... funcN --- func(...))
00196         // Label for a jump
00197         OpcLabel,   // ( --- )
00198         // Field assignment - can be ORed with other binary operators
00199         OpcAssign  = 0x0100, // (A B --- B,(&A=B))
00200         // Private extension area for derived classes
00201         OpcPrivate = 0x1000
00202     };
00203 
00209     explicit ExpEvaluator(const TokenDict* operators = 0, const TokenDict* unaryOps = 0);
00210 
00215     explicit ExpEvaluator(Parser style);
00216 
00221     ExpEvaluator(const ExpEvaluator& original);
00222 
00226     virtual ~ExpEvaluator();
00227 
00234     int compile(const char* expr, GenObject* context = 0);
00235 
00242     bool evaluate(ObjList* results, GenObject* context = 0) const;
00243 
00250     inline bool evaluate(ObjList& results, GenObject* context = 0) const
00251         { return evaluate(&results,context); }
00252 
00261     int evaluate(NamedList& results, unsigned int index = 0, const char* prefix = 0, GenObject* context = 0) const;
00262 
00270     int evaluate(Array& results, unsigned int index, GenObject* context = 0) const;
00271 
00276     inline bool simplify()
00277         { return trySimplify(); }
00278 
00283     inline bool inError() const
00284         { return m_inError; }
00285 
00290     inline bool null() const
00291         { return m_opcodes.count() == 0; }
00292 
00298     void dump(const ObjList& codes, String& res) const;
00299 
00304     inline void dump(String& res) const
00305         { return dump(m_opcodes,res); }
00306 
00312     inline String dump(const ObjList& codes) const
00313         { String s; dump(codes,s); return s; }
00314 
00319     inline String dump() const
00320         { String s; dump(s); return s; }
00321 
00326     inline const TokenDict* operators() const
00327         { return m_operators; }
00328 
00333     inline const TokenDict* unaryOps() const
00334         { return m_unaryOps; }
00335 
00340     inline ExpExtender* extender() const
00341         { return m_extender; }
00342 
00347     void extender(ExpExtender* ext);
00348 
00354     static void pushOne(ObjList& stack, ExpOperation* oper);
00355 
00361     static ExpOperation* popOne(ObjList& stack);
00362 
00368     static ExpOperation* popAny(ObjList& stack);
00369 
00376     virtual ExpOperation* popValue(ObjList& stack, GenObject* context = 0) const;
00377 
00386     virtual bool runOperation(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const;
00387 
00394     virtual bool runAllFields(ObjList& stack, GenObject* context = 0) const;
00395 
00396 protected:
00402     static char skipWhites(const char*& expr);
00403 
00410     inline static char condLower(char chr, bool makeLower)
00411         { return (makeLower && ('A' <= chr) && (chr <= 'Z')) ? (chr + ('a' - 'A')) : chr; }
00412 
00420     Opcode getOperator(const char*& expr, const TokenDict* operators, bool caseInsensitive = false) const;
00421 
00427     virtual bool keywordChar(char c) const;
00428 
00434     virtual int getKeyword(const char* str) const;
00435 
00442     bool gotError(const char* error = 0, const char* text = 0) const;
00443 
00450     bool gotError(const char* error = 0, const char* text = 0);
00451 
00459     virtual bool runCompile(const char*& expr, char stop = 0, Opcode nested = OpcNone);
00460 
00467     virtual char skipComments(const char*& expr, GenObject* context = 0) const;
00468 
00475     virtual int preProcess(const char*& expr, GenObject* context = 0);
00476 
00482     virtual Opcode getOperator(const char*& expr);
00483 
00489     virtual Opcode getUnaryOperator(const char*& expr);
00490 
00496     virtual Opcode getPostfixOperator(const char*& expr);
00497 
00503     virtual const char* getOperator(Opcode oper) const;
00504 
00510     virtual int getPrecedence(Opcode oper) const;
00511 
00517     virtual bool getRightAssoc(Opcode oper) const;
00518 
00525     virtual bool getSeparator(const char*& expr, bool remove);
00526 
00533     virtual bool getInstruction(const char*& expr, Opcode nested = OpcNone);
00534 
00541     virtual bool getOperand(const char*& expr, bool endOk = true);
00542 
00548     virtual bool getNumber(const char*& expr);
00549 
00555     virtual bool getString(const char*& expr);
00556 
00562     virtual bool getFunction(const char*& expr);
00563 
00569     virtual bool getField(const char*& expr);
00570 
00576     ExpOperation* addOpcode(Opcode oper, bool barrier = false);
00577 
00584     ExpOperation* addOpcode(Opcode oper, long int value, bool barrier = false);
00585 
00590     ExpOperation* addOpcode(const String& value);
00591 
00596     ExpOperation* addOpcode(long int value);
00597 
00602     ExpOperation* addOpcode(bool value);
00603 
00611     ExpOperation* addOpcode(Opcode oper, const String& name, long int value = 0, bool barrier = false);
00612 
00617     virtual bool trySimplify();
00618 
00626     virtual bool runEvaluate(const ObjList& opcodes, ObjList& stack, GenObject* context = 0) const;
00627 
00636     virtual bool runEvaluate(const ObjVector& opcodes, ObjList& stack, GenObject* context = 0, unsigned int index = 0) const;
00637 
00644     virtual bool runEvaluate(ObjList& stack, GenObject* context = 0) const;
00645 
00654     virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const;
00655 
00663     virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const;
00664 
00672     virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const;
00673 
00677     const TokenDict* m_operators;
00678 
00682     const TokenDict* m_unaryOps;
00683 
00687     ObjList m_opcodes;
00688 
00692     bool m_inError;
00693 
00694 private:
00695     ExpExtender* m_extender;
00696 };
00697 
00702 class YSCRIPT_API ExpOperation : public NamedString
00703 {
00704     friend class ExpEvaluator;
00705     YCLASS(ExpOperation,NamedString)
00706 public:
00711     inline static long int nonInteger()
00712         { return LONG_MIN; }
00713 
00718     inline ExpOperation(const ExpOperation& original)
00719         : NamedString(original.name(),original),
00720           m_opcode(original.opcode()), m_number(original.number()),
00721           m_barrier(original.barrier())
00722         { }
00723 
00729     inline ExpOperation(const ExpOperation& original, const char* name)
00730         : NamedString(name,original),
00731           m_opcode(original.opcode()), m_number(original.number()),
00732           m_barrier(original.barrier())
00733         { }
00734 
00741     inline explicit ExpOperation(const String& value, const char* name = 0, bool autoNum = false)
00742         : NamedString(name,value),
00743           m_opcode(ExpEvaluator::OpcPush),
00744           m_number(autoNum ? value.toLong(nonInteger()) : nonInteger()),
00745           m_barrier(false)
00746         { if (autoNum && value.isBoolean()) m_number = value.toBoolean() ? 1 : 0; }
00747 
00753     inline explicit ExpOperation(const char* value, const char* name = 0)
00754         : NamedString(name,value),
00755           m_opcode(ExpEvaluator::OpcPush), m_number(nonInteger()), m_barrier(false)
00756         { }
00757 
00763     inline explicit ExpOperation(long int value, const char* name = 0)
00764         : NamedString(name,"NaN"),
00765           m_opcode(ExpEvaluator::OpcPush), m_number(value), m_barrier(false)
00766         { if (value != nonInteger()) String::operator=((int)value); }
00767 
00773     inline explicit ExpOperation(bool value, const char* name = 0)
00774         : NamedString(name,String::boolText(value)),
00775           m_opcode(ExpEvaluator::OpcPush), m_number(value ? 1 : 0), m_barrier(false)
00776         { }
00777 
00785     inline ExpOperation(ExpEvaluator::Opcode oper, const char* name = 0, long int value = nonInteger(), bool barrier = false)
00786         : NamedString(name,""),
00787           m_opcode(oper), m_number(value), m_barrier(barrier)
00788         { }
00789 
00797     inline ExpOperation(ExpEvaluator::Opcode oper, const char* name, const char* value, bool barrier = false)
00798         : NamedString(name,value),
00799           m_opcode(oper), m_number(nonInteger()), m_barrier(barrier)
00800         { }
00801 
00806     inline ExpEvaluator::Opcode opcode() const
00807         { return m_opcode; }
00808 
00813     inline bool isInteger() const
00814         { return m_number != nonInteger(); }
00815 
00820     inline long int number() const
00821         { return m_number; }
00822 
00827     inline bool barrier() const
00828         { return m_barrier; }
00829 
00835     inline long int operator=(long int num)
00836         { m_number = num; String::operator=((int)num); return num; }
00837 
00843     virtual ExpOperation* clone(const char* name) const
00844         { return new ExpOperation(*this,name); }
00845 
00850     inline ExpOperation* clone() const
00851         { return clone(name()); }
00852 
00853 private:
00854     ExpEvaluator::Opcode m_opcode;
00855     long int m_number;
00856     bool m_barrier;
00857 };
00858 
00863 class YSCRIPT_API ExpFunction : public ExpOperation
00864 {
00865     YCLASS(ExpFunction,ExpOperation)
00866 public:
00872     inline ExpFunction(const char* name, long int argc = 0)
00873         : ExpOperation(ExpEvaluator::OpcFunc,name,argc)
00874         { if (name) (*this) << "[function " << name << "()]"; }
00875 
00881     virtual ExpOperation* clone(const char* name) const;
00882 };
00883 
00888 class YSCRIPT_API ExpWrapper : public ExpOperation
00889 {
00890 public:
00896     inline ExpWrapper(GenObject* object, const char* name = 0)
00897         : ExpOperation(ExpEvaluator::OpcPush,name,
00898             object ? object->toString().c_str() : (const char*)0),
00899           m_object(object)
00900         { }
00901 
00905     virtual ~ExpWrapper()
00906         { TelEngine::destruct(m_object); }
00907 
00913     virtual void* getObject(const String& name) const;
00914 
00920     virtual ExpOperation* clone(const char* name) const;
00921 
00926     GenObject* object() const
00927         { return m_object; }
00928 
00929 private:
00930     GenObject* m_object;
00931 };
00932 
00937 class YSCRIPT_API TableEvaluator
00938 {
00939 public:
00944     TableEvaluator(const TableEvaluator& original);
00945 
00950     TableEvaluator(ExpEvaluator::Parser style);
00951 
00957     TableEvaluator(const TokenDict* operators, const TokenDict* unaryOps);
00958 
00962     virtual ~TableEvaluator();
00963 
00969     virtual bool evalWhere(GenObject* context = 0);
00970 
00977     virtual bool evalSelect(ObjList& results, GenObject* context = 0);
00978 
00984     virtual unsigned int evalLimit(GenObject* context = 0);
00985 
00990     void extender(ExpExtender* ext);
00991 
00992 protected:
00993     ExpEvaluator m_select;
00994     ExpEvaluator m_where;
00995     ExpEvaluator m_limit;
00996     unsigned int m_limitVal;
00997 };
00998 
00999 class ScriptRun;
01000 
01005 class YSCRIPT_API ScriptContext : public RefObject, public ExpExtender
01006 {
01007 public:
01012     inline explicit ScriptContext(const char* name = 0)
01013         : m_params(name)
01014         { }
01015 
01020     inline NamedList& params()
01021         { return m_params; }
01022 
01027     inline const NamedList& params() const
01028         { return m_params; }
01029 
01034     virtual const String& toString() const
01035         { return m_params; }
01036 
01042     virtual void* getObject(const String& name) const;
01043 
01048     virtual RefObject* refObj()
01049         { return this; }
01050 
01055     virtual Mutex* mutex() = 0;
01056 
01064     virtual bool hasField(ObjList& stack, const String& name, GenObject* context) const;
01065 
01073     virtual NamedString* getField(ObjList& stack, const String& name, GenObject* context) const;
01074 
01082     virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context);
01083 
01091     virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context);
01092 
01100     virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
01101 
01102 private:
01103     NamedList m_params;
01104 };
01105 
01110 class YSCRIPT_API ScriptCode : public RefObject
01111 {
01112     YCLASS(ScriptCode,RefObject)
01113 public:
01119     virtual bool initialize(ScriptContext* context) const = 0;
01120 
01126     virtual bool evaluate(ScriptRun& runner, ObjList& results) const = 0;
01127 };
01128 
01133 class YSCRIPT_API ScriptStack : public ObjList
01134 {
01135     YCLASS(ScriptStack,ObjList)
01136     YNOCOPY(ScriptStack);
01137 public:
01142     ScriptStack(ScriptRun* owner)
01143         : m_runner(owner)
01144         { }
01145 
01150     inline ScriptRun* runner()
01151         { return m_runner; }
01152 private:
01153     ScriptRun* m_runner;
01154 };
01155 
01160 class YSCRIPT_API ScriptRun : public GenObject, public Mutex
01161 {
01162     friend class ScriptCode;
01163     YCLASS(ScriptRun,GenObject)
01164     YNOCOPY(ScriptRun);
01165 public:
01169     enum Status {
01170         Invalid,
01171         Running,
01172         Incomplete,
01173         Succeeded,
01174         Failed,
01175     };
01176 
01182     ScriptRun(ScriptCode* code, ScriptContext* context = 0);
01183 
01187     virtual ~ScriptRun();
01188 
01193     inline ScriptCode* code() const
01194         { return m_code; }
01195 
01200     inline ScriptContext* context() const
01201         { return m_context; }
01202 
01206     inline Status state() const
01207         { return m_state; }
01208 
01214     static const char* textState(Status state);
01215 
01220     inline const char* textState() const
01221         { return textState(m_state); }
01222 
01227     inline ObjList& stack()
01228         { return m_stack; }
01229 
01234     inline const ObjList& stack() const
01235         { return m_stack; }
01236 
01241     inline ScriptRun* clone() const
01242         { return new ScriptRun(code(),context()); }
01243 
01248     Status reset();
01249 
01254     Status execute();
01255 
01260     Status run();
01261 
01268     bool runAssign(const ExpOperation& oper, GenObject* context = 0);
01269 
01270 protected:
01275     Status resume();
01276 
01277 private:
01278     ScriptCode* m_code;
01279     ScriptContext* m_context;
01280     Status m_state;
01281     ObjList m_stack;
01282 };
01283 
01288 class YSCRIPT_API ScriptParser : public GenObject
01289 {
01290     YCLASS(ScriptParser,GenObject)
01291 public:
01295     virtual ~ScriptParser();
01296 
01303     virtual bool parse(const char* text, bool fragment = false) = 0;
01304 
01311     virtual bool parseFile(const char* name, bool fragment = false);
01312 
01316     inline void clear()
01317         { setCode(0); }
01318 
01323     inline ScriptCode* code() const
01324         { return m_code; }
01325 
01330     virtual ScriptContext* createContext() const;
01331 
01338     virtual ScriptRun* createRunner(ScriptCode* code, ScriptContext* context = 0) const;
01339 
01345     inline ScriptRun* createRunner(ScriptContext* context = 0) const
01346         { return createRunner(code(),context); }
01347 
01348 protected:
01352     inline ScriptParser()
01353         : m_code(0)
01354         { }
01355 
01360     void setCode(ScriptCode* code);
01361 
01362 private:
01363     ScriptCode* m_code;
01364 };
01365 
01370 class YSCRIPT_API JsObject : public ScriptContext
01371 {
01372     YCLASS(JsObject,ScriptContext)
01373 public:
01380     JsObject(const char* name = "Object", Mutex* mtx = 0, bool frozen = false);
01381 
01385     virtual ~JsObject();
01386 
01391     virtual Mutex* mutex()
01392         { return m_mutex; }
01393 
01402     virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context);
01403 
01411     virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context);
01412 
01420     virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context);
01421 
01428     virtual ExpOperation* popValue(ObjList& stack, GenObject* context = 0);
01429 
01434     inline bool frozen() const
01435         { return m_frozen; }
01436 
01440     inline void freeze()
01441         { m_frozen = true; }
01442 
01447     static void initialize(ScriptContext* context);
01448 
01449 protected:
01458     virtual bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context);
01459 
01460 private:
01461     bool m_frozen;
01462     Mutex* m_mutex;
01463 };
01464 
01469 class YSCRIPT_API JsFunction : public JsObject
01470 {
01471     YCLASS(JsFunction,JsObject)
01472 public:
01473 
01478     inline JsFunction(Mutex* mtx = 0)
01479         : JsObject("Function",mtx,true)
01480         { }
01481 
01490     virtual bool runDefined(ObjList& stack, const ExpOperation& oper, GenObject* context);
01491 
01492 };
01493 
01498 class YSCRIPT_API JsParser : public ScriptParser
01499 {
01500     YCLASS(JsParser,ScriptParser)
01501 public:
01508     virtual bool parse(const char* text, bool fragment = false);
01509 
01514     virtual ScriptContext* createContext() const;
01515 
01522     virtual ScriptRun* createRunner(ScriptCode* code, ScriptContext* context = 0) const;
01523 
01529     inline ScriptRun* createRunner(ScriptContext* context = 0) const
01530         { return createRunner(code(),context); }
01531 
01536     void adjustPath(String& script);
01537 
01542     inline const String& basePath() const
01543         { return m_basePath; }
01544 
01549     inline void basePath(const char* path)
01550         { m_basePath = path; }
01551 
01559     static ScriptRun::Status eval(const String& text, ExpOperation** result = 0, ScriptContext* context = 0);
01560 
01561 private:
01562     String m_basePath;
01563 };
01564 
01565 }; // namespace TelEngine
01566 
01567 #endif /* __YATESCRIPT_H */
01568 
01569 /* vi: set ts=8 sw=4 sts=4 noet: */