├── common ├── global.cpp ├── common.pri ├── ztool.h ├── zobjectpool.h ├── zobject.cpp ├── zobject.h ├── zglobal.h ├── ztool.cpp ├── zvariant.h ├── zcode.h ├── zvariant.cpp └── zcode.cpp ├── base ├── zbase.h ├── base.pri ├── zsystem.h ├── zconsole.h ├── zsystem.cpp ├── zconsole.cpp └── zbase.cpp ├── lexical ├── lexical.pri └── zScript.ll ├── syntax ├── syntax.pri ├── stack.hh ├── position.hh ├── location.hh └── zScript.tab.hpp ├── zScript.pro ├── .gitignore ├── main.cpp ├── README.md ├── 3rdparty └── FlexLexer.h └── demo └── snake.zs /common/global.cpp: -------------------------------------------------------------------------------- 1 | #include "global.h" 2 | -------------------------------------------------------------------------------- /base/zbase.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE_H 2 | #define BASE_H 3 | 4 | namespace ZBase { 5 | void init(); 6 | } 7 | 8 | #endif // BASE_H 9 | -------------------------------------------------------------------------------- /lexical/lexical.pri: -------------------------------------------------------------------------------- 1 | SOURCES += $$PWD/lex.yy.cpp 2 | 3 | OTHER_FILES += $$PWD/zScript.ll 4 | 5 | win*: INCLUDEPATH += $$PWD/../3rdparty 6 | else: system(flex -+ -o lex.yy.cpp $$PWD/zScript.ll) 7 | 8 | INCLUDEPATH += $$PWD 9 | -------------------------------------------------------------------------------- /base/base.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | 3 | HEADERS += \ 4 | $$PWD/zconsole.h \ 5 | $$PWD/zbase.h \ 6 | $$PWD/zsystem.h 7 | 8 | SOURCES += \ 9 | $$PWD/zconsole.cpp \ 10 | $$PWD/zsystem.cpp \ 11 | $$PWD/zbase.cpp 12 | -------------------------------------------------------------------------------- /syntax/syntax.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/zScript.tab.hpp 3 | 4 | SOURCES += \ 5 | $$PWD/zScript.tab.cpp 6 | 7 | OTHER_FILES += $$PWD/zScript.yy 8 | 9 | win*: INCLUDEPATH += $$PWD/../3rdparty 10 | else: system(bison -d -v -L c++ -o zScript.tab.cpp $$PWD/zScript.yy) 11 | 12 | INCLUDEPATH += $$PWD 13 | -------------------------------------------------------------------------------- /common/common.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/zvariant.h \ 3 | $$PWD/zobject.h \ 4 | $$PWD/zcode.h \ 5 | $$PWD/zglobal.h \ 6 | $$PWD/ztool.h \ 7 | $$PWD/zobjectpool.h 8 | 9 | INCLUDEPATH += $$PWD 10 | 11 | SOURCES += \ 12 | $$PWD/zvariant.cpp \ 13 | $$PWD/zobject.cpp \ 14 | $$PWD/zcode.cpp \ 15 | $$PWD/ztool.cpp 16 | -------------------------------------------------------------------------------- /zScript.pro: -------------------------------------------------------------------------------- 1 | TARGET = zScript 2 | 3 | QT += core concurrent 4 | QT -= gui 5 | 6 | CONFIG += c++11 7 | 8 | CONFIG += console 9 | CONFIG -= app_bundle 10 | 11 | TEMPLATE = app 12 | 13 | include($$PWD/lexical/lexical.pri) 14 | include($$PWD/syntax/syntax.pri) 15 | include($$PWD/common/common.pri) 16 | include($$PWD/base/base.pri) 17 | 18 | #DESTDIR = $$shadowed($$PWD/../bin) 19 | 20 | SOURCES += \ 21 | main.cpp 22 | 23 | target.path = /usr/bin/ 24 | 25 | INSTALLS += target 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # bison tmp file 2 | 3 | syntax/zScript.output 4 | 5 | # C++ objects and libs 6 | 7 | *.slo 8 | *.lo 9 | *.o 10 | *.a 11 | *.la 12 | *.lai 13 | *.so 14 | *.dll 15 | *.dylib 16 | 17 | # Qt-es 18 | 19 | /.qmake.cache 20 | /.qmake.stash 21 | *.pro.user 22 | *.pro.user.* 23 | *.qbs.user 24 | *.qbs.user.* 25 | *.moc 26 | moc_*.cpp 27 | qrc_*.cpp 28 | ui_*.h 29 | Makefile* 30 | *build-* 31 | build 32 | 33 | # QtCreator 34 | 35 | *.autosave 36 | 37 | #QtCtreator Qml 38 | *.qmlproject.user 39 | *.qmlproject.user.* 40 | -------------------------------------------------------------------------------- /base/zsystem.h: -------------------------------------------------------------------------------- 1 | #ifndef ZSYSTEM_H 2 | #define ZSYSTEM_H 3 | 4 | #include "zobject.h" 5 | 6 | class ZSystem : public ZObject 7 | { 8 | public: 9 | explicit ZSystem(ZObject *parent = 0); 10 | 11 | void eval(ZVariant &retVals, const QList &args); 12 | void sleep(ZVariant &retVals, const QList &args); 13 | void msleep(ZVariant &retVals, const QList &args); 14 | void usleep(ZVariant &retVals, const QList &args); 15 | void random(ZVariant &retVals, const QList &args) const; 16 | void msecsSinceStartOfDay(ZVariant &retVals, const QList &args) const; 17 | }; 18 | 19 | #endif // ZSYSTEM_H 20 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "zbase.h" 2 | #include "zcode.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void begin(const char *fileName) 9 | { 10 | qRegisterMetaType("ZVariant"); 11 | ZCode::virtualStack.reserve(50); 12 | 13 | ZBase::init(); 14 | 15 | ZCodeExecuter *executer = ZCodeExecuter::beginCodeExecuter(); 16 | 17 | int quitCode = executer->eval(fileName); 18 | 19 | ZCodeExecuter::endCodeExecuter(); 20 | 21 | delete executer; 22 | 23 | qApp->exit(quitCode); 24 | } 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | QCoreApplication a(argc, argv); 29 | 30 | if(argc > 1) { 31 | QtConcurrent::run(QThreadPool::globalInstance(), &begin, argv[1]); 32 | } 33 | 34 | return a.exec();; 35 | } 36 | -------------------------------------------------------------------------------- /common/ztool.h: -------------------------------------------------------------------------------- 1 | #ifndef ZTOOL_H 2 | #define ZTOOL_H 3 | 4 | #include "zobject.h" 5 | 6 | #include 7 | 8 | Z_BEGIN_NAMESPACE 9 | 10 | class ZTool : public ZObject 11 | { 12 | public: 13 | explicit ZTool(ZObject *parent); 14 | 15 | static char charToEscape(char ch); 16 | /// \XXX 17 | static QString octStringHandler(QTextStream &stream, QString *errorString = 0); 18 | /// \xXX 19 | static QString utf8StringHandler(QTextStream &stream, QString *errorString = 0); 20 | /// \uXXXX 21 | static QString utf16StringHandler(QTextStream &stream, QString *errorString = 0); 22 | /// \u{XXX...} 23 | static QString ucs4StringHandler(QTextStream &stream, QString *errorString = 0); 24 | 25 | static QByteArray stringEscapeHandler(QTextStream &stream, const char *endWith = 0, QString *errorString = 0); 26 | inline static QByteArray stringEscapeHandler(const QByteArray &array) 27 | { 28 | QTextStream stream(array); 29 | 30 | return stringEscapeHandler(stream); 31 | } 32 | }; 33 | 34 | Z_END_NAMESPACE 35 | 36 | #endif // ZTOOL_H 37 | -------------------------------------------------------------------------------- /common/zobjectpool.h: -------------------------------------------------------------------------------- 1 | #ifndef ZOBJECTPOOL_H 2 | #define ZOBJECTPOOL_H 3 | 4 | #include "zglobal.h" 5 | 6 | #include 7 | 8 | Z_BEGIN_NAMESPACE 9 | 10 | template 11 | class ZObjectPool 12 | { 13 | public: 14 | ~ZObjectPool() 15 | { 16 | qDeleteAll(objectList); 17 | qDeleteAll(usedObjectList); 18 | } 19 | 20 | inline quint32 usedCount() const 21 | { 22 | return usedObjectList.count(); 23 | } 24 | 25 | inline T *reserveObject() 26 | { 27 | if (objectList.isEmpty()) { 28 | objectList << new T(); 29 | } 30 | 31 | usedObjectList << objectList.takeFirst(); 32 | 33 | return usedObjectList.last(); 34 | } 35 | 36 | inline void releaseObject(T *obj) 37 | { 38 | usedObjectList.removeOne(obj); 39 | objectList << obj; 40 | } 41 | 42 | inline void reset() 43 | { 44 | objectList << usedObjectList; 45 | usedObjectList.clear(); 46 | } 47 | 48 | private: 49 | QList objectList; 50 | QList usedObjectList; 51 | }; 52 | 53 | Z_END_NAMESPACE 54 | 55 | #endif // ZOBJECTPOOL_H 56 | -------------------------------------------------------------------------------- /common/zobject.cpp: -------------------------------------------------------------------------------- 1 | #include "zobject.h" 2 | 3 | Z_BEGIN_NAMESPACE 4 | 5 | /// ZObject 6 | ZObject::ZObject(ZObject *parent) 7 | : QObject(parent) 8 | { 9 | 10 | } 11 | 12 | Z_END_NAMESPACE 13 | 14 | ZVariant ZFunction::call(const QList &args) const 15 | { 16 | ZVariant retVal; 17 | 18 | emit callFun(retVal, args); 19 | 20 | return retVal; 21 | } 22 | 23 | ZPropertyVariant::ZPropertyVariant(const ZVariant &other, ZObject *object, const QByteArray &name) 24 | : ZVariant(other) 25 | { 26 | this->object = object; 27 | propertyName = name; 28 | } 29 | 30 | void ZPropertyVariant::depthCopyAssign(const ZVariant &other) const 31 | { 32 | if (object) 33 | object->setProperty(propertyName, other); 34 | 35 | ZVariant::depthCopyAssign(other); 36 | } 37 | 38 | ZVariant &ZPropertyVariant::operator=(const ZVariant &other) 39 | { 40 | if (object) 41 | object->setProperty(propertyName, other); 42 | 43 | return ZVariant::operator=(other); 44 | } 45 | 46 | ZVariant &ZPropertyVariant::operator=(ZVariant &&other) 47 | { 48 | if (object) 49 | object->setProperty(propertyName, other); 50 | 51 | return ZVariant::operator=(other); 52 | } 53 | -------------------------------------------------------------------------------- /base/zconsole.h: -------------------------------------------------------------------------------- 1 | #ifndef ZCONSOLE_H 2 | #define ZCONSOLE_H 3 | 4 | #include "zobject.h" 5 | 6 | Z_BEGIN_NAMESPACE 7 | 8 | class ZConsole : public ZObject 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | explicit ZConsole(ZObject *parent = 0); 14 | ~ZConsole(); 15 | 16 | public slots: 17 | void log(ZVariant &retVals, const QList &args) const; 18 | void print(ZVariant &retVals, const QList &args) const; 19 | void printLine(ZVariant &retVals, const QList &args) const; 20 | void getLine(ZVariant &retVals, const QList &args) const; 21 | void getChar(ZVariant &retVals, const QList &args) const; 22 | void getCh(ZVariant &retVals, const QList &args) const; 23 | void getKey(ZVariant &retVals, const QList &args) const; 24 | void kbhit(ZVariant &retVals, const QList &args) const; 25 | void setEcho(ZVariant &retVals, const QList &args) const; 26 | void setCursorVisible(ZVariant &retVals, const QList &args) const; 27 | void setCursorPos(ZVariant &retVals, const QList &args) const; 28 | void upCursor(ZVariant &retVals, const QList &args) const; 29 | void downCursor(ZVariant &retVals, const QList &args) const; 30 | void leftCursor(ZVariant &retVals, const QList &args) const; 31 | void rightCursor(ZVariant &retVals, const QList &args) const; 32 | void clear(ZVariant &retVals, const QList &args) const; 33 | void clearLine(ZVariant &retVals, const QList &args) const; 34 | void reset(ZVariant &retVals, const QList &args) const; 35 | void setColor(ZVariant &retVals, const QList &args) const; 36 | void flushInput(ZVariant &retVals, const QList &args) const; 37 | void flushOutput(ZVariant &retVals, const QList &args) const; 38 | 39 | private: 40 | QString variantToString(const ZVariant &val) const; 41 | }; 42 | 43 | Z_END_NAMESPACE 44 | 45 | #endif // ZCONSOLE_H 46 | -------------------------------------------------------------------------------- /common/zobject.h: -------------------------------------------------------------------------------- 1 | #ifndef ZOBJECT_H 2 | #define ZOBJECT_H 3 | 4 | #include "zvariant.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | Z_BEGIN_NAMESPACE 12 | 13 | #define Z_REGIST_SLOT(Fun) \ 14 | setProperty(QString(#Fun).split("::").last().toLatin1().constData(), ZVariant(new ZFunction(this, Fun, this))) 15 | 16 | class ZObject : public QObject 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit ZObject(ZObject *parent = 0); 22 | 23 | inline ZVariant property(const char *name) const 24 | { return ZVariant(QObject::property(name));} 25 | 26 | public slots: 27 | void setProperty(const char *name, const ZVariant &value) 28 | { QObject::setProperty(name, value.toQVariant());} 29 | }; 30 | 31 | class ZFunction : public ZObject 32 | { 33 | Q_OBJECT 34 | 35 | public: 36 | inline explicit ZFunction(ZObject *parent = 0) 37 | : ZObject(parent){} 38 | 39 | template 40 | inline explicit ZFunction(T target, Fun method, ZObject *parent) 41 | : ZObject(parent) 42 | { 43 | connect(this, &ZFunction::callFun, target, method, Qt::DirectConnection); 44 | } 45 | 46 | virtual ZVariant call(const QList &args) const; 47 | 48 | signals: 49 | void callFun(ZVariant &retVals, const QList &args) const; 50 | }; 51 | 52 | class ZMethod : public ZFunction 53 | { 54 | public: 55 | inline explicit ZMethod(const std::function&)> &fun, ZObject *parent = 0) 56 | : ZFunction(parent) 57 | , function(fun) 58 | { 59 | 60 | } 61 | 62 | ZVariant call(const QList &args) const Q_DECL_OVERRIDE 63 | { 64 | return function(args); 65 | } 66 | 67 | private: 68 | std::function&)> function; 69 | }; 70 | 71 | class ZPropertyVariant : public ZVariant 72 | { 73 | public: 74 | explicit ZPropertyVariant(const ZVariant &other, ZObject *object, const QByteArray &name); 75 | 76 | void depthCopyAssign(const ZVariant &other) const Q_DECL_OVERRIDE; 77 | ZVariant& operator=(const ZVariant &other) Q_DECL_OVERRIDE; 78 | ZVariant& operator=(ZVariant &&other) Q_DECL_OVERRIDE; 79 | 80 | private: 81 | QPointer object; 82 | QByteArray propertyName; 83 | }; 84 | 85 | Z_END_NAMESPACE 86 | 87 | #endif // ZOBJECT_H 88 | -------------------------------------------------------------------------------- /base/zsystem.cpp: -------------------------------------------------------------------------------- 1 | #include "zsystem.h" 2 | #include "zcode.h" 3 | 4 | #include 5 | #include 6 | 7 | ZSystem::ZSystem(ZObject *parent) 8 | : ZObject(parent) 9 | { 10 | Z_REGIST_SLOT(&ZSystem::eval); 11 | Z_REGIST_SLOT(&ZSystem::sleep); 12 | Z_REGIST_SLOT(&ZSystem::msleep); 13 | Z_REGIST_SLOT(&ZSystem::usleep); 14 | Z_REGIST_SLOT(&ZSystem::random); 15 | Z_REGIST_SLOT(&ZSystem::msecsSinceStartOfDay); 16 | 17 | const QTime &time = QTime::currentTime(); 18 | 19 | qsrand(time.msec() + time.second() * 1000); 20 | } 21 | 22 | void ZSystem::eval(ZVariant &retVals, const QList &args) 23 | { 24 | if(args.isEmpty()) 25 | return; 26 | 27 | ZCodeExecuter *executer = ZCodeExecuter::beginCodeExecuter(); 28 | 29 | retVals = executer->eval(args.first().toString().toLocal8Bit()); 30 | 31 | executer->endCodeExecuter(); 32 | 33 | delete executer; 34 | } 35 | 36 | void ZSystem::sleep(ZVariant &retVals, const QList &args) 37 | { 38 | Q_UNUSED(retVals) 39 | 40 | if(args.isEmpty()) 41 | return; 42 | 43 | QThread::currentThread()->sleep(args.first().toInt()); 44 | } 45 | 46 | void ZSystem::msleep(ZVariant &retVals, const QList &args) 47 | { 48 | Q_UNUSED(retVals) 49 | 50 | if(args.isEmpty()) 51 | return; 52 | 53 | QThread::currentThread()->msleep(args.first().toInt()); 54 | } 55 | 56 | void ZSystem::usleep(ZVariant &retVals, const QList &args) 57 | { 58 | Q_UNUSED(retVals) 59 | 60 | if(args.isEmpty()) 61 | return; 62 | 63 | QThread::currentThread()->usleep(args.first().toInt()); 64 | } 65 | 66 | void ZSystem::random(ZVariant &retVals, const QList &args) const 67 | { 68 | int min, max; 69 | 70 | if (args.count() == 2) { 71 | min = args.first().toInt(); 72 | max = args.last().toInt(); 73 | } else if (args.count() == 3) { 74 | qsrand(args.first().toInt()); 75 | min = args.at(1).toInt(); 76 | max = args.last().toInt(); 77 | } else { 78 | return; 79 | } 80 | 81 | retVals = (qrand() % (max - min + 1)) + min; 82 | 83 | const QTime &time = QTime::currentTime(); 84 | 85 | qsrand(time.msec() + time.second() * 1000 * retVals.toInt()); 86 | } 87 | 88 | void ZSystem::msecsSinceStartOfDay(ZVariant &retVals, const QList &args) const 89 | { 90 | Q_UNUSED(args) 91 | 92 | retVals = QTime::currentTime().msecsSinceStartOfDay(); 93 | } 94 | -------------------------------------------------------------------------------- /common/zglobal.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_H 2 | #define GLOBAL_H 3 | 4 | #define ENABLE_DEBUG QByteArray(getenv("ENABLE_DEBUG")).toInt() > 0 5 | 6 | #define zDebug \ 7 | if(ENABLE_DEBUG)\ 8 | qDebug().noquote() << __FILE__ << __LINE__ << __FUNCTION__ << "[Debug]:" 9 | #define zError qCritical().noquote() << "[Error]:" 10 | #define zInfo qInfo().noquote() << "[Info]:" 11 | #define zWarning qWarning().noquote() << "[Warning]:" 12 | #define zPrint qDebug().noquote() 13 | #define zStandardPrint std::cout 14 | 15 | #if !defined(Z_NAMESPACE) /* user namespace */ 16 | 17 | # define Z_PREPEND_NAMESPACE(name) ::name 18 | # define Z_USE_NAMESPACE 19 | # define Z_BEGIN_NAMESPACE 20 | # define Z_END_NAMESPACE 21 | # define Z_BEGIN_INCLUDE_NAMESPACE 22 | # define Z_END_INCLUDE_NAMESPACE 23 | #ifndef Z_BEGIN_MOC_NAMESPACE 24 | # define Z_BEGIN_MOC_NAMESPACE 25 | #endif 26 | #ifndef Z_END_MOC_NAMESPACE 27 | # define Z_END_MOC_NAMESPACE 28 | #endif 29 | # define Z_FORWARD_DECLARE_CLASS(name) class name; 30 | # define Z_FORWARD_DECLARE_STRUCT(name) struct name; 31 | # define Z_MANGLE_NAMESPACE(name) name 32 | 33 | #else /* user namespace */ 34 | 35 | # define Z_PREPEND_NAMESPACE(name) ::Z_NAMESPACE::name 36 | # define Z_USE_NAMESPACE using namespace ::Z_NAMESPACE; 37 | # define Z_BEGIN_NAMESPACE namespace Z_NAMESPACE { 38 | # define Z_END_NAMESPACE } 39 | # define Z_BEGIN_INCLUDE_NAMESPACE } 40 | # define Z_END_INCLUDE_NAMESPACE namespace Z_NAMESPACE { 41 | #ifndef Z_BEGIN_MOC_NAMESPACE 42 | # define Z_BEGIN_MOC_NAMESPACE Z_USE_NAMESPACE 43 | #endif 44 | #ifndef Z_END_MOC_NAMESPACE 45 | # define Z_END_MOC_NAMESPACE 46 | #endif 47 | # define Z_FORWARD_DECLARE_CLASS(name) \ 48 | Z_BEGIN_NAMESPACE class name; Z_END_NAMESPACE \ 49 | using Z_PREPEND_NAMESPACE(name); 50 | 51 | # define Z_FORWARD_DECLARE_STRUCT(name) \ 52 | Z_BEGIN_NAMESPACE struct name; Z_END_NAMESPACE \ 53 | using Z_PREPEND_NAMESPACE(name); 54 | 55 | # define Z_MANGLE_NAMESPACE0(x) x 56 | # define Z_MANGLE_NAMESPACE1(a, b) a##_##b 57 | # define Z_MANGLE_NAMESPACE2(a, b) Z_MANGLE_NAMESPACE1(a,b) 58 | # define Z_MANGLE_NAMESPACE(name) Z_MANGLE_NAMESPACE2( \ 59 | Z_MANGLE_NAMESPACE0(name), Z_MANGLE_NAMESPACE0(Z_NAMESPACE)) 60 | 61 | namespace Z_NAMESPACE {} 62 | 63 | # ifndef Z_BOOTSTRAPPED 64 | # ifndef Z_NO_USING_NAMESPACE 65 | /* 66 | This expands to a "using Z_NAMESPACE" also in _header files_. 67 | It is the only way the feature can be used without too much 68 | pain, but if people _really_ do not want it they can add 69 | DEFINES += Z_NO_USING_NAMESPACE to their .pro files. 70 | */ 71 | Z_USE_NAMESPACE 72 | # endif 73 | # endif 74 | 75 | #endif /* user namespace */ 76 | 77 | #endif // GLOBAL_H 78 | -------------------------------------------------------------------------------- /syntax/stack.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Stack handling for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file stack.hh 35 | ** Define the yy::stack class. 36 | */ 37 | 38 | #ifndef YY_YY_STACK_HH_INCLUDED 39 | # define YY_YY_STACK_HH_INCLUDED 40 | 41 | # include 42 | 43 | 44 | namespace yy { 45 | #line 46 "stack.hh" // stack.hh:132 46 | template > 47 | class stack 48 | { 49 | public: 50 | // Hide our reversed order. 51 | typedef typename S::reverse_iterator iterator; 52 | typedef typename S::const_reverse_iterator const_iterator; 53 | 54 | stack () 55 | : seq_ () 56 | { 57 | seq_.reserve (200); 58 | } 59 | 60 | stack (unsigned int n) 61 | : seq_ (n) 62 | {} 63 | 64 | inline 65 | T& 66 | operator[] (unsigned int i) 67 | { 68 | return seq_[seq_.size () - 1 - i]; 69 | } 70 | 71 | inline 72 | const T& 73 | operator[] (unsigned int i) const 74 | { 75 | return seq_[seq_.size () - 1 - i]; 76 | } 77 | 78 | /// Steal the contents of \a t. 79 | /// 80 | /// Close to move-semantics. 81 | inline 82 | void 83 | push (T& t) 84 | { 85 | seq_.push_back (T()); 86 | operator[](0).move (t); 87 | } 88 | 89 | inline 90 | void 91 | pop (unsigned int n = 1) 92 | { 93 | for (; n; --n) 94 | seq_.pop_back (); 95 | } 96 | 97 | void 98 | clear () 99 | { 100 | seq_.clear (); 101 | } 102 | 103 | inline 104 | typename S::size_type 105 | size () const 106 | { 107 | return seq_.size (); 108 | } 109 | 110 | inline 111 | const_iterator 112 | begin () const 113 | { 114 | return seq_.rbegin (); 115 | } 116 | 117 | inline 118 | const_iterator 119 | end () const 120 | { 121 | return seq_.rend (); 122 | } 123 | 124 | private: 125 | stack (const stack&); 126 | stack& operator= (const stack&); 127 | /// The wrapped container. 128 | S seq_; 129 | }; 130 | 131 | /// Present a slice of the top of a stack. 132 | template > 133 | class slice 134 | { 135 | public: 136 | slice (const S& stack, unsigned int range) 137 | : stack_ (stack) 138 | , range_ (range) 139 | {} 140 | 141 | inline 142 | const T& 143 | operator [] (unsigned int i) const 144 | { 145 | return stack_[range_ - i]; 146 | } 147 | 148 | private: 149 | const S& stack_; 150 | unsigned int range_; 151 | }; 152 | 153 | 154 | } // yy 155 | #line 156 "stack.hh" // stack.hh:132 156 | 157 | #endif // !YY_YY_STACK_HH_INCLUDED 158 | -------------------------------------------------------------------------------- /syntax/position.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Positions for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file position.hh 35 | ** Define the yy::position class. 36 | */ 37 | 38 | #ifndef YY_YY_POSITION_HH_INCLUDED 39 | # define YY_YY_POSITION_HH_INCLUDED 40 | 41 | # include // std::max 42 | # include 43 | # include 44 | 45 | # ifndef YY_NULLPTR 46 | # if defined __cplusplus && 201103L <= __cplusplus 47 | # define YY_NULLPTR nullptr 48 | # else 49 | # define YY_NULLPTR 0 50 | # endif 51 | # endif 52 | 53 | 54 | namespace yy { 55 | #line 56 "position.hh" // location.cc:296 56 | /// Abstract a position. 57 | class position 58 | { 59 | public: 60 | /// Construct a position. 61 | explicit position (std::string* f = YY_NULLPTR, 62 | unsigned int l = 1u, 63 | unsigned int c = 1u) 64 | : filename (f) 65 | , line (l) 66 | , column (c) 67 | { 68 | } 69 | 70 | 71 | /// Initialization. 72 | void initialize (std::string* fn = YY_NULLPTR, 73 | unsigned int l = 1u, 74 | unsigned int c = 1u) 75 | { 76 | filename = fn; 77 | line = l; 78 | column = c; 79 | } 80 | 81 | /** \name Line and Column related manipulators 82 | ** \{ */ 83 | /// (line related) Advance to the COUNT next lines. 84 | void lines (int count = 1) 85 | { 86 | if (count) 87 | { 88 | column = 1u; 89 | line = add_ (line, count, 1); 90 | } 91 | } 92 | 93 | /// (column related) Advance to the COUNT next columns. 94 | void columns (int count = 1) 95 | { 96 | column = add_ (column, count, 1); 97 | } 98 | /** \} */ 99 | 100 | /// File name to which this position refers. 101 | std::string* filename; 102 | /// Current line number. 103 | unsigned int line; 104 | /// Current column number. 105 | unsigned int column; 106 | 107 | private: 108 | /// Compute max(min, lhs+rhs) (provided min <= lhs). 109 | static unsigned int add_ (unsigned int lhs, int rhs, unsigned int min) 110 | { 111 | return (0 < rhs || -static_cast(rhs) < lhs 112 | ? rhs + lhs 113 | : min); 114 | } 115 | }; 116 | 117 | /// Add \a width columns, in place. 118 | inline position& 119 | operator+= (position& res, int width) 120 | { 121 | res.columns (width); 122 | return res; 123 | } 124 | 125 | /// Add \a width columns. 126 | inline position 127 | operator+ (position res, int width) 128 | { 129 | return res += width; 130 | } 131 | 132 | /// Subtract \a width columns, in place. 133 | inline position& 134 | operator-= (position& res, int width) 135 | { 136 | return res += -width; 137 | } 138 | 139 | /// Subtract \a width columns. 140 | inline position 141 | operator- (position res, int width) 142 | { 143 | return res -= width; 144 | } 145 | 146 | /// Compare two position objects. 147 | inline bool 148 | operator== (const position& pos1, const position& pos2) 149 | { 150 | return (pos1.line == pos2.line 151 | && pos1.column == pos2.column 152 | && (pos1.filename == pos2.filename 153 | || (pos1.filename && pos2.filename 154 | && *pos1.filename == *pos2.filename))); 155 | } 156 | 157 | /// Compare two position objects. 158 | inline bool 159 | operator!= (const position& pos1, const position& pos2) 160 | { 161 | return !(pos1 == pos2); 162 | } 163 | 164 | /** \brief Intercept output stream redirection. 165 | ** \param ostr the destination output stream 166 | ** \param pos a reference to the position to redirect 167 | */ 168 | template 169 | inline std::basic_ostream& 170 | operator<< (std::basic_ostream& ostr, const position& pos) 171 | { 172 | if (pos.filename) 173 | ostr << *pos.filename << ':'; 174 | return ostr << pos.line << '.' << pos.column; 175 | } 176 | 177 | 178 | } // yy 179 | #line 180 "position.hh" // location.cc:296 180 | #endif // !YY_YY_POSITION_HH_INCLUDED 181 | -------------------------------------------------------------------------------- /syntax/location.hh: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Locations for Bison parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file location.hh 35 | ** Define the yy::location class. 36 | */ 37 | 38 | #ifndef YY_YY_LOCATION_HH_INCLUDED 39 | # define YY_YY_LOCATION_HH_INCLUDED 40 | 41 | # include "position.hh" 42 | 43 | 44 | namespace yy { 45 | #line 46 "location.hh" // location.cc:296 46 | /// Abstract a location. 47 | class location 48 | { 49 | public: 50 | 51 | /// Construct a location from \a b to \a e. 52 | location (const position& b, const position& e) 53 | : begin (b) 54 | , end (e) 55 | { 56 | } 57 | 58 | /// Construct a 0-width location in \a p. 59 | explicit location (const position& p = position ()) 60 | : begin (p) 61 | , end (p) 62 | { 63 | } 64 | 65 | /// Construct a 0-width location in \a f, \a l, \a c. 66 | explicit location (std::string* f, 67 | unsigned int l = 1u, 68 | unsigned int c = 1u) 69 | : begin (f, l, c) 70 | , end (f, l, c) 71 | { 72 | } 73 | 74 | 75 | /// Initialization. 76 | void initialize (std::string* f = YY_NULLPTR, 77 | unsigned int l = 1u, 78 | unsigned int c = 1u) 79 | { 80 | begin.initialize (f, l, c); 81 | end = begin; 82 | } 83 | 84 | /** \name Line and Column related manipulators 85 | ** \{ */ 86 | public: 87 | /// Reset initial location to final location. 88 | void step () 89 | { 90 | begin = end; 91 | } 92 | 93 | /// Extend the current location to the COUNT next columns. 94 | void columns (int count = 1) 95 | { 96 | end += count; 97 | } 98 | 99 | /// Extend the current location to the COUNT next lines. 100 | void lines (int count = 1) 101 | { 102 | end.lines (count); 103 | } 104 | /** \} */ 105 | 106 | 107 | public: 108 | /// Beginning of the located region. 109 | position begin; 110 | /// End of the located region. 111 | position end; 112 | }; 113 | 114 | /// Join two locations, in place. 115 | inline location& operator+= (location& res, const location& end) 116 | { 117 | res.end = end.end; 118 | return res; 119 | } 120 | 121 | /// Join two locations. 122 | inline location operator+ (location res, const location& end) 123 | { 124 | return res += end; 125 | } 126 | 127 | /// Add \a width columns to the end position, in place. 128 | inline location& operator+= (location& res, int width) 129 | { 130 | res.columns (width); 131 | return res; 132 | } 133 | 134 | /// Add \a width columns to the end position. 135 | inline location operator+ (location res, int width) 136 | { 137 | return res += width; 138 | } 139 | 140 | /// Subtract \a width columns to the end position, in place. 141 | inline location& operator-= (location& res, int width) 142 | { 143 | return res += -width; 144 | } 145 | 146 | /// Subtract \a width columns to the end position. 147 | inline location operator- (location res, int width) 148 | { 149 | return res -= width; 150 | } 151 | 152 | /// Compare two location objects. 153 | inline bool 154 | operator== (const location& loc1, const location& loc2) 155 | { 156 | return loc1.begin == loc2.begin && loc1.end == loc2.end; 157 | } 158 | 159 | /// Compare two location objects. 160 | inline bool 161 | operator!= (const location& loc1, const location& loc2) 162 | { 163 | return !(loc1 == loc2); 164 | } 165 | 166 | /** \brief Intercept output stream redirection. 167 | ** \param ostr the destination output stream 168 | ** \param loc a reference to the location to redirect 169 | ** 170 | ** Avoid duplicate information. 171 | */ 172 | template 173 | inline std::basic_ostream& 174 | operator<< (std::basic_ostream& ostr, const location& loc) 175 | { 176 | unsigned int end_col = 0 < loc.end.column ? loc.end.column - 1 : 0; 177 | ostr << loc.begin; 178 | if (loc.end.filename 179 | && (!loc.begin.filename 180 | || *loc.begin.filename != *loc.end.filename)) 181 | ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col; 182 | else if (loc.begin.line < loc.end.line) 183 | ostr << '-' << loc.end.line << '.' << end_col; 184 | else if (loc.begin.column < end_col) 185 | ostr << '-' << end_col; 186 | return ostr; 187 | } 188 | 189 | 190 | } // yy 191 | #line 192 "location.hh" // location.cc:296 192 | #endif // !YY_YY_LOCATION_HH_INCLUDED 193 | -------------------------------------------------------------------------------- /lexical/zScript.ll: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "zScript.tab.hpp" 3 | #include "zglobal.h" 4 | #include "ztool.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | yy::parser::semantic_type *yylval = Q_NULLPTR; 13 | yy::parser::location_type *yyloc = Q_NULLPTR; 14 | 15 | int lineCount = 1; 16 | int currentColumn = 0; 17 | 18 | QQueue tokenQueue; 19 | QQueue tokenValQueue; 20 | QQueue tokenLocQueue; 21 | 22 | #define TOKEN_PREFIX yy::parser::token 23 | #define RECORD_TOKEN_LOC \ 24 | yyloc->begin.line = lineCount;\ 25 | yyloc->begin.column = currentColumn;\ 26 | yyloc->end.line = lineCount;\ 27 | yyloc->end.column = strlen(yytext) + currentColumn;\ 28 | currentColumn = yyloc->end.column; 29 | %} 30 | 31 | identifier [a-zA-Z][a-zA-Z0-9_]* 32 | number [0-9]+ 33 | real {number}\.{number}+ 34 | operator [-+*/=!<>,;{}\(\)\[\]&\|\^%~.?:@_] 35 | ignore [ \t\r] 36 | shell_head ^\s*#\s*!.* 37 | 38 | %% 39 | {ignore} 40 | 41 | \n { 42 | ++lineCount; 43 | currentColumn = 0; 44 | } 45 | 46 | "var" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::VAR;} 47 | "function" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::FUNCTION;} 48 | "new" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::NEW;} 49 | "delete" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::DELETE;} 50 | "throw" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::THROW;} 51 | "if" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::IF;} 52 | "else" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::ELSE;} 53 | "while" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::WHILE;} 54 | "for" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::FOR;} 55 | "undefined" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::UNDEFINED;} 56 | "goto" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::GOTO;} 57 | "return" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::RETURN;} 58 | "break" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::BREAK;} 59 | "continue" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::CONTINUE;} 60 | "switch" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::SWITCH;} 61 | "case" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::CASE;} 62 | "default" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::DEFAULT;} 63 | "==" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::EQ;} 64 | "===" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::STEQ;} 65 | "!=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::NEQ;} 66 | "!==" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::STNEQ;} 67 | "<=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::LE;} 68 | ">=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::GE;} 69 | "&=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::ANDASSIGN;} 70 | "|=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::ORASSIGN;} 71 | "^=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::XORASSIGN;} 72 | "%=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::MODASSIGN;} 73 | "+=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::ADDASSIGN;} 74 | "-=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::SUBASSIGN;} 75 | "*=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::MULASSIGN;} 76 | "/=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::DIVASSIGN;} 77 | "++" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::ADDSELF;} 78 | "--" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::SUBSELF;} 79 | "&&" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::LAND;} 80 | "||" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::LOR;} 81 | "&&=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::LANDASSIGN;} 82 | "||=" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::LORASSIGN;} 83 | "<<" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::LL;} 84 | ">>" { RECORD_TOKEN_LOC; return TOKEN_PREFIX::GG;} 85 | 86 | "true" { 87 | RECORD_TOKEN_LOC; 88 | 89 | yylval->identifier = new QByteArray("true"); 90 | 91 | return TOKEN_PREFIX::BOOL; 92 | } 93 | 94 | "false" { 95 | RECORD_TOKEN_LOC; 96 | 97 | yylval->identifier = new QByteArray("false"); 98 | 99 | return TOKEN_PREFIX::BOOL; 100 | } 101 | 102 | {operator} { 103 | RECORD_TOKEN_LOC; 104 | 105 | char ch = yytext[0]; 106 | 107 | if (ch == '{') { 108 | int token = yylex(); 109 | 110 | tokenQueue << token; 111 | tokenValQueue << *yylval; 112 | tokenLocQueue << *yyloc; 113 | 114 | if (token == '}') 115 | return TOKEN_PREFIX::NEW_OBJ_BEGIN; 116 | 117 | if (token != TOKEN_PREFIX::IDENTIFIER) 118 | return ch; 119 | 120 | token = yylex(); 121 | 122 | tokenQueue << token; 123 | tokenValQueue << *yylval; 124 | tokenLocQueue << *yyloc; 125 | 126 | if (token == ':') 127 | return TOKEN_PREFIX::NEW_OBJ_BEGIN; 128 | } 129 | 130 | return ch; 131 | } 132 | 133 | {identifier} { 134 | RECORD_TOKEN_LOC; 135 | 136 | yylval->identifier = new QByteArray(yytext); 137 | 138 | return TOKEN_PREFIX::IDENTIFIER; 139 | } 140 | 141 | (r\"|r\') { 142 | RECORD_TOKEN_LOC; 143 | 144 | yylval->identifier = new QByteArray(); 145 | 146 | QByteArray &str = *yylval->identifier; 147 | 148 | while(!yyin.eof() && !yyin.fail()) { 149 | char ch = yyin.get(); 150 | 151 | if(ch == yytext[1]) 152 | break; 153 | 154 | str.append(ch); 155 | } 156 | 157 | return TOKEN_PREFIX::STRING; 158 | } 159 | 160 | ['"] { 161 | RECORD_TOKEN_LOC; 162 | 163 | yylval->identifier = new QByteArray(); 164 | 165 | QByteArray &str = *yylval->identifier; 166 | char ch = 0; 167 | 168 | while(!yyin.eof() && !yyin.fail()) { 169 | if (ch == '\\') { 170 | str.append(yyin.get()); 171 | 172 | if (yyin.eof() || yyin.fail()) 173 | break; 174 | } 175 | 176 | ch = yyin.get(); 177 | 178 | if(ch == yytext[0]) 179 | break; 180 | 181 | str.append(ch); 182 | } 183 | 184 | str = ZTool::stringEscapeHandler(str); 185 | 186 | return TOKEN_PREFIX::STRING; 187 | } 188 | 189 | "//" { 190 | while(!yyin.eof() && !yyin.fail()) { 191 | char ch = yyin.get(); 192 | 193 | if(ch == '\n' || ch == '\r') 194 | break; 195 | 196 | if(ch == '\\') { 197 | if(yyin.eof() || yyin.fail()) 198 | break; 199 | 200 | yyin.get(); 201 | } 202 | } 203 | 204 | ++lineCount; 205 | } 206 | 207 | "/*" { 208 | while (!yyin.eof() && !yyin.fail()) { 209 | char ch = yyin.get(); 210 | 211 | if (ch == '*') { 212 | if(yyin.eof() || yyin.fail()) 213 | break; 214 | 215 | char ch_next = yyin.get(); 216 | 217 | if (ch_next == '/') 218 | break; 219 | else if (ch_next == '\n') 220 | ++lineCount; 221 | } else if (ch == '\n') { 222 | ++lineCount; 223 | } 224 | } 225 | } 226 | 227 | {number} { 228 | RECORD_TOKEN_LOC; 229 | 230 | yylval->identifier = new QByteArray(yytext); 231 | 232 | return TOKEN_PREFIX::INT; 233 | } 234 | 235 | {real} { 236 | RECORD_TOKEN_LOC; 237 | 238 | yylval->identifier = new QByteArray(yytext); 239 | 240 | return TOKEN_PREFIX::DOUBLE; 241 | } 242 | 243 | {shell_head} { 244 | if(lineCount > 1) { 245 | RECORD_TOKEN_LOC; 246 | 247 | yylval->msg = new std::string("Only at the beginning of the file"); 248 | 249 | return TOKEN_PREFIX::ERROR; 250 | } 251 | } 252 | 253 | %% 254 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 编译&运行 2 | #### Linux(Debian) 3 | 先安装编译依赖: 4 | 5 | sudo apt install qt5-default flex bison g++ make 6 | 7 | 克隆代码: 8 | 9 | git clone https://github.com/zccrs/zScript 10 | 11 | 12 | 编译: 13 | 14 | cd zScript 15 | mkdir build && cd build 16 | qmake .. 17 | make 18 | 19 | 运行: 20 | 21 | ./zScript ../demo/snake.zs 22 | 23 | #### Windows 24 | 先安装编译依赖: 25 | 26 | 到 http://download.qt.io/official_releases/qt/ 下载并安装最新版的Qt 27 | 28 | 克隆代码: 29 | 30 | git clone https://github.com/zccrs/zScript 31 | 32 | 打开项目并编译,可在“项目” --> “Build&Run” --> “Run” --> “Command line arguments:” 中添加命令行参数来执行要执行的代码文件。 33 | 34 | # zScript 35 | ### 变量的定义 36 | 变量使用关键字“var”进行定义。 37 | zScript提供了两种形式的变量定义语句。 38 | 39 | ##### 1.直接定义的形式,该语句的一般形式为: 40 | 41 | var 标识符; 42 | 该语句的含义是:定义变量名为“标识符”的变量。例如: 43 | 44 | var a; 45 | 该语句的作用是:定义一个名为“a”的变量。 46 | 47 | ##### 2.定义同时给变量初始化赋值,该语句的一般形式为: 48 | 49 | var 标识符 = 表达式; 50 | 该语句的含义是:定义变量名为“标识符”的变量,且给变量赋值为表达式的结果。例如: 51 | 52 | var a = 1 + 2; 53 | 该语句的作用是:定义一个名为“a”的变量,且赋值为3。 54 | “var”关键字可同时定义多个变量,每个变量之间使用符号“,”分割。 55 | ### 数组的定义 56 | 数组定义的一般形式为: 57 | 58 | var a = [表达式1, 表达式2, ...]; 59 | 该语句的含义是:生成一个数组,数组元素为中括号中表达式的结果。例如: 60 | 61 | var a = [1, 2, 3]; 62 | 该语句的作用是:定义一个包含三个元素的数组,元素的值分别为1、2、3,然后赋值给变量a; 63 | 数组使用“[”“]”定义,中间内容可以为空、一个表达式、多个表达式,多个表达式之间使用“,”隔开。 64 | 65 | a = a[0]; 66 | 取数组元素语法和C语言一样,都是中括号中写入数组下标。 67 | ### 选择控制语句 68 | 一个选择结构,包括一组或若干组操作,每组操作称为一个分支。通过选择控制语句可以实现选择结构。选择控制语句包括if语句、switch语句及起辅助控制作用的break语句。 69 | If语句用于计算给定的表达式,根据表达式的值是否为假,决定是否执行某一组操作。 70 | Switch语句首先求解一个表达式,然后根据计算结果的值,从哈希表中查询该从哪一组操作开始执行。 71 | Break语句用于switch结构中,用于终止当前switch结构的执行。 72 | #### if语句 73 | zScript提供了两种形式的if语句。 74 | ##### 1.单if子句的if语句。该if语句的一般形式为: 75 | 76 | if (表达式) { 77 | 语句组 78 | } 79 | 该语句的含义是:只有表达式的值为非零值时,才执行其内部的语句组。例如: 80 | 81 | if ( a > b ) { 82 | console.log(“hello”); 83 | } 84 | 该语句的作用是:当a的值大于b的值时(此时,“a>b”的值为真,为非假值),在屏幕上显示“hello”;否则,不显示“hello”。 85 | ##### 2.带else子句的if语句。该if语句的一般形式为: 86 | 87 | if ( 表达式 ) { 88 | 语句组1 89 | } else { 90 | 语句组2 91 | } 92 | 该语句的含义是:当表达式的值为非假时,执行语句组1,而不执行语句组2;否则,即表达式的值为假时,执行语句组2,而不执行语句组1。例如: 93 | 94 | if ( a > b ) { 95 | console.log(“hello1”); 96 | } else { 97 | console.log(“hello2”); 98 | } 99 | 该语句的作用是:若a的值大于b的值(此时“a>b”为真,为非假值),则在屏幕上显示“hello1”,而不显示“hello2”;否则,即表达式的值为假时,显示“hello2”,而不显示“hello1”。 100 | #### switch语句 101 | Switch语句与if语句一样,也可以实现分支选择。但if语句是判断一个表达式的值是否为假,决定是否执行某个分支;而switch语句是计算一个表达式的值,根据计算结果,从哈希表查询从哪个分支开始执行代码。Switch语句的一般形式为: 102 | 103 | switch( 表达式 ) { 104 | case 常量1:{ 105 | 语句组1 106 | } 107 | case 常量2:{ 108 | 语句组2 109 | } 110 | ... 111 | case 常量n:{ 112 | 语句组n 113 | } 114 | default: { 115 | 语句组 n + 1 116 | } 117 | } 118 | switch语句的执行过程: 119 | * 1.求解“表达式”的值; 120 | * 2.如果“表达式”的值与某个case后面的“常量”的值相同,则从这里开始顺序执行语句。结果switch执行有两种形式:一是遇到break语句为止;二是未遇到break语句,则程序依次执行完所有语句组。 121 | * 3.如果“表达式”的值与任何一个case后面的“常量”的值都不相同,当有default子句时,则执行default后面的语句,如果没有default子句,则结束switch。 122 | 123 | **注:与C++语言不通的是,case后可跟任意常量,不仅限于整数。case语句后的代码需使用“{}”包裹** 124 | ### 循环控制语句 125 | #### while语句 126 | while语句的一般形式为 127 | 128 | while( 表达式 ) { 129 | 循环体 130 | } 131 | while语句的执行过程: 132 | * 1.求解小括号中表达式的值。如果表达式的值为真,转第2步;否则转第3步。 133 | * 2.执行循环体,然后转第1步。 134 | * 3.执行while语句后面的语句。 135 | 136 | 小括号中表达式的值是否为假,决定着循环体是终止还是继续循环。因此,该表达式的值为循环条件。while循环语句的执行特点是,先判断循环条件是否成立,然后决定是否执行循环体。 137 | 当while语句的循环体只包含一条语句时,包含该循环体的“{}”可以省略。 138 | ##### 带else的while语句 139 | 140 | while( 表达式 ) { 141 | 循环体 142 | } else { 143 | ... 144 | } 145 | 当while语句的循环体正常结束时将执行else语句中的代码,否则不执行。由表达式的值为假时导致的循环结束视为循环体正常结束,由break语句导致的循环体结束视为非正常结束。 146 | 147 | 正常结束的示例: 148 | 149 | var i = 0; 150 | while( i++ < 3 ) { 151 | console.log(i); 152 | } else { 153 | console.log("正常结束"); 154 | } 155 | 156 | 此段代码的执行结果为: 157 | 158 | 1 159 | 2 160 | 3 161 | 正常结束 162 | 163 | 非正常结束的示例: 164 | 165 | var i = 0; 166 | while( i++ < 3 ) { 167 | console.log(i); 168 | break; 169 | } else { 170 | console.log("正常结束"); 171 | } 172 | 173 | 此段代码的执行结果为: 174 | 175 | 1 176 | 177 | 178 | #### for语句 179 | 在两种循环语句中,for语句最为灵活。for语句的一般形式为: 180 | 181 | for (表达式1; 表达式2; 表达式3) 182 | { 183 | 循环体 184 | } 185 | 186 | for语句的执行过程: 187 | * 1.求解表达式1的值。 188 | * 2.求解表达式2的值,若其值为假,则结束循环,转第4步;若其值为真,则执行循环体。 189 | * 3.求解表达式3。 190 | * 4.结束循环。 191 | 192 | **同while语句,for语句也可以存在else分支语句,表现形式也跟while语句一致。** 193 | 194 | ### 对象的定义 195 | 196 | 对象定义的一般形式为: 197 | 198 | { 199 | 属性名1: 属性的值, 200 | 属性名2: 属性的值, 201 | ... 202 | 属性名n: 属性的值, 203 | 属性名n+1: 属性的值 204 | } 205 | 例如: 206 | 207 | var object = { 208 | name: "张三", 209 | age: 18 210 | }; 211 | 变量object即是一个对象,它包含两个属性。 212 | 213 | **注:当对一个对象不存在的属性赋值时会将此属性加入到对象中,例如:** 214 | 215 | object.sex = '男'; 216 | 对象object中就会多出一个“sex”属性。 217 | ### 函数的定义 218 | 函数定义的一般形式为: 219 | 220 | var fun_name = (形参列表) { 221 | 语句组 222 | }; 223 | 该语句的含义是:生成一个函数对象,例如: 224 | 225 | var print = (a) { 226 | console.log(a); 227 | }; 228 | 229 | print(1); 230 | 231 | 此段代码执行结果为: 232 | 233 | 1 234 | 235 | 该语句的作用是:定义一个函数,它有一个名为“a”的形参,执行此函数会将a的值打印到屏幕上。 236 | 形参列表,可为空、一个、多个,多个形参之间使用“,”分割。 237 | 238 | #### 函数值的返回 239 | 和JavaScript类似,函数的定义中不必包含返回值的说明,直接在函数体任意位置添加 **return** 语句即可结束函数的执行,并且返回指定的值。 240 | 241 | ##### 单值返回 242 | 243 | var test = (arg1, arg2) { 244 | return arg1 + arg2; 245 | }; 246 | 247 | console.log(test(1, 2)); 248 | 249 | 此段代码执行结果为: 250 | 251 | 3 252 | 253 | ##### 多值返回 254 | 255 | var test = (arg1, arg2) { 256 | return arg1, arg2; 257 | }; 258 | 259 | console.log(test(1, 2)); 260 | 261 | 此段代码执行结果为: 262 | 263 | <1, 2> 264 | 265 | return语句在实现上其实仅支持返回一个值,能“多值返回”是因为 266 | 267 | 表达式1, 表达式2, ..., 表达式n,... 268 | 269 | 的写法是定义了一个“元组”类型的数据。 270 | 271 | ### 元组 272 | #### 定义 273 | 元组是一种特殊的数据类型,此类型无法直接被定义,通常和函数的return语句配合使用,可通过函数创建一个元组数据,如: 274 | 275 | var tuple = () { 276 | return 1, 2, 3; 277 | }(); 278 | 279 | console.log(tuple); 280 | 281 | 此段代码的执行结果为: 282 | 283 | <1, 2, 3> 284 | 285 | 使用console.log打印元组类型的数据时,会使用 “<”、“>”将其包括起来,并且使用“,”分割每个元素的值。 286 | 287 | #### 赋值操作 288 | 289 | var tuple = () { 290 | return 1, 2; 291 | }(); 292 | var a, b; 293 | a, b = tuple; 294 | console.log(a, b); 295 | 296 | 元组作为右值时,如果左值为 **“表达式1, 表达式2, ...”** 的写法,则会依次将元组中的值赋值给:表达式1、表达式2、...。否则,当左值为单个表达式时,则跟普通赋值一致,将元组整体赋值给此表达式。 297 | 298 | ### 作用域 299 | 300 | 作用域比较明显的标识的是:"{}",如if、while、for、函数体等语句皆是使用"{}"作为作用域限制的标识。"{}"也可以不依附于if、while、for等语句单独使用,如: 301 | 302 | { 303 | var a = 1; 304 | } 305 | 306 | console.log(a); 307 | 308 | 此段代码的执行结果为: 309 | 310 | [Error]: undefined reference: a 311 | 312 | 值得注意的是,多个连续的“{}”代码块之间至少要包含一句普通代码。如: 313 | 314 | if (true) { 315 | { 316 | console.log(1); 317 | } 318 | } 319 | 320 | 这段代码无法通过语法检查,可在两个代码块间添加空语句避免这种情况,如: 321 | 322 | if (true) { 323 | ; 324 | { 325 | console.log(1); 326 | } 327 | } 328 | 329 | ### break语句 330 | break语句用于结束当前作用域,可用于 while for switch-case "{}" 等语句产生的作用域中。如: 331 | 332 | { 333 | console.log(1); 334 | break; 335 | console.log(2); 336 | } 337 | 338 | console.log(3); 339 | 340 | 此段代码执行结果为: 341 | 342 | 1 343 | 3 344 | 345 | break可以多个连用来结束多层作用域。如: 346 | 347 | while (true) { 348 | console.log(1); 349 | 350 | { 351 | console.log(2); 352 | break, break; 353 | console.log(3); 354 | } 355 | 356 | console.log(4); 357 | } 358 | 359 | console.log(5); 360 | 361 | 此段代码的执行结果为: 362 | 363 | 1 364 | 2 365 | 5 366 | 367 | break, break, ... 的组合形式还可以配合 continue 一起使用,不过,continue 只能是列表中的最后一个。如: 368 | 369 | for (var i = 0; i < 2; ++i) { 370 | console.log(1); 371 | { 372 | console.log(2); 373 | break, continue; 374 | console.log(3); 375 | } 376 | 377 | console.log(4); 378 | } 379 | 380 | 381 | 此段代码的执行结果为: 382 | 383 | 1 384 | 2 385 | 1 386 | 2 -------------------------------------------------------------------------------- /3rdparty/FlexLexer.h: -------------------------------------------------------------------------------- 1 | // -*-C++-*- 2 | // FlexLexer.h -- define interfaces for lexical analyzer classes generated 3 | // by flex 4 | 5 | // Copyright (c) 1993 The Regents of the University of California. 6 | // All rights reserved. 7 | // 8 | // This code is derived from software contributed to Berkeley by 9 | // Kent Williams and Tom Epperly. 10 | // 11 | // Redistribution and use in source and binary forms, with or without 12 | // modification, are permitted provided that the following conditions 13 | // are met: 14 | 15 | // 1. Redistributions of source code must retain the above copyright 16 | // notice, this list of conditions and the following disclaimer. 17 | // 2. Redistributions in binary form must reproduce the above copyright 18 | // notice, this list of conditions and the following disclaimer in the 19 | // documentation and/or other materials provided with the distribution. 20 | 21 | // Neither the name of the University nor the names of its contributors 22 | // may be used to endorse or promote products derived from this software 23 | // without specific prior written permission. 24 | 25 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 26 | // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 27 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 | // PURPOSE. 29 | 30 | // This file defines FlexLexer, an abstract class which specifies the 31 | // external interface provided to flex C++ lexer objects, and yyFlexLexer, 32 | // which defines a particular lexer class. 33 | // 34 | // If you want to create multiple lexer classes, you use the -P flag 35 | // to rename each yyFlexLexer to some other xxFlexLexer. You then 36 | // include in your other sources once per lexer class: 37 | // 38 | // #undef yyFlexLexer 39 | // #define yyFlexLexer xxFlexLexer 40 | // #include 41 | // 42 | // #undef yyFlexLexer 43 | // #define yyFlexLexer zzFlexLexer 44 | // #include 45 | // ... 46 | 47 | #ifndef __FLEX_LEXER_H 48 | // Never included before - need to define base class. 49 | #define __FLEX_LEXER_H 50 | 51 | #include 52 | 53 | extern "C++" { 54 | 55 | struct yy_buffer_state; 56 | typedef int yy_state_type; 57 | 58 | class FlexLexer 59 | { 60 | public: 61 | virtual ~FlexLexer() { } 62 | 63 | const char* YYText() const { return yytext; } 64 | int YYLeng() const { return yyleng; } 65 | 66 | virtual void 67 | yy_switch_to_buffer( yy_buffer_state* new_buffer ) = 0; 68 | virtual yy_buffer_state* yy_create_buffer( std::istream* s, int size ) = 0; 69 | virtual yy_buffer_state* yy_create_buffer( std::istream& s, int size ) = 0; 70 | virtual void yy_delete_buffer( yy_buffer_state* b ) = 0; 71 | virtual void yyrestart( std::istream* s ) = 0; 72 | virtual void yyrestart( std::istream& s ) = 0; 73 | 74 | virtual int yylex() = 0; 75 | 76 | // Call yylex with new input/output sources. 77 | int yylex( std::istream& new_in, std::ostream& new_out ) 78 | { 79 | switch_streams( new_in, new_out ); 80 | return yylex(); 81 | } 82 | 83 | int yylex( std::istream* new_in, std::ostream* new_out = 0) 84 | { 85 | switch_streams( new_in, new_out ); 86 | return yylex(); 87 | } 88 | 89 | // Switch to new input/output streams. A nil stream pointer 90 | // indicates "keep the current one". 91 | virtual void switch_streams( std::istream* new_in, 92 | std::ostream* new_out ) = 0; 93 | virtual void switch_streams( std::istream& new_in, 94 | std::ostream& new_out ) = 0; 95 | 96 | int lineno() const { return yylineno; } 97 | 98 | int debug() const { return yy_flex_debug; } 99 | void set_debug( int flag ) { yy_flex_debug = flag; } 100 | 101 | protected: 102 | char* yytext; 103 | int yyleng; 104 | int yylineno; // only maintained if you use %option yylineno 105 | int yy_flex_debug; // only has effect with -d or "%option debug" 106 | }; 107 | 108 | } 109 | #endif // FLEXLEXER_H 110 | 111 | #if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce) 112 | // Either this is the first time through (yyFlexLexerOnce not defined), 113 | // or this is a repeated include to define a different flavor of 114 | // yyFlexLexer, as discussed in the flex manual. 115 | # define yyFlexLexerOnce 116 | 117 | extern "C++" { 118 | 119 | class yyFlexLexer : public FlexLexer { 120 | public: 121 | // arg_yyin and arg_yyout default to the cin and cout, but we 122 | // only make that assignment when initializing in yylex(). 123 | yyFlexLexer( std::istream& arg_yyin, std::ostream& arg_yyout ); 124 | yyFlexLexer( std::istream* arg_yyin = 0, std::ostream* arg_yyout = 0 ); 125 | private: 126 | void ctor_common(); 127 | 128 | public: 129 | 130 | virtual ~yyFlexLexer(); 131 | 132 | void yy_switch_to_buffer( yy_buffer_state* new_buffer ); 133 | yy_buffer_state* yy_create_buffer( std::istream* s, int size ); 134 | yy_buffer_state* yy_create_buffer( std::istream& s, int size ); 135 | void yy_delete_buffer( yy_buffer_state* b ); 136 | void yyrestart( std::istream* s ); 137 | void yyrestart( std::istream& s ); 138 | 139 | void yypush_buffer_state( yy_buffer_state* new_buffer ); 140 | void yypop_buffer_state(); 141 | 142 | virtual int yylex(); 143 | virtual void switch_streams( std::istream& new_in, std::ostream& new_out ); 144 | virtual void switch_streams( std::istream* new_in = 0, std::ostream* new_out = 0 ); 145 | virtual int yywrap(); 146 | 147 | protected: 148 | virtual int LexerInput( char* buf, int max_size ); 149 | virtual void LexerOutput( const char* buf, int size ); 150 | virtual void LexerError( const char* msg ); 151 | 152 | void yyunput( int c, char* buf_ptr ); 153 | int yyinput(); 154 | 155 | void yy_load_buffer_state(); 156 | void yy_init_buffer( yy_buffer_state* b, std::istream& s ); 157 | void yy_flush_buffer( yy_buffer_state* b ); 158 | 159 | int yy_start_stack_ptr; 160 | int yy_start_stack_depth; 161 | int* yy_start_stack; 162 | 163 | void yy_push_state( int new_state ); 164 | void yy_pop_state(); 165 | int yy_top_state(); 166 | 167 | yy_state_type yy_get_previous_state(); 168 | yy_state_type yy_try_NUL_trans( yy_state_type current_state ); 169 | int yy_get_next_buffer(); 170 | 171 | std::istream yyin; // input source for default LexerInput 172 | std::ostream yyout; // output sink for default LexerOutput 173 | 174 | // yy_hold_char holds the character lost when yytext is formed. 175 | char yy_hold_char; 176 | 177 | // Number of characters read into yy_ch_buf. 178 | int yy_n_chars; 179 | 180 | // Points to current character in buffer. 181 | char* yy_c_buf_p; 182 | 183 | int yy_init; // whether we need to initialize 184 | int yy_start; // start state number 185 | 186 | // Flag which is used to allow yywrap()'s to do buffer switches 187 | // instead of setting up a fresh yyin. A bit of a hack ... 188 | int yy_did_buffer_switch_on_eof; 189 | 190 | 191 | size_t yy_buffer_stack_top; /**< index of top of stack. */ 192 | size_t yy_buffer_stack_max; /**< capacity of stack. */ 193 | yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */ 194 | void yyensure_buffer_stack(void); 195 | 196 | // The following are not always needed, but may be depending 197 | // on use of certain flex features (like REJECT or yymore()). 198 | 199 | yy_state_type yy_last_accepting_state; 200 | char* yy_last_accepting_cpos; 201 | 202 | yy_state_type* yy_state_buf; 203 | yy_state_type* yy_state_ptr; 204 | 205 | char* yy_full_match; 206 | int* yy_full_state; 207 | int yy_full_lp; 208 | 209 | int yy_lp; 210 | int yy_looking_for_trail_begin; 211 | 212 | int yy_more_flag; 213 | int yy_more_len; 214 | int yy_more_offset; 215 | int yy_prev_more_offset; 216 | }; 217 | 218 | } 219 | 220 | #endif // yyFlexLexer || ! yyFlexLexerOnce 221 | -------------------------------------------------------------------------------- /common/ztool.cpp: -------------------------------------------------------------------------------- 1 | #include "ztool.h" 2 | 3 | #include 4 | #include 5 | 6 | Z_BEGIN_NAMESPACE 7 | 8 | ZTool::ZTool(ZObject *parent) 9 | : ZObject(parent) 10 | { 11 | 12 | } 13 | 14 | char ZTool::charToEscape(char ch) 15 | { 16 | switch (ch) { 17 | case 'a': 18 | return '\a'; 19 | case 'b': 20 | return '\b'; 21 | case 'f': 22 | return '\f'; 23 | case 'n': 24 | return '\n'; 25 | case 'r': 26 | return '\r'; 27 | case 't': 28 | return '\t'; 29 | case 'v': 30 | return '\v'; 31 | case '0': 32 | return '\0'; 33 | default: 34 | return ch; 35 | } 36 | } 37 | 38 | QString ZTool::octStringHandler(QTextStream &stream, QString *errorString) 39 | { 40 | QString array; 41 | 42 | while(!stream.atEnd()) { 43 | QString str = stream.read(4); 44 | 45 | if(str.count() != 4 || str.at(0) != '\\' || !str.at(1).isNumber()) { 46 | stream.seek(stream.pos() - 4); 47 | 48 | return array; 49 | } 50 | 51 | bool ok; 52 | 53 | quint8 ch = str.right(3).toUShort(&ok, 8); 54 | 55 | if(!ok) { 56 | if(errorString) { 57 | *errorString = QObject::tr("The unexpected symbol: ") + str; 58 | } 59 | 60 | return array; 61 | } 62 | 63 | array.append(ch); 64 | } 65 | 66 | return array; 67 | } 68 | 69 | QString ZTool::utf8StringHandler(QTextStream &stream, QString *errorString) 70 | { 71 | QString array; 72 | 73 | while(!stream.atEnd()) { 74 | QString str = stream.read(4); 75 | 76 | if(str.count() != 4 || str.at(0) != '\\' || str.at(1) != 'x') { 77 | stream.seek(stream.pos() - 4); 78 | 79 | return array; 80 | } 81 | 82 | bool ok; 83 | 84 | quint8 ch = str.right(2).toUShort(&ok, 16); 85 | 86 | if(!ok) { 87 | if(errorString) { 88 | *errorString = QObject::tr("The unexpected symbol: ") + str; 89 | } 90 | 91 | return array; 92 | } 93 | 94 | array.append(ch); 95 | } 96 | 97 | return array; 98 | } 99 | 100 | QString ZTool::utf16StringHandler(QTextStream &stream, QString *errorString) 101 | { 102 | QVector array; 103 | 104 | while(!stream.atEnd()) { 105 | QString str = stream.read(6); 106 | 107 | if(str.count() != 6 || str.at(0) != '\\' || str.at(1) != 'u' || str.at(2) == '{') { 108 | stream.seek(stream.pos() - 6); 109 | 110 | return QString::fromUtf16(array.constData(), array.size()); 111 | } 112 | 113 | bool ok; 114 | 115 | quint16 ch = str.right(4).toUShort(&ok, 16); 116 | 117 | if(!ok) { 118 | if(errorString) { 119 | *errorString = QObject::tr("The unexpected symbol: ") + str; 120 | } 121 | 122 | return QString::fromUtf16(array.constData(), array.size()); 123 | } 124 | 125 | array << ch; 126 | } 127 | 128 | return QString::fromUtf16(array.constData(), array.size()); 129 | } 130 | 131 | QString ZTool::ucs4StringHandler(QTextStream &stream, QString *errorString) 132 | { 133 | QVector array; 134 | 135 | while(!stream.atEnd()) { 136 | QString str = stream.read(3); 137 | 138 | if(str.count() != 3 || str.at(0) != '\\' || str.at(1) != 'u' || str.at(2) != '{') { 139 | stream.seek(stream.pos() - 3); 140 | 141 | return QString::fromUcs4(array.constData(), array.size()); 142 | } 143 | 144 | char ch; 145 | 146 | while(!stream.atEnd()) { 147 | stream >> ch; 148 | 149 | if(ch == '}') 150 | break; 151 | 152 | str.append(ch); 153 | } 154 | 155 | if(ch != '}') { 156 | if(errorString) { 157 | *errorString = QObject::tr("The unexpected symbol: ") + str + ch; 158 | } 159 | 160 | return QString::fromUcs4(array.constData(), array.size()); 161 | } 162 | 163 | bool ok; 164 | 165 | quint32 hex = str.mid(3).toUInt(&ok, 16); 166 | 167 | if(!ok) { 168 | if(errorString) { 169 | *errorString = QObject::tr("The unexpected symbol: ") + str; 170 | } 171 | 172 | return QString::fromUcs4(array.constData(), array.size()); 173 | } 174 | 175 | array << hex; 176 | } 177 | 178 | return QString::fromUcs4(array.constData(), array.size()); 179 | } 180 | 181 | QByteArray ZTool::stringEscapeHandler(QTextStream &stream, const char *endWith, QString *errorString) 182 | { 183 | QByteArray str; 184 | 185 | while(!stream.atEnd()) { 186 | char ch; 187 | 188 | stream.device()->peek(&ch, 1); 189 | 190 | if(endWith && ch == *endWith) { 191 | stream.device()->getChar(&ch); 192 | break; 193 | } 194 | 195 | if(ch == '\n' || ch == '\r') { 196 | if(errorString) 197 | *errorString = QObject::tr("The unexpected symbol: ") + ch; 198 | 199 | return str; 200 | } 201 | 202 | if(ch == '\\') { 203 | char next_ch; 204 | 205 | stream.seek(stream.pos() + 1); 206 | 207 | if(stream.device()->peek(&next_ch, 1) != 1) { 208 | if(errorString) 209 | *errorString = QObject::tr("Should not end with: ") + ch; 210 | 211 | return str; 212 | } 213 | 214 | stream.seek(stream.pos() - 1); 215 | 216 | switch(next_ch) { 217 | case 'x':{ 218 | qint64 pos = stream.pos(); 219 | 220 | str.append(utf8StringHandler(stream, errorString)); 221 | 222 | if(pos == stream.pos()) { 223 | if(errorString) 224 | *errorString = QObject::tr("The unexpected symbol: ") + next_ch; 225 | 226 | stream.seek(pos + 2); 227 | 228 | return str; 229 | } 230 | 231 | if(errorString && !errorString->isEmpty()) { 232 | return str; 233 | } 234 | 235 | break; 236 | } 237 | case 'u': { 238 | char next_ch; 239 | 240 | stream.seek(stream.pos() + 2); 241 | 242 | if(stream.device()->peek(&next_ch, 1) != 1) { 243 | if(errorString) 244 | *errorString = QObject::tr("Should not end with: ") + ch; 245 | 246 | return str; 247 | } 248 | 249 | stream.seek(stream.pos() - 2); 250 | 251 | qint64 pos = stream.pos(); 252 | 253 | if(next_ch == '{') { 254 | str.append(ucs4StringHandler(stream, errorString)); 255 | } else { 256 | str.append(utf16StringHandler(stream, errorString)); 257 | } 258 | 259 | if(pos == stream.pos()) { 260 | if(errorString) 261 | *errorString = QObject::tr("The unexpected symbol: ") + next_ch; 262 | 263 | stream.seek(pos + 3); 264 | 265 | return str; 266 | } 267 | 268 | if(errorString && !errorString->isEmpty()) { 269 | return str; 270 | } 271 | 272 | break; 273 | } 274 | default: { 275 | QChar ch(next_ch); 276 | 277 | if(ch.isNumber()) { 278 | qint64 pos = stream.pos(); 279 | 280 | str.append(octStringHandler(stream, errorString)); 281 | 282 | if(pos == stream.pos()) { 283 | if(errorString) 284 | *errorString = QObject::tr("The unexpected symbol: ") + next_ch; 285 | 286 | stream.seek(pos + 1); 287 | 288 | return str; 289 | } 290 | 291 | if(errorString && !errorString->isEmpty()) { 292 | return str; 293 | } 294 | } else { 295 | stream.seek(stream.pos() + 2); 296 | str.append(charToEscape(next_ch)); 297 | } 298 | break; 299 | } 300 | } 301 | } else { 302 | stream.seek(stream.pos() + 1); 303 | str.append(ch); 304 | } 305 | } 306 | 307 | return str; 308 | } 309 | 310 | Z_END_NAMESPACE 311 | -------------------------------------------------------------------------------- /base/zconsole.cpp: -------------------------------------------------------------------------------- 1 | #include "zconsole.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #ifdef Q_OS_UNIX 7 | #include 8 | #include 9 | #endif 10 | 11 | Z_BEGIN_NAMESPACE 12 | 13 | ZConsole::ZConsole(ZObject *parent) 14 | : ZObject(parent) 15 | { 16 | Z_REGIST_SLOT(&ZConsole::log); 17 | Z_REGIST_SLOT(&ZConsole::print); 18 | Z_REGIST_SLOT(&ZConsole::printLine); 19 | Z_REGIST_SLOT(&ZConsole::getLine); 20 | Z_REGIST_SLOT(&ZConsole::getChar); 21 | Z_REGIST_SLOT(&ZConsole::getCh); 22 | Z_REGIST_SLOT(&ZConsole::getKey); 23 | Z_REGIST_SLOT(&ZConsole::kbhit); 24 | Z_REGIST_SLOT(&ZConsole::setEcho); 25 | Z_REGIST_SLOT(&ZConsole::setCursorVisible); 26 | Z_REGIST_SLOT(&ZConsole::setCursorPos); 27 | Z_REGIST_SLOT(&ZConsole::upCursor); 28 | Z_REGIST_SLOT(&ZConsole::downCursor); 29 | Z_REGIST_SLOT(&ZConsole::leftCursor); 30 | Z_REGIST_SLOT(&ZConsole::rightCursor); 31 | Z_REGIST_SLOT(&ZConsole::clear); 32 | Z_REGIST_SLOT(&ZConsole::reset); 33 | Z_REGIST_SLOT(&ZConsole::setColor); 34 | Z_REGIST_SLOT(&ZConsole::flushInput); 35 | Z_REGIST_SLOT(&ZConsole::flushOutput); 36 | } 37 | 38 | ZConsole::~ZConsole() 39 | { 40 | 41 | } 42 | 43 | void ZConsole::log(ZVariant &retVals, const QList &args) const 44 | { 45 | printLine(retVals, args); 46 | } 47 | 48 | void ZConsole::print(ZVariant &retVals, const QList &args) const 49 | { 50 | Q_UNUSED(retVals) 51 | 52 | if(args.isEmpty()) 53 | return; 54 | 55 | for(int i = 0; i < args.count() - 1; ++i) { 56 | const ZVariant &val = args.at(i); 57 | 58 | zStandardPrint << variantToString(val).toStdString() << " "; 59 | } 60 | 61 | const ZVariant &val = args.last(); 62 | 63 | zStandardPrint << variantToString(val).toStdString(); 64 | } 65 | 66 | void ZConsole::printLine(ZVariant &retVals, const QList &args) const 67 | { 68 | print(retVals, args); 69 | 70 | zStandardPrint << std::endl; 71 | } 72 | 73 | void ZConsole::getLine(ZVariant &retVals, const QList &args) const 74 | { 75 | Q_UNUSED(args) 76 | 77 | char ch[100]; 78 | 79 | print(retVals, args); 80 | std::cin.getline(ch, 100, '\n'); 81 | 82 | retVals = QString(ch); 83 | } 84 | 85 | void ZConsole::getChar(ZVariant &retVals, const QList &args) const 86 | { 87 | Q_UNUSED(args) 88 | 89 | print(retVals, args); 90 | retVals = QString(std::cin.get()); 91 | } 92 | 93 | void ZConsole::getCh(ZVariant &retVals, const QList &args) const 94 | { 95 | Q_UNUSED(args) 96 | 97 | #ifdef Q_OS_UNIX 98 | struct termios newt, oldt; 99 | 100 | //获取终端属性 101 | tcgetattr(STDIN_FILENO, &oldt); 102 | newt = oldt; 103 | //设置字符不缓冲且不回显 104 | newt.c_lflag &= ~( ICANON | ECHO ); 105 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); 106 | retVals = QString(getchar()); 107 | //还原终端属性 108 | tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 109 | #endif 110 | } 111 | 112 | void ZConsole::getKey(ZVariant &retVals, const QList &args) const 113 | { 114 | Q_UNUSED(args) 115 | 116 | #ifdef Q_OS_UNIX 117 | int oldf; 118 | struct termios newt, oldt; 119 | 120 | tcgetattr(STDIN_FILENO, &oldt); 121 | newt = oldt; 122 | //设置字符不缓冲且不回显 123 | newt.c_lflag &= ~( ICANON | ECHO ); 124 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); 125 | oldf = fcntl(STDIN_FILENO, F_GETFL, 0); 126 | fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); 127 | retVals = int(getchar()); 128 | //还原终端属性 129 | tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 130 | fcntl(STDIN_FILENO, F_SETFL, oldf); 131 | #endif 132 | } 133 | 134 | void ZConsole::kbhit(ZVariant &retVals, const QList &args) const 135 | { 136 | Q_UNUSED(args) 137 | 138 | #ifdef Q_OS_UNIX 139 | struct termios oldt, newt; 140 | 141 | int ch; 142 | int oldf; 143 | 144 | tcgetattr(STDIN_FILENO, &oldt); 145 | newt = oldt; 146 | newt.c_lflag &= ~(ICANON | ECHO); 147 | tcsetattr(STDIN_FILENO, TCSANOW, &newt); 148 | oldf = fcntl(STDIN_FILENO, F_GETFL, 0); 149 | fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); 150 | ch = getchar(); 151 | tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 152 | fcntl(STDIN_FILENO, F_SETFL, oldf); 153 | 154 | if(ch != EOF) 155 | { 156 | ungetc(ch, stdin); 157 | retVals = true; 158 | 159 | return; 160 | } 161 | #endif 162 | 163 | retVals = false; 164 | } 165 | 166 | void ZConsole::setEcho(ZVariant &retVals, const QList &args) const 167 | { 168 | Q_UNUSED(retVals) 169 | 170 | if (args.isEmpty()) 171 | return; 172 | 173 | #ifdef Q_OS_UNIX 174 | struct termios termios; 175 | 176 | tcgetattr(STDIN_FILENO, &termios); 177 | 178 | if (args.first().toBool()) 179 | termios.c_lflag |= ECHO; 180 | else 181 | termios.c_lflag &= ~ECHO; 182 | 183 | tcsetattr(STDIN_FILENO, TCSANOW, &termios); 184 | #endif 185 | } 186 | 187 | void ZConsole::setCursorVisible(ZVariant &retVals, const QList &args) const 188 | { 189 | Q_UNUSED(retVals) 190 | 191 | if (args.isEmpty()) 192 | return; 193 | 194 | if (args.first().toBool()) 195 | printf("\033[?25h"); 196 | else 197 | printf("\033[?25l"); 198 | 199 | fflush(stdout); 200 | } 201 | 202 | void ZConsole::setCursorPos(ZVariant &retVals, const QList &args) const 203 | { 204 | Q_UNUSED(retVals) 205 | 206 | const ZVariant& x = args.value(0); 207 | const ZVariant& y = args.value(1); 208 | 209 | printf("\033[%d;%dH", y.toInt(), x.toInt()); 210 | fflush(stdout); 211 | } 212 | 213 | void ZConsole::upCursor(ZVariant &retVals, const QList &args) const 214 | { 215 | Q_UNUSED(retVals) 216 | 217 | int n = 1; 218 | 219 | if (!args.isEmpty()) 220 | n = args.first().toInt(); 221 | 222 | printf("\033[%dA", n); 223 | fflush(stdout); 224 | } 225 | 226 | void ZConsole::downCursor(ZVariant &retVals, const QList &args) const 227 | { 228 | Q_UNUSED(retVals) 229 | 230 | int n = 1; 231 | 232 | if (!args.isEmpty()) 233 | n = args.first().toInt(); 234 | 235 | printf("\033[%dB", n); 236 | fflush(stdout); 237 | } 238 | 239 | void ZConsole::leftCursor(ZVariant &retVals, const QList &args) const 240 | { 241 | Q_UNUSED(retVals) 242 | 243 | int n = 1; 244 | 245 | if (!args.isEmpty()) 246 | n = args.first().toInt(); 247 | 248 | printf("\033[%dD", n); 249 | fflush(stdout); 250 | } 251 | 252 | void ZConsole::rightCursor(ZVariant &retVals, const QList &args) const 253 | { 254 | Q_UNUSED(retVals) 255 | 256 | int n = 1; 257 | 258 | if (!args.isEmpty()) 259 | n = args.first().toInt(); 260 | 261 | printf("\033[%dC", n); 262 | fflush(stdout); 263 | } 264 | 265 | void ZConsole::clear(ZVariant &retVals, const QList &args) const 266 | { 267 | Q_UNUSED(retVals) 268 | Q_UNUSED(args) 269 | 270 | printf("\033[2J"); 271 | fflush(stdout); 272 | } 273 | 274 | void ZConsole::clearLine(ZVariant &retVals, const QList &args) const 275 | { 276 | Q_UNUSED(retVals) 277 | Q_UNUSED(args) 278 | 279 | printf("\033[K"); 280 | fflush(stdout); 281 | } 282 | 283 | void ZConsole::reset(ZVariant &retVals, const QList &args) const 284 | { 285 | Q_UNUSED(retVals) 286 | Q_UNUSED(args) 287 | 288 | printf("\033[0m"); 289 | fflush(stdout); 290 | } 291 | 292 | void ZConsole::setColor(ZVariant &retVals, const QList &args) const 293 | { 294 | if (args.isEmpty()) 295 | return; 296 | 297 | Q_UNUSED(retVals) 298 | 299 | if (args.count() == 1) { 300 | printf("\033[;%dm", args.first().toInt()); 301 | } else if (args.count() == 2) { 302 | printf("\033[%d;%dm", args.first().toInt(), args.at(1).toInt()); 303 | } else { 304 | printf("\033[%d;%d;%dm", args.first().toInt(), args.at(1).toInt(), args.at(2).toInt()); 305 | } 306 | 307 | fflush(stdout); 308 | } 309 | 310 | void ZConsole::flushInput(ZVariant &retVals, const QList &args) const 311 | { 312 | Q_UNUSED(retVals) 313 | Q_UNUSED(args) 314 | 315 | fflush(stdin); 316 | } 317 | 318 | void ZConsole::flushOutput(ZVariant &retVals, const QList &args) const 319 | { 320 | Q_UNUSED(retVals) 321 | Q_UNUSED(args) 322 | 323 | fflush(stdout); 324 | } 325 | 326 | QString ZConsole::variantToString(const ZVariant &val) const 327 | { 328 | switch (val.type()) { 329 | case ZVariant::Object: 330 | return "[Object:0x" + QString::number((qintptr)val.toObject(), 16) + "]"; 331 | case ZVariant::Function: 332 | return "[Function:0x" + QString::number((qintptr)val.toObject(), 16) + "]";; 333 | case ZVariant::Undefined: 334 | return "undefined"; 335 | case ZVariant::Tuple: { 336 | QString str = "<"; 337 | const ZVariant::ZTuple &tuple = val.toTuple(); 338 | 339 | for(int i = 0; i < tuple.count() - 1; ++i) { 340 | str.append(variantToString(*tuple.value(i))).append(", "); 341 | } 342 | 343 | if(tuple.isEmpty()) 344 | return str.append(">"); 345 | 346 | return str.append(variantToString(*tuple.last())).append(">"); 347 | } 348 | case ZVariant::List: { 349 | QString str = "["; 350 | const QList &list = val.toList(); 351 | 352 | for(int i = 0; i < list.count() - 1; ++i) { 353 | str.append(variantToString(list.value(i))).append(", "); 354 | } 355 | 356 | if(list.isEmpty()) 357 | return str.append("]"); 358 | 359 | return str.append(variantToString(list.last())).append("]"); 360 | } 361 | case ZVariant::Int: 362 | case ZVariant::Double: 363 | return QString::number(val.toDouble()); 364 | default: 365 | return val.toString(); 366 | } 367 | } 368 | 369 | Z_END_NAMESPACE 370 | -------------------------------------------------------------------------------- /common/zvariant.h: -------------------------------------------------------------------------------- 1 | #ifndef ZVARIANT_H 2 | #define ZVARIANT_H 3 | 4 | #include "zglobal.h" 5 | 6 | #include 7 | #include 8 | 9 | Z_BEGIN_NAMESPACE 10 | class ZVariant; 11 | Z_END_NAMESPACE 12 | 13 | QT_BEGIN_NAMESPACE 14 | uint qHash(const ZVariant &val, uint seed = 0); 15 | QT_END_NAMESPACE 16 | 17 | Z_BEGIN_NAMESPACE 18 | 19 | class ZObject; 20 | class ZFunction; 21 | 22 | class ZVariant 23 | { 24 | public: 25 | enum Type { 26 | Int = QMetaType::Int, 27 | Double = QMetaType::Double, 28 | Bool = QMetaType::Bool, 29 | String = QMetaType::QString, 30 | List = QMetaType::QVariantList, 31 | Object = QMetaType::PointerToQObject, 32 | Undefined = QMetaType::UnknownType, 33 | Tuple = QMetaType::User + 1, 34 | Function = QMetaType::User + 2, 35 | Unknow = QMetaType::User + 3 36 | }; 37 | 38 | typedef QList ZTuple; 39 | 40 | ZVariant(Type type = Undefined); 41 | ZVariant(int val); 42 | ZVariant(double val); 43 | ZVariant(bool val); 44 | ZVariant(const char *val); 45 | ZVariant(const ZVariant &other); 46 | ZVariant(ZVariant &&other); 47 | ZVariant(const QString &val); 48 | ZVariant(QLatin1String val); 49 | template 50 | ZVariant(const QList &val); 51 | ZVariant(const QList &val); 52 | ZVariant(const ZTuple &group); 53 | ZVariant(ZObject * const object); 54 | ZVariant(ZFunction * const function); 55 | ZVariant(const QVariant &val); 56 | ~ZVariant(); 57 | 58 | inline bool isObject() const 59 | { 60 | return m_data->type == Object || m_data->type == Function; 61 | } 62 | 63 | const char *typeName() const; 64 | 65 | inline Type type() const 66 | { return m_data->type;} 67 | 68 | int toInt(bool *ok = 0) const; 69 | double toDouble(bool *ok = 0) const; 70 | bool toBool() const; 71 | inline QString toString() const 72 | { return m_data->variant.toString();} 73 | QList toList() const; 74 | inline ZTuple toTuple() const 75 | { if(type() == Tuple) 76 | return qvariant_cast(m_data->variant); 77 | 78 | return ZTuple() << const_cast(this); 79 | } 80 | ZObject *toObject() const; 81 | ZFunction *toFunction() const; 82 | inline QVariant toQVariant() const 83 | { return m_data->variant;} 84 | 85 | virtual void depthCopyAssign(const ZVariant &other) const 86 | { 87 | if(type() == Tuple) { 88 | const ZTuple &tuple = toTuple(); 89 | const ZTuple &other_tuple = other.toTuple(); 90 | 91 | int min = qMin(tuple.count(), other_tuple.count()); 92 | 93 | for(int i = 0; i < min; ++i) { 94 | tuple.at(i)->depthCopyAssign(*other_tuple.at(i)); 95 | } 96 | 97 | return; 98 | } 99 | 100 | VariantData *data = const_cast(this->m_data.constData()); 101 | 102 | if (other.type() == Tuple) { 103 | // 元组类型由于存储的是指针,因此也要深度复制 104 | ZTuple tuple; 105 | 106 | for (const ZVariant *i : other.toTuple()) { 107 | tuple << new ZVariant(*i); 108 | } 109 | 110 | data->variant = QVariant::fromValue(tuple); 111 | } else { 112 | data->variant = other.m_data->variant; 113 | } 114 | 115 | data->type = other.m_data->type; 116 | } 117 | 118 | virtual ZVariant& operator=(const ZVariant &other) 119 | { 120 | if(type() == Tuple) { 121 | const ZTuple &other_group = other.toTuple(); 122 | const ZTuple &this_group = toTuple(); 123 | 124 | int min = qMin(other_group.count(), this_group.count()); 125 | 126 | for(int i = 0; i < min; ++i) { 127 | this_group[i]->m_data = other_group[i]->m_data; 128 | } 129 | } else { 130 | m_data = other.m_data; 131 | } 132 | 133 | return *this; 134 | } 135 | 136 | virtual ZVariant& operator=(ZVariant &&other) 137 | { 138 | if(type() == Tuple) { 139 | const ZTuple &other_group = other.toTuple(); 140 | const ZTuple &this_group = toTuple(); 141 | 142 | int min = qMin(other_group.count(), this_group.count()); 143 | 144 | for(int i = 0; i < min; ++i) { 145 | this_group[i]->m_data.swap(other_group[i]->m_data); 146 | } 147 | } else { 148 | m_data.swap(other.m_data); 149 | } 150 | 151 | return *this; 152 | } 153 | 154 | inline bool operator==(const ZVariant &v) const 155 | { return m_data->variant == v.m_data->variant; } 156 | inline bool operator!=(const ZVariant &v) const 157 | { return m_data->variant != v.m_data->variant; } 158 | inline bool operator<(const ZVariant &v) const 159 | { return m_data->variant < v.m_data->variant; } 160 | inline bool operator<=(const ZVariant &v) const 161 | { return m_data->variant <= v.m_data->variant; } 162 | inline bool operator>(const ZVariant &v) const 163 | { return m_data->variant > v.m_data->variant; } 164 | inline bool operator>=(const ZVariant &v) const 165 | { return m_data->variant >= v.m_data->variant; } 166 | inline bool operator&&(const ZVariant &v) const 167 | { return toBool() && v.toBool();} 168 | inline bool operator||(const ZVariant &v) const 169 | { return toBool() || v.toBool();} 170 | inline bool operator!() const 171 | { return !toBool();} 172 | inline ZVariant operator-() const 173 | { 174 | switch(m_data->type) { 175 | case Double: 176 | return -toDouble(); 177 | case Int: 178 | case Bool: 179 | return -toInt(); 180 | case String: 181 | return toString().toLower(); 182 | default: return Undefined; 183 | } 184 | } 185 | inline ZVariant operator+() const 186 | { 187 | switch(m_data->type) { 188 | case Double: 189 | return qAbs(toDouble()); 190 | case Int: 191 | case Bool: 192 | return qAbs(toInt()); 193 | case String: 194 | return toString().toUpper(); 195 | default: return Undefined; 196 | } 197 | } 198 | inline ZVariant operator<<(const ZVariant &value) 199 | { 200 | switch (m_data.constData()->type) { 201 | case List: 202 | const_cast(m_data.constData())->variant = QVariant::fromValue(toList() += value); 203 | break; 204 | case String: 205 | const_cast(m_data.constData())->variant = toString().append(value.toString()); 206 | break; 207 | default: 208 | break; 209 | } 210 | 211 | return *this; 212 | } 213 | ZVariant operator[](const ZVariant &value) const; 214 | 215 | inline static ZVariant copy(const ZVariant &value) 216 | { 217 | ZVariant val(value.m_data->type); 218 | 219 | val.m_data->variant = value.m_data->variant; 220 | 221 | return val; 222 | } 223 | 224 | friend uint qHash(const ZVariant &val, uint seed); 225 | 226 | private: 227 | class VariantData : public QSharedData 228 | { 229 | public: 230 | ~VariantData() { 231 | if (type == Tuple) { 232 | // 销毁列表中的数据 233 | qDeleteAll(qvariant_cast(variant)); 234 | } 235 | } 236 | 237 | QVariant variant; 238 | ZVariant::Type type; 239 | }; 240 | 241 | QSharedDataPointer m_data; 242 | 243 | friend class ZCode; 244 | 245 | public: 246 | inline const VariantData *data() const 247 | { 248 | return m_data.constData(); 249 | } 250 | 251 | inline VariantData *data() 252 | { 253 | return m_data.data(); 254 | } 255 | }; 256 | 257 | /// int 258 | ZVariant operator +(const int var1, const ZVariant &var2); 259 | ZVariant operator -(const int var1, const ZVariant &var2); 260 | ZVariant operator *(const int var1, const ZVariant &var2); 261 | ZVariant operator /(const int var1, const ZVariant &var2); 262 | ZVariant operator &(const int var1, const ZVariant &var2); 263 | ZVariant operator |(const int var1, const ZVariant &var2); 264 | ZVariant operator ^(const int var1, const ZVariant &var2); 265 | ZVariant operator %(const int var1, const ZVariant &var2); 266 | 267 | /// double 268 | ZVariant operator +(const double &var1, const ZVariant &var2); 269 | ZVariant operator -(const double &var1, const ZVariant &var2); 270 | ZVariant operator *(const double &var1, const ZVariant &var2); 271 | ZVariant operator /(const double &var1, const ZVariant &var2); 272 | 273 | inline ZVariant operator &(const double &var1, const ZVariant &var2) 274 | {return (int)var1 & var2;} 275 | 276 | inline ZVariant operator |(const double &var1, const ZVariant &var2) 277 | {return (int)var1 | var2;} 278 | 279 | inline ZVariant operator ^(const double &var1, const ZVariant &var2) 280 | {return (int)var1 ^ var2;} 281 | 282 | inline ZVariant operator %(const double &var1, const ZVariant &var2) 283 | {return (int)var1 ^ var2;} 284 | 285 | /// string 286 | ZVariant operator +(const QString &var1, const ZVariant &var2); 287 | ZVariant operator -(const QString &var1, const ZVariant &var2); 288 | ZVariant operator *(const QString &var1, const ZVariant &var2); 289 | ZVariant operator /(const QString &var1, const ZVariant &var2); 290 | ZVariant operator &(const QString &var1, const ZVariant &var2); 291 | ZVariant operator |(const QString &var1, const ZVariant &var2); 292 | ZVariant operator ^(const QString &var1, const ZVariant &var2); 293 | ZVariant operator %(const QString &var1, const ZVariant &var2); 294 | 295 | #define OPERATOR(OP) \ 296 | inline ZVariant operator OP (const ZVariant &var1, const ZVariant &var2)\ 297 | {\ 298 | switch(var1.type()) {\ 299 | case ZVariant::Int:\ 300 | return var1.toInt() OP var2;\ 301 | case ZVariant::Double:\ 302 | return var1.toDouble() OP var2;\ 303 | case ZVariant::String:\ 304 | return var1.toString() OP var2;\ 305 | case ZVariant::Bool:\ 306 | return (int)var1.toBool() OP var2;\ 307 | default: break;\ 308 | }\ 309 | return ZVariant::Undefined;\ 310 | } 311 | 312 | #define OPERATOR_ASS(OP) \ 313 | inline ZVariant &operator OP##=(ZVariant &var1, const ZVariant &var2)\ 314 | {return var1 = var1 OP var2;} 315 | 316 | OPERATOR(+) 317 | OPERATOR(-) 318 | OPERATOR(*) 319 | OPERATOR(/) 320 | OPERATOR(&) 321 | OPERATOR(|) 322 | OPERATOR(^) 323 | OPERATOR(%) 324 | 325 | OPERATOR_ASS(+) 326 | OPERATOR_ASS(-) 327 | OPERATOR_ASS(*) 328 | OPERATOR_ASS(/) 329 | OPERATOR_ASS(&) 330 | OPERATOR_ASS(|) 331 | OPERATOR_ASS(^) 332 | OPERATOR_ASS(%) 333 | 334 | inline ZVariant &operator ++(ZVariant &var, int) 335 | {return var = 1 + var;} 336 | 337 | inline ZVariant &operator --(ZVariant &var, int) 338 | {return var = -1 + var;} 339 | 340 | inline ZVariant &operator ++(ZVariant &var) 341 | {return var = 1 + var;} 342 | 343 | inline ZVariant &operator --(ZVariant &var) 344 | {return var = -1 + var;} 345 | 346 | ZVariant operator ~(const ZVariant &var); 347 | 348 | class ZSharedVariant : public ZVariant, public QSharedData 349 | { 350 | public: 351 | inline ZSharedVariant(Type type = Undefined) 352 | : ZVariant(type), QSharedData(){} 353 | inline ZSharedVariant(const ZSharedVariant& other) 354 | : ZVariant(other), QSharedData(other){} 355 | inline ZSharedVariant(ZSharedVariant &&other) 356 | : ZVariant(other), QSharedData(other){} 357 | inline ZSharedVariant(const ZVariant &variant) 358 | : ZVariant(variant), QSharedData(){} 359 | inline ZSharedVariant(ZVariant &&variant) 360 | : ZVariant(variant), QSharedData(){} 361 | 362 | inline ZSharedVariant& operator =(const ZSharedVariant &other) 363 | { ZVariant::operator =(other); return *this;} 364 | inline ZSharedVariant& operator =(ZSharedVariant &&other) 365 | { ZVariant::operator =(other); return *this;} 366 | inline ZSharedVariant& operator =(const ZVariant &other) 367 | { ZVariant::operator =(other); return *this;} 368 | inline ZSharedVariant& operator =(ZVariant &&other) 369 | { ZVariant::operator =(other); return *this;} 370 | }; 371 | 372 | Z_END_NAMESPACE 373 | 374 | QT_BEGIN_NAMESPACE 375 | QDebug operator<<(QDebug deg, const ZVariant &var); 376 | QT_END_NAMESPACE 377 | 378 | Q_DECLARE_METATYPE(ZVariant) 379 | Q_DECLARE_METATYPE(ZVariant::ZTuple) 380 | 381 | #endif // ZVARIANT_H 382 | -------------------------------------------------------------------------------- /common/zcode.h: -------------------------------------------------------------------------------- 1 | #ifndef ZCODE_H 2 | #define ZCODE_H 3 | 4 | #include "zvariant.h" 5 | 6 | #include 7 | 8 | class yyFlexLexer; 9 | 10 | namespace yy { 11 | class parser; 12 | } 13 | 14 | typedef yyFlexLexer YYFlexLexer; 15 | typedef yy::parser YYParser; 16 | typedef QExplicitlySharedDataPointer ZSharedVariantPointer; 17 | 18 | Z_BEGIN_NAMESPACE 19 | 20 | struct ValueCode; 21 | struct ZCode 22 | { 23 | enum Action 24 | { 25 | LeftAssign, // = 0 26 | RightAssign, // = 1 27 | Add, // + 2 28 | Sub, // - 3 29 | Mul, // * 4 30 | Div, // / 5 31 | Abs, // + 6 32 | Minus, // - 7 33 | And, // & 8 34 | Or, // | 9 35 | Xor, // ^ 10 36 | Contrary, // ~ 10 37 | Mod, // % 12 38 | Not, // ! 13 39 | AddAssign, // += 14 40 | SubAssign, // -= 15 41 | MulAssign, // *= 16 42 | DivAssign, // /= 17 43 | AndAssign, // &= 18 44 | OrAssign, // |= 19 45 | XorAssign, // ^= 20 46 | ModAssign, // %= 21 47 | NotAssign, // != 22 remove 48 | Less, // < 23 49 | Greater, // > 24 50 | New, // new 25 51 | Delete, // delete 26 52 | Throw, // throw 27 53 | EQ, // == 28 54 | STEQ, // === 29 55 | NEQ, // != 30 56 | STNEQ, // !== 31 57 | LE, // <= 32 58 | GE, // >= 33 59 | LAnd, // && 34 60 | LOr, // || 35 61 | LAndAssign, // &&= 36 62 | LOrAssign, // ||= 37 63 | PrefixAddSelf, // ++ 38 64 | PostfixAddSelf, // ++ 39 65 | PrefixSubSelf, // -- 40 66 | PostfixSubSelf, // -- 41 67 | Get, // . 42 68 | JoinToTuple, // join 43 join to tuple 69 | JoinToList, // join 44 join to list 70 | Call, // () 45 71 | Push, // push target value to stack 46 72 | Pop, // pop stack 47 73 | PopAll, // clear stack 48 74 | Goto, // goto code index 49 75 | If, // if 50 76 | Children, // get children(X[]) 51 77 | Append, // << add children to last 52 78 | Switch, // switch 53 79 | InitObjectProperty, // init object property 54 80 | Unknow // 55 81 | }; 82 | 83 | static QString actionName(quint8 action); 84 | 85 | static ZVariant exec(const QList &codeList); 86 | 87 | quint8 action = Unknow; 88 | 89 | static QStack virtualStack; 90 | 91 | inline bool isValueCode() const 92 | {return action == Push || action == Goto || action == If || action == Switch;} 93 | 94 | inline const ValueCode *toValueCode() const; 95 | inline ValueCode *toValueCode(); 96 | }; 97 | 98 | struct ValueCode : public ZCode 99 | { 100 | ZSharedVariantPointer value; 101 | }; 102 | 103 | const ValueCode *ZCode::toValueCode() const 104 | { return static_cast(this);} 105 | ValueCode *ZCode::toValueCode() 106 | { return static_cast(this);} 107 | 108 | class ZCodeExecuter 109 | { 110 | public: 111 | ~ZCodeExecuter(); 112 | 113 | struct LoopStructureCodeBlock; 114 | struct CodeBlock{ 115 | enum Type { 116 | Normal = 0x01, 117 | Function = 0x02, 118 | While = 0x04, 119 | NormalFor = 0x08, 120 | LoopStructure = While | NormalFor, 121 | If = 0x10, 122 | Switch = 0x20 123 | }; 124 | 125 | /// 代码块第一条指令的index 126 | int beginCodeIndex; 127 | 128 | Type type = Normal; 129 | CodeBlock *parent = Q_NULLPTR; 130 | 131 | QMap identifiers; 132 | QMap undefinedIdentifier; 133 | 134 | /// 临时指令列表 135 | QList tmpCodeList; 136 | 137 | /// 执行break语句时要goto到的指令的位置 138 | ZSharedVariantPointer breakIndex; 139 | 140 | CodeBlock() { 141 | breakIndex = new ZSharedVariant(); 142 | } 143 | 144 | inline bool isLoopStructure() const 145 | { return (type | LoopStructure) == LoopStructure;} 146 | 147 | inline const LoopStructureCodeBlock *toLoopStructureCodeBlock() const 148 | { return static_cast(this);} 149 | inline LoopStructureCodeBlock *toLoopStructureCodeBlock() 150 | { return static_cast(this);} 151 | }; 152 | 153 | /// 循环结构的代码块 154 | struct LoopStructureCodeBlock : public CodeBlock { 155 | LoopStructureCodeBlock() 156 | : CodeBlock() { 157 | continueIndex = new ZSharedVariant(); 158 | } 159 | 160 | /// 循环中的if指令的index 161 | int ifInstructionIndex; 162 | /// 执行containue语句时要goto到的指令的位置 163 | ZSharedVariantPointer continueIndex; 164 | }; 165 | 166 | inline static void registerIdentifier(const QByteArray &name, ZSharedVariant *variant) 167 | {globalIdentifierHash[name] = variant;} 168 | inline static void registerFunction(ZVariant::Type type, const QByteArray &name, ZFunction *function) 169 | { 170 | QHash &hash = globalFunctionHash[type]; 171 | 172 | hash[name] = function; 173 | } 174 | inline static ZFunction *getFunctionForVariantType(ZVariant::Type type, const QByteArray &name) 175 | { 176 | const QHash &hash = globalFunctionHash.value(type); 177 | 178 | return hash.value(name); 179 | } 180 | 181 | /// from stdin get code 182 | int eval(std::istream &s); 183 | int eval(const char *fileName, bool *ok = 0); 184 | int eval(const QByteArray &code); 185 | 186 | inline ZVariant exec() 187 | { return ZCode::exec(codeList);} 188 | 189 | ZSharedVariantPointer getIdentifier(const QByteArray &name); 190 | 191 | static ZSharedVariant *createConstant(const QByteArray &value, ZVariant::Type type); 192 | 193 | static inline ZSharedVariant *createConstantByValue(const ZVariant &value) 194 | { return createConstant(value.toString().toLatin1(), value.type());} 195 | 196 | inline void appendCode(const ZCode::Action &action) 197 | {if(enableTmpCodeList) currentCodeBlock->tmpCodeList << createCode(action, ZSharedVariantPointer()); 198 | else codeList << createCode(action, ZSharedVariantPointer());} 199 | 200 | inline void appendCode(const ZCode::Action &action, ZSharedVariant *val) 201 | { if(enableTmpCodeList) currentCodeBlock->tmpCodeList << createCode(action, ZSharedVariantPointer(val)); 202 | else codeList << createCode(action, ZSharedVariantPointer(val));} 203 | 204 | inline void appendCode(const ZCode::Action &action, const ZSharedVariantPointer &val) 205 | { if(enableTmpCodeList) currentCodeBlock->tmpCodeList << createCode(action, val); 206 | else codeList << createCode(action, val);} 207 | 208 | inline ZSharedVariant *getGotoLabel(const QByteArray &name) 209 | { 210 | ZSharedVariant *val = gotoLabelMap.value(name); 211 | 212 | if(!val) { 213 | val = new ZSharedVariant(); 214 | 215 | gotoLabelMap[name] = val; 216 | } 217 | 218 | return val; 219 | } 220 | 221 | inline QList &getCodeList() 222 | { return codeList;} 223 | 224 | inline QList &getTmpCodeList() 225 | { return currentCodeBlock->tmpCodeList;} 226 | 227 | inline ZSharedVariant *addIdentifier(const QByteArray &name) 228 | { 229 | ZSharedVariantPointer val = currentCodeBlock->undefinedIdentifier.take(name); 230 | 231 | if(!val) { 232 | val = new ZSharedVariant(); 233 | } 234 | 235 | addIdentifier(name, val); 236 | 237 | return val.data(); 238 | } 239 | 240 | inline void addIdentifier(const QByteArray &name, const ZSharedVariantPointer &val) 241 | { 242 | if(currentCodeBlock->identifiers.contains(name)) { 243 | zWarning << "Symbol has been defined:" << name; 244 | 245 | return; 246 | } 247 | 248 | currentCodeBlock->identifiers[name] = val; 249 | } 250 | 251 | static ZSharedVariantPointer createFunction(ZCodeExecuter *executer); 252 | 253 | inline CodeBlock *getCodeBlock() const 254 | { return currentCodeBlock;} 255 | 256 | inline CodeBlock *getCodeBlockByType(CodeBlock::Type type, CodeBlock *startBlock) const 257 | { 258 | if (!startBlock) 259 | return startBlock; 260 | 261 | CodeBlock *block = startBlock; 262 | 263 | while (block) { 264 | // 无breakIndex的block认为是无效的,可忽略的 265 | if (block->breakIndex && (block->type | type) == type) { 266 | return block; 267 | } 268 | 269 | block = block->parent; 270 | } 271 | 272 | return block; 273 | } 274 | 275 | inline QVector &getParameterList() 276 | { return parameterList;} 277 | 278 | void beginCodeBlock(CodeBlock::Type type = CodeBlock::Normal); 279 | void endCodeBlock(); 280 | 281 | /// 设置是否将指令保存到临时列表(tmpCodeList) 282 | inline void setEnableTmpCodeList(bool enable) 283 | { enableTmpCodeList = enable;} 284 | 285 | static ZCodeExecuter *beginCodeExecuter(); 286 | static ZCodeExecuter *endCodeExecuter(); 287 | 288 | static ZCodeExecuter *currentCodeExecuter; 289 | static YYFlexLexer *yyFlexLexer; 290 | 291 | private: 292 | ZCodeExecuter(); 293 | 294 | ZCode *createCode(const ZCode::Action &action, const ZSharedVariantPointer &val); 295 | 296 | inline void deleteAllCodeBlock() 297 | { 298 | for (int i = 0; i < codeBlockList.count(); ++i) { 299 | CodeBlock *block = codeBlockList.at(i); 300 | 301 | if (block->isLoopStructure()) { 302 | delete block->toLoopStructureCodeBlock(); 303 | } else { 304 | delete block; 305 | } 306 | } 307 | 308 | codeBlockList.clear(); 309 | } 310 | 311 | inline void deleteAllCode() 312 | { 313 | for(int i = 0; i < codeList.count(); ++i) { 314 | ZCode *code = codeList.at(i); 315 | 316 | if(code->isValueCode()) { 317 | delete code->toValueCode(); 318 | } else { 319 | delete code; 320 | } 321 | } 322 | 323 | codeList.clear(); 324 | } 325 | 326 | ZCodeExecuter *parent = Q_NULLPTR; 327 | 328 | /// 指令列表 329 | QList codeList; 330 | 331 | /// 是否启用临时指令列表 332 | bool enableTmpCodeList = false; 333 | 334 | CodeBlock *currentCodeBlock = Q_NULLPTR; 335 | QList codeBlockList; 336 | QMap gotoLabelMap; 337 | /// function object parameter tmp list 338 | QVector parameterList; 339 | 340 | /// 储存标识符对应的全局对象 341 | static QHash globalIdentifierHash; 342 | /// 存储标识符对应的全局函数(用于处理特定数据类型的函数) 343 | static QHash> globalFunctionHash; 344 | static QMap stringConstantMap; 345 | static QMap numberConstantMap; 346 | static ZVariant constTrue; 347 | static ZVariant constFalse; 348 | static ZVariant constUndefined; 349 | 350 | friend class ZUserFunction; 351 | friend class ZCode; 352 | }; 353 | 354 | Z_END_NAMESPACE 355 | 356 | QT_BEGIN_NAMESPACE 357 | Q_CORE_EXPORT QDebug operator<<(QDebug deg, const ZCode &var); 358 | QT_END_NAMESPACE 359 | 360 | #endif // ZCODE_H 361 | -------------------------------------------------------------------------------- /base/zbase.cpp: -------------------------------------------------------------------------------- 1 | #include "zbase.h" 2 | #include "zcode.h" 3 | #include "zconsole.h" 4 | #include "zsystem.h" 5 | 6 | #include 7 | 8 | #define TYPE_TRANSITION(Type)\ 9 | class Z##Type : public ZFunction\ 10 | {\ 11 | public:\ 12 | explicit Z##Type(ZObject *parent = 0)\ 13 | : ZFunction(parent)\ 14 | {}\ 15 | ZVariant call(const QList &args) const Q_DECL_OVERRIDE\ 16 | {\ 17 | if (args.isEmpty())\ 18 | return ZVariant::Undefined;\ 19 | return args.first().to##Type();\ 20 | }\ 21 | }; 22 | 23 | #define REGISTER_FUNCTION(Type, Fun) {\ 24 | const QList list = QString(#Fun).split("::");\ 25 | if (list.count() == 2)\ 26 | ZCodeExecuter::registerFunction(Type, list.last().toLatin1(), new ZMethod(&Fun));\ 27 | else\ 28 | ZCodeExecuter::registerFunction(Type, #Fun, new ZMethod(&Fun));} 29 | 30 | namespace ZBase { 31 | 32 | TYPE_TRANSITION(Int) 33 | TYPE_TRANSITION(Double) 34 | TYPE_TRANSITION(Bool) 35 | TYPE_TRANSITION(String) 36 | 37 | namespace String { 38 | ZVariant toInt(const QList &args) 39 | { 40 | ZVariant::ZTuple retVals; 41 | 42 | bool ok; 43 | 44 | int base = 10; 45 | 46 | if (args.count() > 1) { 47 | base = args.at(1).toInt(&ok); 48 | 49 | if (!ok) 50 | base = 10; 51 | } 52 | 53 | retVals << new ZVariant(args.first().toString().toInt(&ok, base)); 54 | retVals << new ZVariant(ok); 55 | 56 | return retVals; 57 | } 58 | 59 | ZVariant append(const QList &args) 60 | { 61 | QString string = args.first().toString(); 62 | 63 | for (int i = 1; i < args.count(); ++i) 64 | string.append(args.at(i).toString()); 65 | 66 | args.first().depthCopyAssign(string); 67 | 68 | return args.first(); 69 | } 70 | 71 | ZVariant at(const QList &args) 72 | { 73 | if (args.count() < 2) 74 | return ZVariant(); 75 | 76 | return QString(args.first().toString().at(args.at(1).toInt())); 77 | } 78 | 79 | ZVariant contains(const QList &args) 80 | { 81 | if (args.count() < 2) 82 | return ZVariant(); 83 | 84 | const ZVariant &variant = args.first(); 85 | 86 | return variant.toString().contains(args.at(1).toString()); 87 | } 88 | 89 | ZVariant count(const QList &args) 90 | { 91 | return args.first().toString().count(); 92 | } 93 | 94 | ZVariant endsWith(const QList &args) 95 | { 96 | if (args.count() < 2) 97 | return ZVariant(); 98 | 99 | return args.first().toString().endsWith(args.at(1).toString()); 100 | } 101 | 102 | ZVariant indexOf(const QList &args) 103 | { 104 | if (args.count() < 2) 105 | return ZVariant(); 106 | 107 | const ZVariant &variant = args.first(); 108 | 109 | return variant.toString().indexOf(args.at(1).toString()); 110 | } 111 | 112 | ZVariant insert(const QList &args) 113 | { 114 | if (args.count() < 3) 115 | return ZVariant(); 116 | 117 | ZVariant variant = args.first(); 118 | 119 | variant.depthCopyAssign(variant.toString().insert(args.at(1).toInt(), args.at(2).toString())); 120 | 121 | return args.first(); 122 | } 123 | 124 | ZVariant isEmpty(const QList &args) 125 | { 126 | return args.first().toString().isEmpty(); 127 | } 128 | 129 | ZVariant isNull(const QList &args) 130 | { 131 | return args.first().toString().isNull(); 132 | } 133 | 134 | ZVariant lastIndexOf(const QList &args) 135 | { 136 | if (args.count() < 2) 137 | return ZVariant(); 138 | 139 | return args.first().toString().lastIndexOf(args.at(1).toString()); 140 | } 141 | 142 | ZVariant left(const QList &args) 143 | { 144 | if (args.count() < 2) 145 | return ZVariant(); 146 | 147 | return args.first().toString().left(args.at(1).toInt()); 148 | } 149 | 150 | ZVariant length(const QList &args) 151 | { 152 | return args.first().toString().length(); 153 | } 154 | 155 | ZVariant mid(const QList &args) 156 | { 157 | if (args.count() == 2) 158 | return args.first().toString().mid(args.at(1).toInt()); 159 | else if (args.count() > 2) 160 | return args.first().toString().mid(args.at(1).toInt(), args.at(2).toInt()); 161 | 162 | return ZVariant(); 163 | } 164 | 165 | ZVariant prepend(const QList &args) 166 | { 167 | if (args.count() < 2) 168 | return ZVariant(); 169 | 170 | QString string = args.first().toString(); 171 | 172 | string.prepend(args.at(1).toString()); 173 | 174 | args.first().depthCopyAssign(string); 175 | 176 | return args.first(); 177 | } 178 | 179 | ZVariant remove(const QList &args) 180 | { 181 | QString string = args.first().toString(); 182 | 183 | if (args.count() == 2) 184 | string.remove(args.at(1).toString()); 185 | else if (args.count() > 2) 186 | string.remove(args.at(1).toInt(), args.at(2).toInt()); 187 | 188 | args.first().depthCopyAssign(string); 189 | 190 | return args.first(); 191 | } 192 | 193 | ZVariant replace(const QList &args) 194 | { 195 | QString string = args.first().toString(); 196 | 197 | if (args.count() == 3) 198 | string.replace(args.at(1).toString(), args.at(2).toString()); 199 | else if (args.count() > 3) 200 | string.replace(args.at(1).toInt(), args.at(2).toInt(), args.at(3).toString()); 201 | 202 | args.first().depthCopyAssign(string); 203 | 204 | return args.first(); 205 | } 206 | 207 | ZVariant right(const QList &args) 208 | { 209 | if (args.count() < 2) 210 | return ZVariant(); 211 | 212 | return args.first().toString().right(args.at(1).toInt()); 213 | } 214 | 215 | ZVariant split(const QList &args) 216 | { 217 | if (args.count() < 2) 218 | return ZVariant(); 219 | 220 | QList list; 221 | 222 | for (const QString &str : args.first().toString().split(args.at(1).toString())) { 223 | list << str; 224 | } 225 | 226 | return list; 227 | } 228 | 229 | ZVariant startsWith(const QList &args) 230 | { 231 | if (args.count() < 2) 232 | return ZVariant(); 233 | 234 | return args.first().toString().startsWith(args.at(1).toString()); 235 | } 236 | }// end namespace String 237 | 238 | namespace List { 239 | ZVariant append(const QList &args) 240 | { 241 | QList list = args.first().toList(); 242 | 243 | for (int i = 1; i < args.count(); ++i) 244 | list.append(args.at(i)); 245 | 246 | args.first().depthCopyAssign(list); 247 | 248 | return ZVariant(); 249 | } 250 | 251 | ZVariant at(const QList &args) 252 | { 253 | if (args.count() < 2) 254 | return ZVariant(); 255 | 256 | return args.first().toList().at(args.at(1).toInt()); 257 | } 258 | 259 | ZVariant contains(const QList &args) 260 | { 261 | if (args.count() < 2) 262 | return ZVariant(); 263 | 264 | const ZVariant &variant = args.first(); 265 | 266 | return variant.toList().contains(args.at(1)); 267 | } 268 | 269 | ZVariant count(const QList &args) 270 | { 271 | return args.first().toList().count(); 272 | } 273 | 274 | ZVariant indexOf(const QList &args) 275 | { 276 | if (args.count() < 2) 277 | return ZVariant(); 278 | 279 | const ZVariant &variant = args.first(); 280 | 281 | return variant.toList().indexOf(args.at(1)); 282 | } 283 | 284 | ZVariant insert(const QList &args) 285 | { 286 | if (args.count() > 2) { 287 | QList list = args.first().toList(); 288 | 289 | list.insert(args.at(1).toInt(), args.at(2)); 290 | args.first().depthCopyAssign(list); 291 | } 292 | 293 | return ZVariant(); 294 | } 295 | 296 | ZVariant isEmpty(const QList &args) 297 | { 298 | return args.first().toList().isEmpty(); 299 | } 300 | 301 | ZVariant lastIndexOf(const QList &args) 302 | { 303 | if (args.count() < 2) 304 | return ZVariant(); 305 | 306 | return args.first().toList().lastIndexOf(args.at(1)); 307 | } 308 | 309 | ZVariant length(const QList &args) 310 | { 311 | return args.first().toList().length(); 312 | } 313 | 314 | ZVariant mid(const QList &args) 315 | { 316 | if (args.count() < 3) 317 | return ZVariant(); 318 | 319 | return args.first().toList().mid(args.at(1).toInt(), args.at(2).toInt()); 320 | } 321 | 322 | ZVariant prepend(const QList &args) 323 | { 324 | if (args.count() > 1) { 325 | QList list = args.first().toList(); 326 | 327 | list.prepend(args.at(1)); 328 | args.first().depthCopyAssign(list); 329 | } 330 | 331 | return args.first(); 332 | } 333 | 334 | ZVariant removeAll(const QList &args) 335 | { 336 | if (args.count() > 1) { 337 | QList list = args.first().toList(); 338 | 339 | list.removeAll(args.at(1)); 340 | args.first().depthCopyAssign(list); 341 | } 342 | 343 | return args.first(); 344 | } 345 | 346 | ZVariant removeAt(const QList &args) 347 | { 348 | if (args.count() > 1) { 349 | QList list = args.first().toList(); 350 | 351 | list.removeAt(args.at(1).toInt()); 352 | args.first().depthCopyAssign(list); 353 | } 354 | 355 | return args.first(); 356 | } 357 | 358 | ZVariant removeOne(const QList &args) 359 | { 360 | if (args.count() > 1) { 361 | QList list = args.first().toList(); 362 | 363 | list.removeOne(args.at(1)); 364 | args.first().depthCopyAssign(list); 365 | } 366 | 367 | return args.first(); 368 | } 369 | 370 | ZVariant replace(const QList &args) 371 | { 372 | if (args.count() > 2) { 373 | QList list = args.first().toList(); 374 | 375 | list.replace(args.at(1).toInt(), args.at(2)); 376 | args.first().depthCopyAssign(list); 377 | } 378 | 379 | return ZVariant(); 380 | } 381 | 382 | ZVariant join(const QList &args) 383 | { 384 | if (args.count() < 2) 385 | return ZVariant(); 386 | 387 | QString string; 388 | const QString separator = args.at(1).toString(); 389 | 390 | for (const ZVariant &item : args.first().toList()) { 391 | string.append(separator).append(item.toString()); 392 | } 393 | 394 | return string.mid(separator.count()); 395 | } 396 | 397 | ZVariant clear(const QList &args) 398 | { 399 | QList list = args.first().toList(); 400 | 401 | list.clear(); 402 | args.first().depthCopyAssign(list); 403 | 404 | return ZVariant(); 405 | } 406 | 407 | ZVariant last(const QList &args) 408 | { 409 | return args.first().toList().last(); 410 | } 411 | 412 | ZVariant first(const QList &args) 413 | { 414 | return args.first().toList().first(); 415 | } 416 | }// end namespace List 417 | 418 | void init() 419 | { 420 | ZCodeExecuter::registerIdentifier("console", new ZSharedVariant(new ZConsole)); 421 | ZCodeExecuter::registerIdentifier("sys", new ZSharedVariant(new ZSystem)); 422 | ZCodeExecuter::registerIdentifier("int", new ZSharedVariant(new ZInt)); 423 | ZCodeExecuter::registerIdentifier("double", new ZSharedVariant(new ZDouble)); 424 | ZCodeExecuter::registerIdentifier("bool", new ZSharedVariant(new ZBool)); 425 | ZCodeExecuter::registerIdentifier("string", new ZSharedVariant(new ZString)); 426 | 427 | REGISTER_FUNCTION(ZVariant::String, String::toInt); 428 | REGISTER_FUNCTION(ZVariant::String, String::append); 429 | REGISTER_FUNCTION(ZVariant::String, String::at); 430 | REGISTER_FUNCTION(ZVariant::String, String::contains); 431 | REGISTER_FUNCTION(ZVariant::String, String::count); 432 | REGISTER_FUNCTION(ZVariant::String, String::endsWith); 433 | REGISTER_FUNCTION(ZVariant::String, String::indexOf); 434 | REGISTER_FUNCTION(ZVariant::String, String::insert); 435 | REGISTER_FUNCTION(ZVariant::String, String::isEmpty); 436 | REGISTER_FUNCTION(ZVariant::String, String::isNull); 437 | REGISTER_FUNCTION(ZVariant::String, String::lastIndexOf); 438 | REGISTER_FUNCTION(ZVariant::String, String::left); 439 | REGISTER_FUNCTION(ZVariant::String, String::length); 440 | REGISTER_FUNCTION(ZVariant::String, String::mid); 441 | REGISTER_FUNCTION(ZVariant::String, String::prepend); 442 | REGISTER_FUNCTION(ZVariant::String, String::remove); 443 | REGISTER_FUNCTION(ZVariant::String, String::replace); 444 | REGISTER_FUNCTION(ZVariant::String, String::right); 445 | REGISTER_FUNCTION(ZVariant::String, String::split); 446 | REGISTER_FUNCTION(ZVariant::String, String::startsWith); 447 | 448 | REGISTER_FUNCTION(ZVariant::List, List::append); 449 | REGISTER_FUNCTION(ZVariant::List, List::at); 450 | REGISTER_FUNCTION(ZVariant::List, List::contains); 451 | REGISTER_FUNCTION(ZVariant::List, List::count); 452 | REGISTER_FUNCTION(ZVariant::List, List::indexOf); 453 | REGISTER_FUNCTION(ZVariant::List, List::insert); 454 | REGISTER_FUNCTION(ZVariant::List, List::isEmpty); 455 | REGISTER_FUNCTION(ZVariant::List, List::lastIndexOf); 456 | REGISTER_FUNCTION(ZVariant::List, List::length); 457 | REGISTER_FUNCTION(ZVariant::List, List::mid); 458 | REGISTER_FUNCTION(ZVariant::List, List::prepend); 459 | REGISTER_FUNCTION(ZVariant::List, List::removeAll); 460 | REGISTER_FUNCTION(ZVariant::List, List::removeAt); 461 | REGISTER_FUNCTION(ZVariant::List, List::removeOne); 462 | REGISTER_FUNCTION(ZVariant::List, List::replace); 463 | REGISTER_FUNCTION(ZVariant::List, List::join); 464 | REGISTER_FUNCTION(ZVariant::List, List::clear); 465 | REGISTER_FUNCTION(ZVariant::List, List::last); 466 | REGISTER_FUNCTION(ZVariant::List, List::first); 467 | } 468 | }// end namespace ZBase 469 | -------------------------------------------------------------------------------- /syntax/zScript.tab.hpp: -------------------------------------------------------------------------------- 1 | // A Bison parser, made by GNU Bison 3.0.4. 2 | 3 | // Skeleton interface for Bison LALR(1) parsers in C++ 4 | 5 | // Copyright (C) 2002-2015 Free Software Foundation, Inc. 6 | 7 | // This program is free software: you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License as published by 9 | // the Free Software Foundation, either version 3 of the License, or 10 | // (at your option) any later version. 11 | 12 | // This program is distributed in the hope that it will be useful, 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | // GNU General Public License for more details. 16 | 17 | // You should have received a copy of the GNU General Public License 18 | // along with this program. If not, see . 19 | 20 | // As a special exception, you may create a larger work that contains 21 | // part or all of the Bison parser skeleton and distribute that work 22 | // under terms of your choice, so long as that work isn't itself a 23 | // parser generator using the skeleton or a modified version thereof 24 | // as a parser skeleton. Alternatively, if you modify or redistribute 25 | // the parser skeleton itself, you may (at your option) remove this 26 | // special exception, which will cause the skeleton and the resulting 27 | // Bison output files to be licensed under the GNU General Public 28 | // License without this special exception. 29 | 30 | // This special exception was added by the Free Software Foundation in 31 | // version 2.2 of Bison. 32 | 33 | /** 34 | ** \file zScript.tab.hpp 35 | ** Define the yy::parser class. 36 | */ 37 | 38 | // C++ LALR(1) parser skeleton written by Akim Demaille. 39 | 40 | #ifndef YY_YY_ZSCRIPT_TAB_HPP_INCLUDED 41 | # define YY_YY_ZSCRIPT_TAB_HPP_INCLUDED 42 | 43 | 44 | # include // std::abort 45 | # include 46 | # include 47 | # include 48 | # include 49 | # include "stack.hh" 50 | # include "location.hh" 51 | 52 | 53 | #ifndef YY_ATTRIBUTE 54 | # if (defined __GNUC__ \ 55 | && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ 56 | || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C 57 | # define YY_ATTRIBUTE(Spec) __attribute__(Spec) 58 | # else 59 | # define YY_ATTRIBUTE(Spec) /* empty */ 60 | # endif 61 | #endif 62 | 63 | #ifndef YY_ATTRIBUTE_PURE 64 | # define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) 65 | #endif 66 | 67 | #ifndef YY_ATTRIBUTE_UNUSED 68 | # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) 69 | #endif 70 | 71 | #if !defined _Noreturn \ 72 | && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) 73 | # if defined _MSC_VER && 1200 <= _MSC_VER 74 | # define _Noreturn __declspec (noreturn) 75 | # else 76 | # define _Noreturn YY_ATTRIBUTE ((__noreturn__)) 77 | # endif 78 | #endif 79 | 80 | /* Suppress unused-variable warnings by "using" E. */ 81 | #if ! defined lint || defined __GNUC__ 82 | # define YYUSE(E) ((void) (E)) 83 | #else 84 | # define YYUSE(E) /* empty */ 85 | #endif 86 | 87 | #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ 88 | /* Suppress an incorrect diagnostic about yylval being uninitialized. */ 89 | # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ 90 | _Pragma ("GCC diagnostic push") \ 91 | _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ 92 | _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") 93 | # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ 94 | _Pragma ("GCC diagnostic pop") 95 | #else 96 | # define YY_INITIAL_VALUE(Value) Value 97 | #endif 98 | #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN 99 | # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN 100 | # define YY_IGNORE_MAYBE_UNINITIALIZED_END 101 | #endif 102 | #ifndef YY_INITIAL_VALUE 103 | # define YY_INITIAL_VALUE(Value) /* Nothing. */ 104 | #endif 105 | 106 | /* Debug traces. */ 107 | #ifndef YYDEBUG 108 | # define YYDEBUG 1 109 | #endif 110 | 111 | 112 | namespace yy { 113 | #line 114 "zScript.tab.hpp" // lalr1.cc:377 114 | 115 | 116 | 117 | 118 | 119 | /// A Bison parser. 120 | class parser 121 | { 122 | public: 123 | #ifndef YYSTYPE 124 | /// Symbol semantic values. 125 | union semantic_type 126 | { 127 | #line 28 "/mnt/c/Users/zccrs/projects/zScript/syntax/zScript.yy" // lalr1.cc:377 128 | 129 | int valueType; 130 | quint16 count; 131 | QByteArray *identifier; 132 | ZSharedVariantPointer *value; 133 | QVarLengthArray *parameterList; 134 | QPair *caseKey; 135 | QVector> *cases; 136 | std::string *msg; 137 | 138 | #line 139 "zScript.tab.hpp" // lalr1.cc:377 139 | }; 140 | #else 141 | typedef YYSTYPE semantic_type; 142 | #endif 143 | /// Symbol locations. 144 | typedef location location_type; 145 | 146 | /// Syntax errors thrown from user actions. 147 | struct syntax_error : std::runtime_error 148 | { 149 | syntax_error (const location_type& l, const std::string& m); 150 | location_type location; 151 | }; 152 | 153 | /// Tokens. 154 | struct token 155 | { 156 | enum yytokentype 157 | { 158 | VAR = 258, 159 | FUNCTION = 259, 160 | NEW = 260, 161 | DELETE = 261, 162 | THROW = 262, 163 | IF = 263, 164 | ELSE = 264, 165 | WHILE = 265, 166 | FOR = 266, 167 | UNDEFINED = 267, 168 | GOTO = 268, 169 | RETURN = 269, 170 | BREAK = 270, 171 | CONTINUE = 271, 172 | SWITCH = 272, 173 | CASE = 273, 174 | DEFAULT = 274, 175 | IDENTIFIER = 275, 176 | INT = 276, 177 | STRING = 277, 178 | BOOL = 278, 179 | DOUBLE = 279, 180 | EQ = 280, 181 | STEQ = 281, 182 | NEQ = 282, 183 | STNEQ = 283, 184 | LE = 284, 185 | GE = 285, 186 | LAND = 286, 187 | LOR = 287, 188 | ADDSELF = 288, 189 | SUBSELF = 289, 190 | LL = 290, 191 | GG = 291, 192 | DIVASSIGN = 292, 193 | MULASSIGN = 293, 194 | ADDASSIGN = 294, 195 | SUBASSIGN = 295, 196 | MODASSIGN = 296, 197 | ANDASSIGN = 297, 198 | ORASSIGN = 298, 199 | XORASSIGN = 299, 200 | LANDASSIGN = 300, 201 | LORASSIGN = 301, 202 | ERROR = 302, 203 | NEW_OBJ_BEGIN = 303, 204 | COMMA = 304, 205 | LTGT = 305, 206 | UMINUS = 306 207 | }; 208 | }; 209 | 210 | /// (External) token type, as returned by yylex. 211 | typedef token::yytokentype token_type; 212 | 213 | /// Symbol type: an internal symbol number. 214 | typedef int symbol_number_type; 215 | 216 | /// The symbol type number to denote an empty symbol. 217 | enum { empty_symbol = -2 }; 218 | 219 | /// Internal symbol number for tokens (subsumed by symbol_number_type). 220 | typedef unsigned char token_number_type; 221 | 222 | /// A complete symbol. 223 | /// 224 | /// Expects its Base type to provide access to the symbol type 225 | /// via type_get(). 226 | /// 227 | /// Provide access to semantic value and location. 228 | template 229 | struct basic_symbol : Base 230 | { 231 | /// Alias to Base. 232 | typedef Base super_type; 233 | 234 | /// Default constructor. 235 | basic_symbol (); 236 | 237 | /// Copy constructor. 238 | basic_symbol (const basic_symbol& other); 239 | 240 | /// Constructor for valueless symbols. 241 | basic_symbol (typename Base::kind_type t, 242 | const location_type& l); 243 | 244 | /// Constructor for symbols with semantic value. 245 | basic_symbol (typename Base::kind_type t, 246 | const semantic_type& v, 247 | const location_type& l); 248 | 249 | /// Destroy the symbol. 250 | ~basic_symbol (); 251 | 252 | /// Destroy contents, and record that is empty. 253 | void clear (); 254 | 255 | /// Whether empty. 256 | bool empty () const; 257 | 258 | /// Destructive move, \a s is emptied into this. 259 | void move (basic_symbol& s); 260 | 261 | /// The semantic value. 262 | semantic_type value; 263 | 264 | /// The location. 265 | location_type location; 266 | 267 | private: 268 | /// Assignment operator. 269 | basic_symbol& operator= (const basic_symbol& other); 270 | }; 271 | 272 | /// Type access provider for token (enum) based symbols. 273 | struct by_type 274 | { 275 | /// Default constructor. 276 | by_type (); 277 | 278 | /// Copy constructor. 279 | by_type (const by_type& other); 280 | 281 | /// The symbol type as needed by the constructor. 282 | typedef token_type kind_type; 283 | 284 | /// Constructor from (external) token numbers. 285 | by_type (kind_type t); 286 | 287 | /// Record that this symbol is empty. 288 | void clear (); 289 | 290 | /// Steal the symbol type from \a that. 291 | void move (by_type& that); 292 | 293 | /// The (internal) type number (corresponding to \a type). 294 | /// \a empty when empty. 295 | symbol_number_type type_get () const; 296 | 297 | /// The token. 298 | token_type token () const; 299 | 300 | /// The symbol type. 301 | /// \a empty_symbol when empty. 302 | /// An int, not token_number_type, to be able to store empty_symbol. 303 | int type; 304 | }; 305 | 306 | /// "External" symbols: returned by the scanner. 307 | typedef basic_symbol symbol_type; 308 | 309 | 310 | /// Build a parser object. 311 | parser (); 312 | virtual ~parser (); 313 | 314 | /// Parse. 315 | /// \returns 0 iff parsing succeeded. 316 | virtual int parse (); 317 | 318 | #if YYDEBUG 319 | /// The current debugging stream. 320 | std::ostream& debug_stream () const YY_ATTRIBUTE_PURE; 321 | /// Set the current debugging stream. 322 | void set_debug_stream (std::ostream &); 323 | 324 | /// Type for debugging levels. 325 | typedef int debug_level_type; 326 | /// The current debugging level. 327 | debug_level_type debug_level () const YY_ATTRIBUTE_PURE; 328 | /// Set the current debugging level. 329 | void set_debug_level (debug_level_type l); 330 | #endif 331 | 332 | /// Report a syntax error. 333 | /// \param loc where the syntax error is found. 334 | /// \param msg a description of the syntax error. 335 | virtual void error (const location_type& loc, const std::string& msg); 336 | 337 | /// Report a syntax error. 338 | void error (const syntax_error& err); 339 | 340 | private: 341 | /// This class is not copyable. 342 | parser (const parser&); 343 | parser& operator= (const parser&); 344 | 345 | /// State numbers. 346 | typedef int state_type; 347 | 348 | /// Generate an error message. 349 | /// \param yystate the state where the error occurred. 350 | /// \param yyla the lookahead token. 351 | virtual std::string yysyntax_error_ (state_type yystate, 352 | const symbol_type& yyla) const; 353 | 354 | /// Compute post-reduction state. 355 | /// \param yystate the current state 356 | /// \param yysym the nonterminal to push on the stack 357 | state_type yy_lr_goto_state_ (state_type yystate, int yysym); 358 | 359 | /// Whether the given \c yypact_ value indicates a defaulted state. 360 | /// \param yyvalue the value to check 361 | static bool yy_pact_value_is_default_ (int yyvalue); 362 | 363 | /// Whether the given \c yytable_ value indicates a syntax error. 364 | /// \param yyvalue the value to check 365 | static bool yy_table_value_is_error_ (int yyvalue); 366 | 367 | static const signed char yypact_ninf_; 368 | static const signed char yytable_ninf_; 369 | 370 | /// Convert a scanner token number \a t to a symbol number. 371 | static token_number_type yytranslate_ (int t); 372 | 373 | // Tables. 374 | // YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing 375 | // STATE-NUM. 376 | static const short int yypact_[]; 377 | 378 | // YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. 379 | // Performed when YYTABLE does not specify something else to do. Zero 380 | // means the default is an error. 381 | static const unsigned char yydefact_[]; 382 | 383 | // YYPGOTO[NTERM-NUM]. 384 | static const signed char yypgoto_[]; 385 | 386 | // YYDEFGOTO[NTERM-NUM]. 387 | static const short int yydefgoto_[]; 388 | 389 | // YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If 390 | // positive, shift that token. If negative, reduce the rule whose 391 | // number is the opposite. If YYTABLE_NINF, syntax error. 392 | static const short int yytable_[]; 393 | 394 | static const short int yycheck_[]; 395 | 396 | // YYSTOS[STATE-NUM] -- The (internal number of the) accessing 397 | // symbol of state STATE-NUM. 398 | static const unsigned char yystos_[]; 399 | 400 | // YYR1[YYN] -- Symbol number of symbol that rule YYN derives. 401 | static const unsigned char yyr1_[]; 402 | 403 | // YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. 404 | static const unsigned char yyr2_[]; 405 | 406 | 407 | /// Convert the symbol name \a n to a form suitable for a diagnostic. 408 | static std::string yytnamerr_ (const char *n); 409 | 410 | 411 | /// For a symbol, its name in clear. 412 | static const char* const yytname_[]; 413 | #if YYDEBUG 414 | // YYRLINE[YYN] -- Source line where rule number YYN was defined. 415 | static const unsigned short int yyrline_[]; 416 | /// Report on the debug stream that the rule \a r is going to be reduced. 417 | virtual void yy_reduce_print_ (int r); 418 | /// Print the state stack on the debug stream. 419 | virtual void yystack_print_ (); 420 | 421 | // Debugging. 422 | int yydebug_; 423 | std::ostream* yycdebug_; 424 | 425 | /// \brief Display a symbol type, value and location. 426 | /// \param yyo The output stream. 427 | /// \param yysym The symbol. 428 | template 429 | void yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const; 430 | #endif 431 | 432 | /// \brief Reclaim the memory associated to a symbol. 433 | /// \param yymsg Why this token is reclaimed. 434 | /// If null, print nothing. 435 | /// \param yysym The symbol. 436 | template 437 | void yy_destroy_ (const char* yymsg, basic_symbol& yysym) const; 438 | 439 | private: 440 | /// Type access provider for state based symbols. 441 | struct by_state 442 | { 443 | /// Default constructor. 444 | by_state (); 445 | 446 | /// The symbol type as needed by the constructor. 447 | typedef state_type kind_type; 448 | 449 | /// Constructor. 450 | by_state (kind_type s); 451 | 452 | /// Copy constructor. 453 | by_state (const by_state& other); 454 | 455 | /// Record that this symbol is empty. 456 | void clear (); 457 | 458 | /// Steal the symbol type from \a that. 459 | void move (by_state& that); 460 | 461 | /// The (internal) type number (corresponding to \a state). 462 | /// \a empty_symbol when empty. 463 | symbol_number_type type_get () const; 464 | 465 | /// The state number used to denote an empty symbol. 466 | enum { empty_state = -1 }; 467 | 468 | /// The state. 469 | /// \a empty when empty. 470 | state_type state; 471 | }; 472 | 473 | /// "Internal" symbol: element of the stack. 474 | struct stack_symbol_type : basic_symbol 475 | { 476 | /// Superclass. 477 | typedef basic_symbol super_type; 478 | /// Construct an empty symbol. 479 | stack_symbol_type (); 480 | /// Steal the contents from \a sym to build this. 481 | stack_symbol_type (state_type s, symbol_type& sym); 482 | /// Assignment, needed by push_back. 483 | stack_symbol_type& operator= (const stack_symbol_type& that); 484 | }; 485 | 486 | /// Stack type. 487 | typedef stack stack_type; 488 | 489 | /// The stack. 490 | stack_type yystack_; 491 | 492 | /// Push a new state on the stack. 493 | /// \param m a debug message to display 494 | /// if null, no trace is output. 495 | /// \param s the symbol 496 | /// \warning the contents of \a s.value is stolen. 497 | void yypush_ (const char* m, stack_symbol_type& s); 498 | 499 | /// Push a new look ahead token on the state on the stack. 500 | /// \param m a debug message to display 501 | /// if null, no trace is output. 502 | /// \param s the state 503 | /// \param sym the symbol (for its value and location). 504 | /// \warning the contents of \a s.value is stolen. 505 | void yypush_ (const char* m, state_type s, symbol_type& sym); 506 | 507 | /// Pop \a n symbols the three stacks. 508 | void yypop_ (unsigned int n = 1); 509 | 510 | /// Constants. 511 | enum 512 | { 513 | yyeof_ = 0, 514 | yylast_ = 967, ///< Last index in yytable_. 515 | yynnts_ = 39, ///< Number of nonterminal symbols. 516 | yyfinal_ = 3, ///< Termination state number. 517 | yyterror_ = 1, 518 | yyerrcode_ = 256, 519 | yyntokens_ = 77 ///< Number of tokens. 520 | }; 521 | 522 | 523 | }; 524 | 525 | 526 | 527 | } // yy 528 | #line 529 "zScript.tab.hpp" // lalr1.cc:377 529 | 530 | 531 | 532 | 533 | #endif // !YY_YY_ZSCRIPT_TAB_HPP_INCLUDED 534 | -------------------------------------------------------------------------------- /demo/snake.zs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/zScript 2 | 3 | var UP = 65;//上 4 | var DOWN = 66;//下 5 | var LEFT = 68;//左 6 | var RIGHT = 67;//右 7 | 8 | var guan;//用来记录关卡 9 | var T;//用来给记录蛇的移动速度 10 | var t1, t2, t3 = 0;//用来记录已用时间 11 | var HP = 5;//记录蛇的生命值,初始化为6 12 | var food = 0;//用来记录所吃到的食物数 13 | var x = 12, y = 12;//记录食物所在地 14 | var p = []; 15 | var food_pos, star_pos; 16 | 17 | var fred = 31, fgreen = 32, fyellow = 33, fblue = 34, fwhite = 37; 18 | var bblack = 40, bred = 41, bgreen = 42, byellow = 43, bblue = 44, bwhite = 47; 19 | 20 | var time = () { 21 | return sys.msecsSinceStartOfDay() / 1000; 22 | }; 23 | 24 | var game; 25 | 26 | //绘制墙/绘制启动画面以及隔墙 27 | var start = () { 28 | var i, j; 29 | 30 | console.setColor(fgreen);//调成红色 31 | 32 | for (var z = 0; z < 20; ++z) { 33 | if (z >= 0) { 34 | console.setCursorPos(12, z); 35 | console.print(" ~--______-~ ~-___-~\" "); 36 | } 37 | 38 | if (z >= 1) { 39 | console.setCursorPos(12, z - 1); 40 | console.print(" ~-_ _-~ ~-_ _-~ "); 41 | } 42 | 43 | if (z >= 2) { 44 | console.setCursorPos(12, z - 2); 45 | console.print(" \\ ~-____-~ _-~ ~-_ ~-_-~ / "); 46 | } 47 | 48 | if (z >= 3) { 49 | console.setCursorPos(12, z - 3); 50 | console.print(" ( ( _-~ _--_ ~-_ _/ | "); 51 | } 52 | 53 | if (z >= 4) { 54 | console.setCursorPos(12, z - 4); 55 | console.print(" / / _-~ ~-_ | | "); 56 | } 57 | 58 | if (z >= 5) { 59 | console.setCursorPos(12, z - 5); 60 | console.print(" / / _----_ \\ \\ "); 61 | } 62 | 63 | if (z >= 6) { 64 | console.setCursorPos(12, z - 6); 65 | console.print(" / / \\ \\ "); 66 | } 67 | 68 | if (z >= 7) { 69 | console.setCursorPos(12, z - 7); 70 | console.print(" / / \\\\ "); 71 | } 72 | 73 | if (z >= 8) { 74 | console.setCursorPos(12, z - 8); 75 | console.print(" / / \\\\ "); 76 | } 77 | 78 | if (z >= 9) { 79 | console.setCursorPos(12, z - 9); 80 | console.print(" / / \\ "); 81 | } 82 | 83 | if (z >= 10) { 84 | console.setCursorPos(12, z - 10); 85 | console.print(" | | \\ "); 86 | } 87 | 88 | if (z >= 11) { 89 | console.setCursorPos(12, z - 11); 90 | console.print(" \\ \\ "); 91 | } 92 | 93 | if (z >= 12) { 94 | console.setCursorPos(12, z - 12); 95 | console.print(" \\_______ \\ "); 96 | } 97 | 98 | if (z >= 13) { 99 | console.setCursorPos(12, z - 13); 100 | console.print(" \\____|__________/ \\ "); 101 | } 102 | 103 | if (z >= 14) { 104 | console.setCursorPos(12, z - 14); 105 | console.print("\\/ /~ \\_/ \\ "); 106 | } 107 | 108 | if (z >= 15) { 109 | console.setCursorPos(12, z - 15); 110 | console.print(" _|__| O| "); 111 | } 112 | 113 | for (var k = 15; k < z; ++k) 114 | { 115 | console.setCursorPos(12, k - 15); 116 | console.print(" "); 117 | } 118 | 119 | sys.msleep(30); 120 | } 121 | 122 | sys.sleep(1); 123 | 124 | console.setCursorPos(0, 0); 125 | console.clear(); 126 | console.setColor(fred);//调整输出颜色 127 | 128 | for (i = 0, j = 60; i < 60; ++i, --j) {//if是为了异步输出 129 | if (j > 20) { 130 | console.setCursorPos(2 * (j - 21), 0); 131 | console.print("回");//输出第一行 132 | } 133 | 134 | if (i < 40) { 135 | console.setCursorPos(2 * i, 23); 136 | console.print("回");// 输出最下面一行 137 | } 138 | 139 | if (j > 22 && j < 45) { 140 | console.setCursorPos(78, j - 22); 141 | console.print("回");//输出最右边列 142 | } 143 | 144 | if (j > 22 && j < 45) { 145 | console.setCursorPos(0, i - 15); 146 | console.print("回");//输出第一列 147 | } 148 | 149 | if (i > 37 && i < 60) { 150 | console.setCursorPos(54, i - 37); 151 | sys.msleep(10); 152 | console.print("回");//输出中间那列 153 | } 154 | 155 | sys.msleep(30); 156 | } 157 | 158 | console.setCursorPos(56, 11); 159 | console.print("回回回回回回回回回回回"); //56 160 | console.setCursorPos(19, 0); 161 | console.setColor(fyellow);//调整输出颜色 162 | console.print("| | |贪 吃 蛇| | |");//输出标题 163 | 164 | console.setCursorPos(56, 2); 165 | console.print("已用时间:"); 166 | console.setCursorPos(75, 2); 167 | console.print("秒"); 168 | console.setCursorPos(56, 4); 169 | console.print("生命值:"); 170 | console.setCursorPos(56, 6); 171 | console.print("当前长度:"); 172 | console.setCursorPos(56, 8); 173 | console.print("已吃食物:"); 174 | console.setCursorPos(56, 10); 175 | console.print("第 关"); 176 | console.setCursorPos(64, 12); 177 | console.print("提示:"); 178 | console.setCursorPos(56, 13); 179 | console.print("向上:↑ 向上:←"); 180 | console.setCursorPos(56, 14); 181 | console.print("向下:↓ 向右:→"); 182 | console.setCursorPos(56, 15); 183 | console.print("暂停/开始:确定键 "); 184 | console.setCursorPos(56, 16); 185 | console.print("重新选关 :Esc键"); 186 | console.setCursorPos(64, 18); 187 | console.print("注意!"); 188 | console.setCursorPos(56, 19); 189 | console.print("1:撞到障碍物或者墙生命"); 190 | console.setCursorPos(56, 20); 191 | console.print(" 值减一 "); 192 | console.setCursorPos(56, 21); 193 | console.print("2:吃到小星星生命值加一"); 194 | }; 195 | 196 | var clear = ()//用来清除屏幕 197 | { 198 | for(var i = 2; i < 23; ++i) 199 | { 200 | console.setCursorPos(2, i); 201 | console.print(" "); 202 | } 203 | 204 | food_pos = undefined; 205 | star_pos = undefined; 206 | }; 207 | 208 | var guanka = () {//用来选择关卡并根据关卡设置蛇的移动速度 209 | console.setCursorVisible(true);//显示光标 210 | console.setEcho(true);//开启回显 211 | 212 | HP = 6;//记录蛇的生命值,初始化为6 213 | 214 | p = [{x:8, y:10, direction:RIGHT}, 215 | {x:6, y:10, direction:RIGHT}, 216 | {x:4, y:10, direction:RIGHT}, 217 | {x:4, y:4, direction:RIGHT}]; 218 | 219 | while (true) { 220 | console.setCursorPos(15, 3); 221 | guan = int(console.getLine("请输入关数(1-6):")); 222 | 223 | if (guan === 0) { //判断是否作弊 224 | console.setCursorPos(15, 3); 225 | console.setColor(fred);//变成红色 226 | console.print(" 作弊有害智商,需谨慎"); 227 | console.setCursorPos(15,5); 228 | console.setColor(fyellow);//变成黄色 229 | HP = console.getLine("请输入你想要的蛇的生命值:"); 230 | console.setCursorPos(15, 3); 231 | console.print(" "); 232 | console.setCursorPos(15, 5); 233 | console.print(" "); 234 | 235 | continue;//返回选关处 236 | } 237 | 238 | if (guan < 7 && guan > 0) 239 | break;//判断关数是否溢出 240 | 241 | console.setCursorPos(15, 5); 242 | console.print("输入错误!"); 243 | console.setCursorPos(32, 3); 244 | console.print(" "); 245 | } 246 | 247 | console.setCursorPos(15, 3); 248 | console.print(" "); 249 | 250 | switch (guan) 251 | { 252 | case 1:{T = 600;break;}// 253 | case 2:{T = 400;break;}// 254 | case 3:{T = 200;break;}// 根据关数来设定蛇的移动速度 255 | case 4:{T = 150;break;}// 256 | case 5:{T = 100;break;}// 257 | case 6:{T = 60;break;}// 258 | } 259 | 260 | clear();//清除屏幕 261 | }; 262 | 263 | var data = ()//用来记录和判断游戏的各种状态数据 264 | { 265 | console.setCursorPos(66, 2); 266 | console.setColor(fred);//调成红色 267 | console.print(t1);//程序已用时间 268 | switch (guan) 269 | { 270 | case 1:{ 271 | console.setCursorPos(59, 10); 272 | console.setColor(fred);//调成红色 273 | console.print("1"); 274 | console.setColor(fyellow);//调成黄色 275 | console.print(" 2 3 4 5 6"); 276 | break; 277 | } 278 | case 2:{ 279 | console.setCursorPos(59, 10); 280 | console.setColor(fyellow);//调成黄色 281 | console.print("1 "); 282 | console.setColor(fred);//调成红色 283 | console.print("2"); 284 | console.setColor(fyellow);//调成黄色 285 | console.print(" 3 4 5 6 "); 286 | break; 287 | } 288 | case 3:{ 289 | console.setCursorPos(59, 10); 290 | console.setColor(fyellow);//调成黄色 291 | console.print("1 2 "); 292 | console.setColor(fred);//调成红色 293 | console.print("3"); 294 | console.setColor(fyellow);//调成黄色 295 | console.print(" 4 5 6 "); 296 | break; 297 | } 298 | case 4:{ 299 | console.setCursorPos(59, 10); 300 | console.setColor(fyellow);//调成黄色 301 | console.print("1 2 3 "); 302 | console.setColor(fred);//调成红色 303 | console.print("4"); 304 | console.setColor(fyellow);//调成黄色 305 | console.print(" 5 6 "); 306 | break; 307 | } 308 | case 5:{ 309 | console.setCursorPos(59, 10); 310 | console.setColor(fyellow);//调成黄色 311 | console.print("1 2 3 4 "); 312 | console.setColor(fred);//调成红色 313 | console.print("5"); 314 | console.setColor(fyellow);//调成黄色 315 | console.print(" 6 "); 316 | break; 317 | } 318 | case 6:{ 319 | console.setCursorPos(59, 10); 320 | console.setColor(fyellow);//调成黄色 321 | console.print("1 2 3 4 5 "); 322 | console.setColor(fred);//调成红色 323 | console.print("6"); 324 | break; 325 | } 326 | } 327 | 328 | switch (HP) 329 | { 330 | case 1:{ 331 | console.setCursorPos(65, 4); 332 | console.setColor(fgreen);//调成绿色 333 | console.print("▁"); 334 | console.setColor(fred);//调成红色 335 | console.print("▂▃▅▆▇"); 336 | break; 337 | } 338 | case 2:{ 339 | console.setCursorPos(65, 4); 340 | console.setColor(fgreen);//调成绿色 341 | console.print("▁▂"); 342 | console.setColor(fred);//调成红色 343 | console.print("▃▅▆▇"); 344 | break; 345 | } 346 | case 3:{ 347 | console.setCursorPos(65, 4); 348 | console.setColor(fgreen);//调成绿色 349 | console.print("▁▂▃"); 350 | console.setColor(fred);//调成红色 351 | console.print("▅▆▇"); 352 | break; 353 | } 354 | case 4:{ 355 | console.setCursorPos(65, 4); 356 | console.setColor(fgreen);//调成绿色 357 | console.print("▁▂▃▅"); 358 | console.setColor(fred);//调成红色 359 | console.print("▆▇"); 360 | break; 361 | } 362 | case 5:{ 363 | console.setCursorPos(65, 4); 364 | console.setColor(fgreen);//调成绿色 365 | console.print("▁▂▃▅▆"); 366 | console.setColor(fred);//调成红色 367 | console.print("▇"); 368 | break; 369 | } 370 | case 6:{ 371 | console.setCursorPos(65, 4); 372 | console.setColor(fgreen);//调成绿色 373 | console.print("▁▂▃▅▆▇"); 374 | break; 375 | } 376 | default:{ 377 | console.setCursorPos(65, 4); 378 | console.setColor(fgreen);//调成红色 379 | console.print("!超级模式 !"); 380 | break; 381 | } 382 | } 383 | 384 | console.setCursorPos(66, 6); 385 | console.setColor(fred);//调成红色 386 | console.print(p.count());//输出蛇的当前长度 387 | console.setCursorPos(66, 8); 388 | console.print(food);//输出蛇当前已经吃到食物 389 | }; 390 | 391 | var isEmptyByPos = (x, y) 392 | { 393 | if (star_pos.x == x && star_pos.y == y) 394 | return false; 395 | 396 | if (x == food_pos.x && y == food_pos.y) 397 | return false; 398 | 399 | var obj; 400 | 401 | for (var i = 0; i < p.count(); ++i) { 402 | obj = p.at(i); 403 | 404 | if (obj.x == x && obj.y == y) 405 | return false; 406 | } 407 | 408 | return true; 409 | }; 410 | 411 | var getUsablePos = () 412 | { 413 | var x, y; 414 | 415 | while(true) { 416 | x = sys.random(1, 25);//产生随机横坐标 417 | y = sys.random(1, 21);//产生随机纵坐标 418 | 419 | if (isEmptyByPos(x, y)) 420 | break;//当此处无其他元素是才生效 421 | } 422 | 423 | return x, y; 424 | }; 425 | 426 | var show = ()//用来随机产生障碍物以及食物和生命药水以及用来判断游戏的各种参数 427 | { 428 | if (!food_pos) {//判断食物是不是被吃掉 429 | food_pos = {};//随机出现食物 430 | food_pos.x, food_pos.y = getUsablePos(); 431 | console.setCursorPos(2 * food_pos.x, food_pos.y);//定位到食物出现的位置 432 | console.setColor(fyellow);//调成黄色 433 | console.print("●");//打印出食物 434 | } 435 | 436 | if (t1 / 25 > 0 && t1 % 15 == 0 && t1 > t3 && !star_pos) {//减少星星出现的几率 437 | star_pos = {}; 438 | star_pos.x, star_pos.y = getUsablePos(); 439 | 440 | console.setCursorPos(2 * star_pos.x, star_pos.y);//定位到星星出现的位置(吃到星星长度减1) 441 | console.setColor(fyellow);//调成黄色 442 | console.print("☆");//打印出星星(吃到星星长度减1) 443 | t3 = t1;//以免产生多个障碍物 444 | 445 | if (HP < 7) { 446 | console.setCursorPos(18, 24); 447 | console.setColor(fwhite);//调成白色 448 | console.print("温馨提示:在选关的时候输入0可以开启作弊模式"); 449 | } 450 | } 451 | 452 | if (p[0].x == food_pos.x *2 && p[0].y == food_pos.y) {//判断蛇是否吃到食物 453 | ++food;//将食物数加1 454 | food_pos = undefined; 455 | //增加蛇的长度 456 | p.append({x:p.at(1).x, y:p.at(1).y}); 457 | } else if (p[0].x == star_pos.x * 2 && p[0].y == star_pos.y) {//判断蛇是否吃到星星 458 | star_pos = undefined; 459 | 460 | if (HP < 6) 461 | ++HP;//将生命值加1 462 | } 463 | 464 | t1 = time() - t2;//刷新游戏运行时间 465 | }; 466 | 467 | var key = ()//用户是否操作键盘 468 | { 469 | var ch = console.getKey(); 470 | 471 | switch (ch) 472 | { 473 | case 27: { 474 | var ch = console.getKey(); 475 | 476 | if (ch === -1) { 477 | guanka();//用来选择关卡并根据关卡设置蛇的移动速度 478 | game();//开始游戏 479 | 480 | break; 481 | } else if (ch != 91) { 482 | break; 483 | } 484 | 485 | ch = console.getKey(); 486 | 487 | if((ch === UP || ch === DOWN || ch === LEFT || ch === RIGHT) 488 | && (ch + p[0].direction != 131) && (ch + p[0].direction != 135) 489 | && ch != p[0].direction) { //判断按键是否是方向键,并且是不是蛇移动方向的反方向 490 | p[0].direction = ch;//如果不是就改变蛇头方向 491 | } 492 | 493 | break; 494 | } 495 | case 10: {//回车键 496 | var a, b; 497 | 498 | a = time();//记录当前程序已用时间 499 | console.setCursorPos(20, 1); 500 | console.setColor(fwhite);//调成白色 501 | console.print("已暂停,按确定键开始"); 502 | console.flushOutput(); 503 | 504 | while(true) { 505 | sys.sleep(1); 506 | 507 | if (console.getKey() == 10) {////判断是否按键且是否解除暂停 508 | console.setCursorPos(19, 0); 509 | console.setColor(fyellow); 510 | console.print("| | |贪 吃 蛇| | |");//清除"已暂停,按确定键开始"这行字 511 | console.setColor(fred); 512 | console.print(" 回"); 513 | 514 | break; 515 | } 516 | } 517 | 518 | b = time();//记录当前程序已用时间 519 | t2 += (b - a);//将暂停加到t2上供t1减去 520 | 521 | break; 522 | } 523 | } 524 | }; 525 | 526 | game = () { 527 | var i; 528 | var ch = RIGHT;//向右 529 | 530 | t2 = time();//记录当前程序已用时间 531 | 532 | console.setCursorVisible(false);//隐藏光标 533 | console.setEcho(false);//禁用回显 534 | 535 | while (true) { 536 | t1 = time() - t2;//刷新游戏运行时间 537 | data();//用来记录游戏的各种状态数据 538 | console.setCursorPos(p[0].x, p[0].y);//转到蛇头位置 539 | console.setColor(fred);//改成红色 540 | console.print("◆");//打印蛇头 541 | 542 | for (i = 1; i < p.count() - 1; ++i) { 543 | console.setCursorPos(p[i].x, p[i].y);//转到当前蛇身位置 544 | console.setColor(fyellow);//改成黄色 545 | console.print("●");//打印蛇身 546 | } 547 | 548 | console.setCursorPos(p[p.count() - 2].x, p[p.count() - 2].y);//转到当前蛇尾位置 549 | console.setColor(fred);//改成红色 550 | console.print("●");//打印蛇尾 551 | 552 | sys.msleep(T);//控制蛇的移动速度 553 | t1 = time() - t2;//刷新游戏运行时间 554 | console.setCursorPos(p.last().x, p.last().y);//移到蛇尾所在地 555 | console.print(" ");//清除上个循环的蛇尾 556 | 557 | for (i = p.count() - 1; i > 0; --i) { 558 | p[i].x = p[i - 1].x;//移动蛇 559 | p[i].y = p[i - 1].y; 560 | p[i].direction = p[i - 1].direction; 561 | } 562 | 563 | key();//用户是否操作键盘 564 | 565 | switch (p[0].direction) 566 | { 567 | case 65:{p[0].y -= 1; break;}//改变蛇头坐标,移动蛇头 568 | case 66:{p[0].y += 1; break;}//改变蛇头坐标,移动蛇头 569 | case 68:{p[0].x -= 2; break;}//改变蛇头坐标,移动蛇头 570 | case 67:{p[0].x += 2; break;}//改变蛇头坐标,移动蛇头 571 | } 572 | 573 | if (p[0].x == 2) {//当蛇撞到左墙时 574 | --HP;//将生命值减一 575 | p[0].x = 52;//将其穿墙 576 | } 577 | 578 | if (p[0].x == 54) {//当蛇撞到右墙时 579 | --HP;//将生命值减一 580 | p[0].x = 4;//将其穿墙 581 | } 582 | 583 | if (p[0].y == 1) {//当蛇撞到上墙时 584 | --HP;//将生命值减一 585 | p[0].y = 22;//将其穿墙 586 | } 587 | 588 | if (p[0].y == 23) {//当蛇撞到下墙时 589 | --HP;//将生命值减一 590 | p[0].y = 2;//将其穿墙 591 | } 592 | 593 | for (i = 1; i < p.count() - 1; i++) { 594 | if(p[0].x == p[i].x && p[0].y == p[i].y) 595 | i = p.count() + 1;//判断蛇是否撞到自己 596 | } 597 | 598 | if (i >= p.count()) {//当蛇撞到自己 599 | HP = 0;//将蛇死亡 600 | } 601 | 602 | if (HP == 0) { 603 | console.setCursorPos(25, 5); 604 | console.setColor(fwhite);//调成白色 605 | console.print("游戏结束!!!"); 606 | console.flushOutput(); 607 | sys.sleep(3);//延时 608 | 609 | return true; 610 | } 611 | 612 | if (p.count() == 81) { 613 | console.setCursorPos(25, 5); 614 | console.setColor(fwhite);//调成白色 615 | console.print("恭喜你过关!!!"); 616 | console.flushOutput(); 617 | sys.sleep(3);//延时 618 | 619 | return true; 620 | } 621 | 622 | show();//用来随机产生障碍物以及食物和生命药水以及用来判断游戏的各种参数(小星星是否吃到,是否撞墙) 623 | } 624 | 625 | return false; 626 | }; 627 | 628 | console.clear(); 629 | console.setCursorVisible(false);//隐藏光标 630 | start();//绘制启动画面以及隔墙 631 | 632 | while (true) { 633 | guanka();//用来选择关卡并根据关卡设置蛇的移动速度 634 | 635 | if (!game()) 636 | break;//游戏运行 637 | } 638 | 639 | console.setCursorVisible(true); 640 | -------------------------------------------------------------------------------- /common/zvariant.cpp: -------------------------------------------------------------------------------- 1 | #include "zvariant.h" 2 | #include "zobject.h" 3 | 4 | #include 5 | 6 | Z_BEGIN_NAMESPACE 7 | 8 | /// ZVariant 9 | ZVariant::ZVariant(ZVariant::Type type) 10 | : m_data(new VariantData) 11 | { 12 | m_data->type = type; 13 | } 14 | 15 | ZVariant::ZVariant(int val) 16 | : m_data(new VariantData) 17 | { 18 | m_data->variant = val; 19 | m_data->type = Int; 20 | } 21 | 22 | ZVariant::ZVariant(double val) 23 | : m_data(new VariantData) 24 | { 25 | m_data->variant = val; 26 | m_data->type = Double; 27 | } 28 | 29 | ZVariant::ZVariant(bool val) 30 | : m_data(new VariantData) 31 | { 32 | m_data->variant = val; 33 | m_data->type = Bool; 34 | } 35 | 36 | ZVariant::ZVariant(const char *val) 37 | : m_data(new VariantData) 38 | { 39 | m_data->variant = val; 40 | m_data->type = String; 41 | } 42 | 43 | ZVariant::ZVariant(const ZVariant &other) 44 | : m_data(other.m_data) 45 | { 46 | 47 | } 48 | 49 | ZVariant::ZVariant(ZVariant &&other) 50 | { 51 | m_data.swap(other.m_data); 52 | } 53 | 54 | ZVariant::ZVariant(const QString &val) 55 | : m_data(new VariantData) 56 | { 57 | m_data->variant = val; 58 | m_data->type = String; 59 | } 60 | 61 | ZVariant::ZVariant(QLatin1String val) 62 | : m_data(new VariantData) 63 | { 64 | m_data->variant = val; 65 | m_data->type = String; 66 | } 67 | 68 | template 69 | ZVariant::ZVariant(const QList &val) 70 | : m_data(new VariantData) 71 | { 72 | QList list; 73 | 74 | list.reserve(val.size()); 75 | 76 | for(const T &v : val) 77 | list << ZVariant(v); 78 | 79 | m_data->variant = QVariant::fromValue(list); 80 | m_data->type = List; 81 | } 82 | 83 | ZVariant::ZVariant(const QList &val) 84 | : m_data(new VariantData) 85 | { 86 | m_data->variant = QVariant::fromValue(val); 87 | m_data->type = List; 88 | } 89 | 90 | ZVariant::ZVariant(const ZVariant::ZTuple &group) 91 | : m_data(new VariantData) 92 | { 93 | m_data->variant = QVariant::fromValue(group); 94 | m_data->type = Tuple; 95 | } 96 | 97 | ZVariant::ZVariant(ZObject * const object) 98 | : m_data(new VariantData) 99 | { 100 | m_data->variant = QVariant::fromValue(object); 101 | m_data->type = Object; 102 | } 103 | 104 | ZVariant::ZVariant(ZFunction * const function) 105 | : m_data(new VariantData) 106 | { 107 | m_data->variant = QVariant::fromValue(function); 108 | m_data->type = Function; 109 | } 110 | 111 | ZVariant::ZVariant(const QVariant &val) 112 | : m_data(new VariantData) 113 | { 114 | m_data->variant = val; 115 | 116 | switch (val.type()) { 117 | case QVariant::Int: 118 | m_data->type = Int; 119 | break; 120 | case QVariant::Double: 121 | m_data->type = Double; 122 | break; 123 | case QVariant::Bool: 124 | m_data->type = Bool; 125 | break; 126 | case QVariant::ByteArray: 127 | case QVariant::String: 128 | m_data->type = String; 129 | break; 130 | case QVariant::List: 131 | m_data->type = List; 132 | break; 133 | case QVariant::Invalid: 134 | m_data->type = Undefined; 135 | break; 136 | case QMetaType::PointerToQObject: 137 | m_data->type = Object; 138 | break; 139 | case QVariant::UserType:{ 140 | if(QString(val.typeName()) == "ZObject*") { 141 | m_data->type = Object; 142 | } else if(QString(val.typeName()) == "ZFunction*") { 143 | m_data->type = Function; 144 | } else if(QString(val.typeName()) == "ZVariant") { 145 | m_data = qvariant_cast(val).m_data; 146 | } else { 147 | // zWarning << "Unknow Type:" << val.typeName(); 148 | m_data->type = Unknow; 149 | m_data->variant = val; 150 | } 151 | break; 152 | } 153 | default: 154 | m_data->type = Undefined; 155 | break; 156 | } 157 | } 158 | 159 | ZVariant::~ZVariant() 160 | { 161 | 162 | } 163 | 164 | const char *ZVariant::typeName() const 165 | { 166 | switch (m_data->type) { 167 | case Int: 168 | return "int"; 169 | case Double: 170 | return "double"; 171 | case Bool: 172 | return "boolean"; 173 | case String: 174 | return "string"; 175 | case List: 176 | return "list"; 177 | case Object: 178 | return "object"; 179 | case Function: 180 | return "function"; 181 | case Undefined: 182 | return "undefined"; 183 | case Tuple: 184 | return "tuple"; 185 | default: 186 | return "unknow"; 187 | break; 188 | } 189 | 190 | return m_data->variant.typeName(); 191 | } 192 | 193 | int ZVariant::toInt(bool *ok) const 194 | { 195 | if(ok) 196 | *ok = true; 197 | 198 | switch(m_data->type) { 199 | case Int: 200 | return m_data->variant.toInt(); 201 | case Double: 202 | return (int)m_data->variant.toDouble(); 203 | case Bool: 204 | return m_data->variant.toBool(); 205 | case String: 206 | return m_data->variant.toString().toInt(ok); 207 | case Object: 208 | case Function: 209 | case Undefined: 210 | if(ok) 211 | *ok = false; 212 | return 0; 213 | default:break; 214 | } 215 | 216 | return m_data->variant.toInt(ok); 217 | } 218 | 219 | double ZVariant::toDouble(bool *ok) const 220 | { 221 | if(ok) 222 | *ok = true; 223 | 224 | switch(m_data->type) { 225 | case Int: 226 | return m_data->variant.toInt(); 227 | case Double: 228 | return m_data->variant.toDouble(); 229 | case Bool: 230 | return m_data->variant.toBool(); 231 | case String: 232 | return m_data->variant.toString().toDouble(ok); 233 | case Object: 234 | case Function: 235 | case Undefined: 236 | if(ok) 237 | *ok = false; 238 | return 0; 239 | default:break; 240 | } 241 | 242 | return m_data->variant.toDouble(ok); 243 | } 244 | 245 | bool ZVariant::toBool() const 246 | { 247 | switch(m_data->type) { 248 | case Int: 249 | return m_data->variant.toInt(); 250 | case Double: 251 | return (int)m_data->variant.toDouble(); 252 | case Bool: 253 | return m_data->variant.toBool(); 254 | case String: 255 | return !m_data->variant.toString().isEmpty(); 256 | case Object: 257 | case Function: 258 | return (bool)toObject(); 259 | case Undefined: 260 | return false; 261 | default: break; 262 | } 263 | 264 | return m_data->variant.toBool(); 265 | } 266 | 267 | QList ZVariant::toList() const 268 | { 269 | if(type() == Tuple) { 270 | QList list; 271 | 272 | for(const ZVariant *val : toTuple()) { 273 | list << *val; 274 | } 275 | 276 | return list; 277 | } 278 | 279 | return qvariant_cast>(m_data->variant); 280 | } 281 | 282 | ZObject *ZVariant::toObject() const 283 | { 284 | return qvariant_cast(m_data->variant); 285 | } 286 | 287 | ZFunction *ZVariant::toFunction() const 288 | { 289 | return qobject_cast(toObject()); 290 | } 291 | 292 | ZVariant ZVariant::operator[](const ZVariant &value) const 293 | { 294 | switch (m_data->type) { 295 | case List: { 296 | bool ok = false; 297 | 298 | const ZVariant &val = toList().value(value.toInt(&ok)); 299 | 300 | if(!ok) 301 | return ZVariant(); 302 | else 303 | return val; 304 | } 305 | case Tuple: { 306 | bool ok; 307 | 308 | const ZVariant &val = *toTuple().value(value.toInt(&ok)); 309 | 310 | if(!ok) 311 | return ZVariant(); 312 | else 313 | return val; 314 | } 315 | case String: { 316 | bool ok; 317 | 318 | int index = value.toInt(&ok); 319 | const QString &str = toString(); 320 | 321 | if(!ok || index >= str.size()) 322 | return QString(); 323 | else 324 | return QString(str.at(index)); 325 | } 326 | case Function: 327 | case Object: 328 | return toObject()->property(value.toString().toLatin1().constData()); 329 | default: 330 | return Undefined; 331 | } 332 | } 333 | 334 | /// global 335 | ZVariant operator +(const int var1, const ZVariant &var2) 336 | { 337 | switch(var2.type()) { 338 | case ZVariant::Int: 339 | return var1 + var2.toInt(); 340 | case ZVariant::Double: 341 | return var1 + var2.toDouble(); 342 | case ZVariant::String: 343 | return QString::number(var1) + var2.toString(); 344 | case ZVariant::Bool: 345 | return var1 + var2.toBool(); 346 | default: break; 347 | } 348 | 349 | return ZVariant::Undefined; 350 | } 351 | 352 | ZVariant operator -(const int var1, const ZVariant &var2) 353 | { 354 | switch(var2.type()) { 355 | case ZVariant::Int: 356 | return var1 - var2.toInt(); 357 | case ZVariant::Double: 358 | return var1 - var2.toDouble(); 359 | case ZVariant::Bool: 360 | return var1 - var2.toBool(); 361 | default: break; 362 | } 363 | 364 | return ZVariant::Undefined; 365 | } 366 | 367 | ZVariant operator *(const int var1, const ZVariant &var2) 368 | { 369 | switch(var2.type()) { 370 | case ZVariant::Int: 371 | return var1 * var2.toInt(); 372 | case ZVariant::Double: 373 | return var1 * var2.toDouble(); 374 | case ZVariant::Bool: 375 | return var1 * var2.toBool(); 376 | case ZVariant::String: 377 | return var2 * var1; 378 | default: break; 379 | } 380 | 381 | return ZVariant::Undefined; 382 | } 383 | 384 | ZVariant operator /(const int var1, const ZVariant &var2) 385 | { 386 | switch(var2.type()) { 387 | case ZVariant::Int: 388 | return var1 / var2.toInt(); 389 | case ZVariant::Double: 390 | return var1 / var2.toDouble(); 391 | case ZVariant::Bool: 392 | return var1 / var2.toBool(); 393 | default: break; 394 | } 395 | 396 | return ZVariant::Undefined; 397 | } 398 | 399 | ZVariant operator &(const int var1, const ZVariant &var2) 400 | { 401 | switch(var2.type()) { 402 | case ZVariant::Int: 403 | return var1 & var2.toInt(); 404 | case ZVariant::Double: 405 | return var1 & (int)var2.toDouble(); 406 | case ZVariant::Bool: 407 | return var1 & var2.toBool(); 408 | default: break; 409 | } 410 | 411 | return ZVariant::Undefined; 412 | } 413 | 414 | ZVariant operator |(const int var1, const ZVariant &var2) 415 | { 416 | switch(var2.type()) { 417 | case ZVariant::Int: 418 | return var1 | var2.toInt(); 419 | case ZVariant::Double: 420 | return var1 | (int)var2.toDouble(); 421 | case ZVariant::Bool: 422 | return var1 | var2.toBool(); 423 | default: break; 424 | } 425 | 426 | return ZVariant::Undefined; 427 | } 428 | 429 | ZVariant operator ^(const int var1, const ZVariant &var2) 430 | { 431 | switch(var2.type()) { 432 | case ZVariant::Int: 433 | return var1 ^ var2.toInt(); 434 | case ZVariant::Double: 435 | return var1 ^ (int)var2.toDouble(); 436 | case ZVariant::Bool: 437 | return var1 ^ var2.toBool(); 438 | default: break; 439 | } 440 | 441 | return ZVariant::Undefined; 442 | } 443 | 444 | ZVariant operator %(const int var1, const ZVariant &var2) 445 | { 446 | switch(var2.type()) { 447 | case ZVariant::Int: 448 | return var1 % var2.toInt(); 449 | case ZVariant::Double: 450 | return var1 % (int)var2.toDouble(); 451 | case ZVariant::Bool: 452 | return var1 % var2.toBool(); 453 | default: break; 454 | } 455 | 456 | return ZVariant::Undefined; 457 | } 458 | 459 | ZVariant operator +(const double &var1, const ZVariant &var2) 460 | { 461 | switch(var2.type()) { 462 | case ZVariant::Int: 463 | return var1 + var2.toInt(); 464 | case ZVariant::Double: 465 | return var1 + var2.toDouble(); 466 | case ZVariant::String: 467 | return QString::number(var1) + var2.toString(); 468 | case ZVariant::Bool: 469 | return var1 + var2.toBool(); 470 | default: break; 471 | } 472 | 473 | return ZVariant::Undefined; 474 | } 475 | 476 | ZVariant operator -(const double &var1, const ZVariant &var2) 477 | { 478 | switch(var2.type()) { 479 | case ZVariant::Int: 480 | return var1 - var2.toInt(); 481 | case ZVariant::Double: 482 | return var1 - var2.toDouble(); 483 | case ZVariant::Bool: 484 | return var1 - var2.toBool(); 485 | default: break; 486 | } 487 | 488 | return ZVariant::Undefined; 489 | } 490 | 491 | ZVariant operator *(const double &var1, const ZVariant &var2) 492 | { 493 | switch(var2.type()) { 494 | case ZVariant::Int: 495 | return var1 * var2.toInt(); 496 | case ZVariant::Double: 497 | return var1 * var2.toDouble(); 498 | case ZVariant::Bool: 499 | return var1 * var2.toBool(); 500 | default: break; 501 | } 502 | 503 | return ZVariant::Undefined; 504 | } 505 | 506 | ZVariant operator /(const double &var1, const ZVariant &var2) 507 | { 508 | switch(var2.type()) { 509 | case ZVariant::Int: 510 | return var1 / var2.toInt(); 511 | case ZVariant::Double: 512 | return var1 / var2.toDouble(); 513 | case ZVariant::Bool: 514 | return var1 / var2.toBool(); 515 | default: break; 516 | } 517 | 518 | return ZVariant::Undefined; 519 | } 520 | 521 | ZVariant operator +(const QString &var1, const ZVariant &var2) 522 | { 523 | switch(var2.type()) { 524 | case ZVariant::Int: 525 | return var1 + QString::number(var2.toInt()); 526 | case ZVariant::Double: 527 | return var1 + QString::number(var2.toDouble()); 528 | case ZVariant::String: 529 | return var1 + var2.toString(); 530 | case ZVariant::Bool: 531 | return var1 + (var2.toBool() ? "true" : "false"); 532 | default: break; 533 | } 534 | 535 | return ZVariant::Undefined; 536 | } 537 | 538 | ZVariant operator -(const QString &var1, const ZVariant &var2) 539 | { 540 | const QString &str = var2.toString(); 541 | 542 | if(!str.isEmpty()) 543 | return QString(var1).replace(str, ""); 544 | 545 | return var1; 546 | } 547 | 548 | ZVariant operator *(const QString &var1, const ZVariant &var2) 549 | { 550 | if(var2.type() == ZVariant::Int) { 551 | QString array; 552 | int count = var2.toInt(); 553 | 554 | array.reserve(var1.size() * count); 555 | 556 | while(count-- > 0) 557 | array.append(var1); 558 | 559 | return array; 560 | } 561 | 562 | return ZVariant::Undefined; 563 | } 564 | 565 | ZVariant operator /(const QString &var1, const ZVariant &var2) 566 | { 567 | const QString &str = var2.toString(); 568 | 569 | if(str.isEmpty()) 570 | return var1; 571 | 572 | return QString(var1).split(str); 573 | } 574 | 575 | ZVariant operator &(const QString &var1, const ZVariant &var2) 576 | { 577 | const QString var2Str = var2.toString(); 578 | 579 | if(var2Str.isEmpty()) 580 | return var1; 581 | 582 | QString str; 583 | 584 | int max_size = qMax(var1.size(), var2Str.size()); 585 | 586 | str.reserve(max_size); 587 | 588 | for(int i = 0; i < max_size; ++i) { 589 | str[i] = var1.at(i % var1.size()).unicode() & var2Str.at(i % var2Str.size()).unicode(); 590 | } 591 | 592 | return str; 593 | } 594 | 595 | ZVariant operator |(const QString &var1, const ZVariant &var2) 596 | { 597 | const QString var2Str = var2.toString(); 598 | 599 | if(var2Str.isEmpty()) 600 | return var1; 601 | 602 | QString str; 603 | 604 | int max_size = qMax(var1.size(), var2Str.size()); 605 | 606 | str.reserve(max_size); 607 | 608 | for(int i = 0; i < max_size; ++i) { 609 | str[i] = var1.at(i % var1.size()).unicode() | var2Str.at(i % var2Str.size()).unicode(); 610 | } 611 | 612 | return str; 613 | } 614 | 615 | ZVariant operator ^(const QString &var1, const ZVariant &var2) 616 | { 617 | const QString var2Str = var2.toString(); 618 | 619 | if(var2Str.isEmpty()) 620 | return var1; 621 | 622 | QString str; 623 | 624 | int max_size = qMax(var1.size(), var2Str.size()); 625 | 626 | str.reserve(max_size); 627 | 628 | for(int i = 0; i < max_size; ++i) { 629 | str[i] = var1.at(i % var1.size()).unicode() ^ var2Str.at(i % var2Str.size()).unicode(); 630 | } 631 | 632 | return str; 633 | } 634 | 635 | ZVariant operator %(const QString &var1, const ZVariant &var2) 636 | { 637 | const QString var2Str = var2.toString(); 638 | 639 | if(var2Str.isEmpty()) 640 | return var1; 641 | 642 | QString str; 643 | 644 | int max_size = qMax(var1.size(), var2Str.size()); 645 | 646 | str.reserve(max_size); 647 | 648 | for(int i = 0; i < max_size; ++i) { 649 | str[i] = var1.at(i % var1.size()).unicode() % var2Str.at(i % var2Str.size()).unicode(); 650 | } 651 | 652 | return str; 653 | } 654 | 655 | ZVariant operator ~(const ZVariant &var) 656 | { 657 | switch(var.type()) { 658 | case ZVariant::Int: 659 | return ~var.toInt(); 660 | case ZVariant::Double: 661 | return ~(int)var.toDouble(); 662 | case ZVariant::Bool: 663 | return ~var.toBool(); 664 | case ZVariant::String:{ 665 | QString str = var.toString(); 666 | 667 | for(QChar &ch : str) { 668 | if(ch.isLower()) 669 | ch = ch.toUpper(); 670 | else 671 | ch = ch.toLower(); 672 | } 673 | 674 | return str; 675 | } 676 | default: break; 677 | } 678 | 679 | return ZVariant::Undefined; 680 | } 681 | 682 | Z_END_NAMESPACE 683 | 684 | QT_BEGIN_NAMESPACE 685 | QDebug operator<<(QDebug deg, const ZVariant &var) 686 | { 687 | deg.nospace() << "Variant(" << var.typeName() << ", "; 688 | 689 | switch(var.type()) { 690 | case ZVariant::Object: 691 | deg.nospace() << var.toObject(); 692 | break; 693 | case ZVariant::Function: 694 | deg.nospace() << var.toFunction(); 695 | break; 696 | case ZVariant::Undefined: 697 | deg.nospace() << var.typeName(); 698 | break; 699 | case ZVariant::List: 700 | case ZVariant::Tuple: 701 | deg.noquote() << var.toList(); 702 | break; 703 | case ZVariant::Int: 704 | case ZVariant::Double: 705 | deg.noquote() << var.toDouble(); 706 | break; 707 | default: 708 | deg.nospace() << var.toString(); 709 | break; 710 | } 711 | 712 | deg.nospace() << ")"; 713 | 714 | return deg; 715 | } 716 | 717 | uint qHash(const ZVariant &val, uint seed) 718 | { 719 | switch (val.type()) { 720 | case ZVariant::Int: 721 | return qHash(val.toInt(), seed); 722 | case ZVariant::Double: 723 | return qHash(val.toDouble(), seed); 724 | case ZVariant::String: 725 | return qHash(val.toString(), seed); 726 | case ZVariant::Bool: 727 | return qHash(val.toBool(), seed); 728 | case ZVariant::List: 729 | return qHash(val.toList(), seed); 730 | case ZVariant::Object: 731 | case ZVariant::Function: 732 | return qHash(val.toObject(), seed); 733 | case ZVariant::Tuple: { 734 | uint hash = 0; 735 | 736 | for(const ZVariant *tmp_val : val.toTuple()) { 737 | hash ^= qHash(*tmp_val, seed); 738 | } 739 | 740 | return hash; 741 | } 742 | default: 743 | return -1; 744 | } 745 | } 746 | QT_END_NAMESPACE 747 | -------------------------------------------------------------------------------- /common/zcode.cpp: -------------------------------------------------------------------------------- 1 | #include "zcode.h" 2 | #include "zobject.h" 3 | #include "zobjectpool.h" 4 | 5 | #include "zScript.tab.hpp" 6 | #include "FlexLexer.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | Z_BEGIN_NAMESPACE 17 | 18 | QStack ZCode::virtualStack; 19 | 20 | QString ZCode::actionName(quint8 action) 21 | { 22 | switch(action) { 23 | case LeftAssign: return "=(left)"; 24 | case RightAssign: return "=(right)"; 25 | case Add: return "+"; 26 | case Sub: return "-"; 27 | case Mul: return "*"; 28 | case Div: return "/"; 29 | case Abs: return "abs"; 30 | case Minus: return "minus"; 31 | case And: return "&"; 32 | case Or: return "|"; 33 | case Xor: return "^"; 34 | case Contrary: return "~"; 35 | case Mod: return "%"; 36 | case Not: return "!"; 37 | case AddAssign: return "+="; 38 | case SubAssign: return "-="; 39 | case MulAssign: return "*="; 40 | case DivAssign: return "/="; 41 | case AndAssign: return "&="; 42 | case OrAssign: return "|="; 43 | case XorAssign: return "^="; 44 | case ModAssign: return "%="; 45 | case NotAssign: return "!="; 46 | case Less: return "<"; 47 | case Greater: return ">"; 48 | case New: return "new"; 49 | case Delete: return "delete"; 50 | case Throw: return "throw"; 51 | case EQ: return "=="; 52 | case STEQ: return "==="; 53 | case NEQ: return "!="; 54 | case STNEQ: return "!=="; 55 | case LE: return "<="; 56 | case GE: return ">="; 57 | case LAnd: return "&&"; 58 | case LOr: return "||"; 59 | case LAndAssign: return "&&="; 60 | case LOrAssign: return "||="; 61 | case PrefixAddSelf: return "++(prefix)"; 62 | case PostfixAddSelf: return "++(postfix)"; 63 | case PrefixSubSelf: return "--(prefix)"; 64 | case PostfixSubSelf: return "--(postfix)"; 65 | case Get: return "."; 66 | case JoinToTuple: return "join to tuple"; 67 | case JoinToList: return "join to list"; 68 | case Call: return "call"; 69 | case Push: return "push"; 70 | case Pop: return "pop"; 71 | case PopAll: return "pop all"; 72 | case Goto: return "goto"; 73 | case If: return "if"; 74 | case Children: return "[](get children)"; 75 | case Append: return "<<(append)"; 76 | case Switch: return "switch"; 77 | case InitObjectProperty:return "init object property"; 78 | case Unknow: return "unknow"; 79 | } 80 | 81 | return ""; 82 | } 83 | 84 | ZVariant ZCode::exec(const QList &codeList) 85 | { 86 | QList temporaryList; 87 | QList temporaryPropertyList; 88 | 89 | temporaryList.reserve(10); 90 | temporaryList.reserve(2); 91 | 92 | for(int i = 0; i < codeList.count(); ++i) { 93 | ZCode *code = codeList.value(i); 94 | 95 | #ifndef QT_NO_DEBUG 96 | zDebug << i <<*code; 97 | #endif 98 | 99 | switch(code->action) { 100 | case LeftAssign: { 101 | const ZVariant &right_val = *virtualStack.pop(); 102 | 103 | virtualStack.top()->depthCopyAssign(right_val); 104 | break; 105 | } 106 | case RightAssign: { 107 | ZVariant &left_val = *virtualStack.pop(); 108 | const ZVariant &right_val = *virtualStack.pop(); 109 | 110 | left_val.depthCopyAssign(right_val); 111 | virtualStack.push(&left_val); 112 | break; 113 | } 114 | case Add: 115 | temporaryList << *virtualStack.pop() + *virtualStack.pop(); 116 | virtualStack.push(&temporaryList.last()); 117 | break; 118 | case Sub: 119 | temporaryList << *virtualStack.pop() - *virtualStack.pop(); 120 | virtualStack.push(&temporaryList.last()); 121 | break; 122 | case Mul: 123 | temporaryList << *virtualStack.pop() * *virtualStack.pop(); 124 | virtualStack.push(&temporaryList.last()); 125 | break; 126 | case Div: 127 | temporaryList << *virtualStack.pop() / *virtualStack.pop(); 128 | virtualStack.push(&temporaryList.last()); 129 | break; 130 | case Abs: 131 | temporaryList << + *virtualStack.pop(); 132 | virtualStack.push(&temporaryList.last()); 133 | break; 134 | case Minus: 135 | temporaryList << - *virtualStack.pop(); 136 | virtualStack.push(&temporaryList.last()); 137 | break; 138 | case And: 139 | temporaryList << *virtualStack.pop() & *virtualStack.pop(); 140 | virtualStack.push(&temporaryList.last()); 141 | break; 142 | case Or: 143 | temporaryList << *virtualStack.pop() | *virtualStack.pop(); 144 | virtualStack.push(&temporaryList.last()); 145 | break; 146 | case Xor: 147 | temporaryList << *virtualStack.pop() ^ *virtualStack.pop(); 148 | virtualStack.push(&temporaryList.last()); 149 | break; 150 | case Contrary: 151 | temporaryList << ~ *virtualStack.pop(); 152 | virtualStack.push(&temporaryList.last()); 153 | break; 154 | case Mod: 155 | temporaryList << *virtualStack.pop() % *virtualStack.pop(); 156 | virtualStack.push(&temporaryList.last()); 157 | break; 158 | case Not: 159 | temporaryList << ! *virtualStack.pop(); 160 | virtualStack.push(&temporaryList.last()); 161 | break; 162 | case AddAssign: { 163 | ZVariant &right_val = *virtualStack.pop(); 164 | ZVariant &left_val = *virtualStack.top(); 165 | 166 | left_val.depthCopyAssign(left_val + right_val); 167 | break; 168 | } 169 | case SubAssign: { 170 | ZVariant &right_val = *virtualStack.pop(); 171 | ZVariant &left_val = *virtualStack.top(); 172 | 173 | left_val.depthCopyAssign(left_val - right_val); 174 | break; 175 | } 176 | case MulAssign: { 177 | ZVariant &right_val = *virtualStack.pop(); 178 | ZVariant &left_val = *virtualStack.top(); 179 | 180 | left_val.depthCopyAssign(left_val * right_val); 181 | break; 182 | } 183 | case DivAssign: { 184 | ZVariant &right_val = *virtualStack.pop(); 185 | ZVariant &left_val = *virtualStack.top(); 186 | 187 | left_val.depthCopyAssign(left_val / right_val); 188 | break; 189 | } 190 | case AndAssign: { // "&="; 191 | ZVariant &right_val = *virtualStack.pop(); 192 | ZVariant &left_val = *virtualStack.top(); 193 | 194 | left_val.depthCopyAssign(left_val & right_val); 195 | break; 196 | } 197 | case OrAssign: { // "|="; 198 | ZVariant &right_val = *virtualStack.pop(); 199 | ZVariant &left_val = *virtualStack.top(); 200 | 201 | left_val.depthCopyAssign(left_val | right_val); 202 | break; 203 | } 204 | case XorAssign: { // "^="; 205 | ZVariant &right_val = *virtualStack.pop(); 206 | ZVariant &left_val = *virtualStack.top(); 207 | 208 | left_val.depthCopyAssign(left_val ^ right_val); 209 | break; 210 | } 211 | case ModAssign: { // "%="; 212 | ZVariant &right_val = *virtualStack.pop(); 213 | ZVariant &left_val = *virtualStack.top(); 214 | 215 | left_val.depthCopyAssign(left_val % right_val); 216 | break; 217 | } 218 | case Less: 219 | temporaryList << (*virtualStack.pop() < *virtualStack.pop()); 220 | virtualStack.push(&temporaryList.last()); 221 | break; 222 | case Greater: 223 | temporaryList << (*virtualStack.pop() > *virtualStack.pop()); 224 | virtualStack.push(&temporaryList.last()); 225 | break; 226 | case New: 227 | /// TODO 228 | break; 229 | case Delete: 230 | /// TODO 231 | break; 232 | case Throw: 233 | /// TODO 234 | break; 235 | case EQ: 236 | temporaryList << (*virtualStack.pop() == *virtualStack.pop()); 237 | virtualStack.push(&temporaryList.last()); 238 | break; 239 | case STEQ: { 240 | const ZVariant &v1 = *virtualStack.pop(); 241 | const ZVariant &v2 = *virtualStack.pop(); 242 | 243 | temporaryList << (v1.type() == v2.type() && v1 == v2); 244 | 245 | virtualStack.push(&temporaryList.last()); 246 | break; 247 | } 248 | case NEQ: 249 | temporaryList << (*virtualStack.pop() != *virtualStack.pop()); 250 | virtualStack.push(&temporaryList.last()); 251 | break; 252 | case STNEQ: { 253 | const ZVariant &v1 = *virtualStack.pop(); 254 | const ZVariant &v2 = *virtualStack.pop(); 255 | 256 | temporaryList << (v1.type() != v2.type() || v1 != v2); 257 | virtualStack.push(&temporaryList.last()); 258 | break; 259 | } 260 | case LE: 261 | temporaryList << (*virtualStack.pop() <= *virtualStack.pop()); 262 | virtualStack.push(&temporaryList.last()); 263 | break; 264 | case GE: 265 | temporaryList << (*virtualStack.pop() >= *virtualStack.pop()); 266 | virtualStack.push(&temporaryList.last()); 267 | break; 268 | case LAnd: 269 | temporaryList << (*virtualStack.pop() && *virtualStack.pop()); 270 | virtualStack.push(&temporaryList.last()); 271 | break; 272 | case LOr: 273 | temporaryList << (*virtualStack.pop() || *virtualStack.pop()); 274 | virtualStack.push(&temporaryList.last()); 275 | break; 276 | case LAndAssign: { // "&&="; 277 | ZVariant &right_val = *virtualStack.pop(); 278 | ZVariant &left_val = *virtualStack.top(); 279 | 280 | left_val.depthCopyAssign(left_val && right_val); 281 | break; 282 | } 283 | case LOrAssign: { // "||="; 284 | ZVariant &right_val = *virtualStack.pop(); 285 | ZVariant &left_val = *virtualStack.top(); 286 | 287 | left_val.depthCopyAssign(left_val || right_val); 288 | break; 289 | } 290 | case PrefixAddSelf: { // "++(prefix)"; 291 | ZVariant &left_val = *virtualStack.top(); 292 | 293 | left_val.depthCopyAssign(1 + left_val); 294 | break; 295 | } 296 | case PostfixAddSelf: { // "++(postfix)"; 297 | ZVariant &left_val = *virtualStack.pop(); 298 | temporaryList << ZVariant::copy(left_val); 299 | virtualStack.push(&temporaryList.last()); 300 | left_val.depthCopyAssign(1 + left_val); 301 | break; 302 | } 303 | case PrefixSubSelf: { // "--(prefix)"; 304 | ZVariant &left_val = *virtualStack.top(); 305 | 306 | left_val.depthCopyAssign(-1 + left_val); 307 | break; 308 | } 309 | case PostfixSubSelf: { // "--(postfix)"; 310 | ZVariant &left_val = *virtualStack.pop(); 311 | temporaryList << ZVariant::copy(left_val); 312 | virtualStack.push(&temporaryList.last()); 313 | left_val.depthCopyAssign(-1 + left_val); 314 | break; 315 | } 316 | case Get: { 317 | ZVariant &right_val = *virtualStack.pop(); 318 | ZVariant &left_val = *virtualStack.pop(); 319 | 320 | const QByteArray &propertyName = right_val.toString().toLatin1(); 321 | 322 | if (left_val.isObject()) { 323 | ZObject *obj = left_val.toObject(); 324 | 325 | if (obj) { 326 | temporaryPropertyList << ZPropertyVariant(obj->property(propertyName.constData()), obj, propertyName); 327 | virtualStack.push(&temporaryPropertyList.last()); 328 | 329 | break; 330 | } 331 | 332 | temporaryList << ZVariant(); 333 | } else { 334 | ZFunction *function = ZCodeExecuter::getFunctionForVariantType(left_val.type(), propertyName); 335 | 336 | if (function) { 337 | function->setProperty("target", true); 338 | 339 | virtualStack << &left_val; 340 | temporaryList << ZVariant(function); 341 | } else { 342 | temporaryList << ZVariant(); 343 | } 344 | } 345 | 346 | virtualStack.push(&temporaryList.last()); 347 | break; 348 | } 349 | case JoinToTuple: { /// join to ZTuple 350 | ZVariant::ZTuple tuple; 351 | 352 | int argsCount = virtualStack.pop()->toInt(); 353 | 354 | tuple.reserve(argsCount); 355 | 356 | for(int i = 0; i< argsCount; ++i) { 357 | // 栈中的数据都是保存在了temporaryList中 358 | // 此函数返回时其中的数据就全部被销毁了,Tuple 359 | // 中存储的是指针,指针指向的是temporaryList中的数据 360 | // 此exec可能是被其他函数调用的,因此Tuple中 361 | // 存储的可能是栈变量,函数执行结束后被其他作用 362 | // 域调用则访问到了无效指针,因此这里要new一个 363 | // 新的ZVariant 364 | tuple.prepend(new ZVariant(*virtualStack.pop())); 365 | } 366 | 367 | temporaryList << std::move(tuple); 368 | 369 | virtualStack.push(&temporaryList.last()); 370 | break; 371 | } 372 | case JoinToList: { /// join to Variant List 373 | QList list; 374 | 375 | int argsCount = virtualStack.pop()->toInt(); 376 | 377 | list.reserve(argsCount); 378 | 379 | for(int i = 0; i< argsCount; ++i) { 380 | list.insert(0, ZVariant::copy(*virtualStack.pop())); 381 | } 382 | 383 | temporaryList << ZVariant(list); 384 | 385 | virtualStack.push(&temporaryList.last()); 386 | break; 387 | } 388 | case Call: { 389 | QList args; 390 | 391 | int argsCount = virtualStack.pop()->toInt(); 392 | 393 | args.reserve(argsCount); 394 | 395 | for(int i = 0; i < argsCount; ++i) { 396 | args.insert(0, *virtualStack.pop()); 397 | } 398 | 399 | ZFunction *fun = virtualStack.pop()->toFunction(); 400 | 401 | if(fun) { 402 | if (fun->property("target").toBool()) 403 | args.prepend(*virtualStack.pop()); 404 | 405 | temporaryList << fun->call(args); 406 | virtualStack.push(&temporaryList.last()); 407 | } 408 | 409 | break; 410 | /// TODO 411 | } 412 | case Push: { 413 | ValueCode *valueCode = code->toValueCode(); 414 | virtualStack.push(valueCode->value.data()); 415 | break; 416 | } 417 | case Pop: { 418 | temporaryList.removeOne(*virtualStack.pop()); 419 | break; 420 | } 421 | case PopAll: { 422 | virtualStack.clear(); 423 | temporaryList.clear(); 424 | temporaryPropertyList.clear(); 425 | break; 426 | } 427 | case Goto: { 428 | i = code->toValueCode()->value->toInt() - 1; 429 | break; 430 | } 431 | case If: { 432 | if(!virtualStack.pop()->toBool()) 433 | i = code->toValueCode()->value->toInt() - 1; 434 | 435 | break; 436 | } 437 | case Children: { 438 | const ZVariant &value = *virtualStack.pop(); 439 | const ZVariant &target = *virtualStack.pop(); 440 | 441 | temporaryList << target[value]; 442 | virtualStack.push(&temporaryList.last()); 443 | break; 444 | } 445 | case Append: { 446 | const ZVariant &value = *virtualStack.pop(); 447 | ZVariant &target = *virtualStack.top(); 448 | 449 | target << value; 450 | break; 451 | } 452 | case Switch: { 453 | const QHash &val = qvariant_cast>(code->toValueCode()->value->toQVariant()); 454 | 455 | i = val.value(*virtualStack.pop(), -1) - 1; 456 | 457 | if(i < 0) { 458 | i = val.value(ZVariant(), -1) - 1; 459 | } 460 | break; 461 | } 462 | case InitObjectProperty: { 463 | ZObject *obj = new ZObject; 464 | int count = virtualStack.pop()->toInt(); 465 | 466 | for (int i = 0; i < count; ++i) { 467 | const char *name = virtualStack.pop()->toString().toLatin1().constData(); 468 | const ZVariant &value = *virtualStack.pop(); 469 | 470 | obj->setProperty(name, value); 471 | } 472 | 473 | temporaryList << ZVariant(obj); 474 | virtualStack.push(&temporaryList.last()); 475 | break; 476 | } 477 | default: break; 478 | } 479 | 480 | #ifndef QT_NO_DEBUG 481 | if(ENABLE_DEBUG) { 482 | qDebug().noquote() << "------------stack-start--------------"; 483 | 484 | for(int i = 0; i < virtualStack.count(); ++i) 485 | qDebug().noquote() << *virtualStack.value(i); 486 | 487 | qDebug().noquote() << "------------stack-end--------------"; 488 | } 489 | #endif 490 | } 491 | 492 | if(!virtualStack.isEmpty()) 493 | return *virtualStack.pop(); 494 | 495 | return ZCodeExecuter::constUndefined; 496 | } 497 | 498 | class ZUserFunction : public ZFunction 499 | { 500 | public: 501 | explicit ZUserFunction(ZCodeExecuter *e, ZObject *parent = 0) 502 | : ZFunction(parent), executer(e){} 503 | 504 | ZVariant call(const QList &args) const Q_DECL_OVERRIDE 505 | { 506 | int min_count = qMin(args.count(), executer->parameterList.count()); 507 | int i = 0; 508 | 509 | for(; i < min_count; ++i) { 510 | *executer->parameterList.at(i) = args.at(i); 511 | } 512 | 513 | for(; i < executer->parameterList.count(); ++i) { 514 | *executer->parameterList.at(i) = ZCodeExecuter::constUndefined; 515 | } 516 | 517 | /// sava current runtime stack 518 | QStack stack = ZCode::virtualStack; 519 | 520 | ZVariant retVal = ZCode::exec(executer->codeList); 521 | 522 | ZCode::virtualStack = stack; 523 | 524 | return retVal; 525 | } 526 | 527 | private: 528 | ZCodeExecuter *executer; 529 | }; 530 | 531 | ZCodeExecuter *ZCodeExecuter::currentCodeExecuter = Q_NULLPTR; 532 | YYFlexLexer *ZCodeExecuter::yyFlexLexer = Q_NULLPTR; 533 | QHash ZCodeExecuter::globalIdentifierHash; 534 | QHash> ZCodeExecuter::globalFunctionHash; 535 | QMap ZCodeExecuter::stringConstantMap; 536 | QMap ZCodeExecuter::numberConstantMap; 537 | ZVariant ZCodeExecuter::constTrue(true); 538 | ZVariant ZCodeExecuter::constFalse(false); 539 | ZVariant ZCodeExecuter::constUndefined; 540 | 541 | ZCodeExecuter::ZCodeExecuter() 542 | { 543 | 544 | } 545 | 546 | ZCodeExecuter::~ZCodeExecuter() 547 | { 548 | deleteAllCodeBlock(); 549 | deleteAllCode(); 550 | qDeleteAll(gotoLabelMap); 551 | } 552 | 553 | int ZCodeExecuter::eval(std::istream &s) 554 | { 555 | beginCodeBlock(CodeBlock::Function); 556 | 557 | YYFlexLexer *yyFlexLexer = new YYFlexLexer; 558 | YYParser *yyParser = new YYParser; 559 | 560 | yyFlexLexer->yyrestart(s); 561 | yyParser->set_debug_level(QByteArray(getenv("DEBUG_PARSE_LEVEL")).toInt()); 562 | 563 | this->yyFlexLexer = yyFlexLexer; 564 | int result = yyParser->parse(); 565 | this->yyFlexLexer = Q_NULLPTR; 566 | 567 | delete yyFlexLexer; 568 | delete yyParser; 569 | 570 | endCodeBlock(); 571 | 572 | deleteAllCodeBlock(); 573 | gotoLabelMap.clear(); 574 | 575 | // 如果语法解析成功 576 | if (result == 0) { 577 | bool ok; 578 | result = exec().toInt(&ok); 579 | 580 | if (!ok) 581 | return -1; 582 | } 583 | 584 | return result; 585 | } 586 | 587 | int ZCodeExecuter::eval(const char *fileName, bool *ok) 588 | { 589 | std::ifstream inFile; 590 | 591 | inFile.open(fileName, std::ios::in); 592 | 593 | if(ok) 594 | *ok = inFile.is_open(); 595 | 596 | if(!inFile.is_open()) 597 | return -1; 598 | 599 | return eval(inFile); 600 | } 601 | 602 | int ZCodeExecuter::eval(const QByteArray &code) 603 | { 604 | std::stringstream inStr; 605 | 606 | inStr << code.toStdString(); 607 | 608 | return eval(inStr); 609 | } 610 | 611 | ZSharedVariantPointer ZCodeExecuter::getIdentifier(const QByteArray &name) 612 | { 613 | ZSharedVariantPointer val = currentCodeBlock->identifiers.value(name); 614 | 615 | if(val) 616 | return val; 617 | 618 | val = currentCodeBlock->undefinedIdentifier.value(name); 619 | 620 | if(val) 621 | return val; 622 | 623 | val = new ZSharedVariant(); 624 | 625 | currentCodeBlock->undefinedIdentifier[name] = val; 626 | 627 | return val; 628 | } 629 | 630 | ZSharedVariant *ZCodeExecuter::createConstant(const QByteArray &value, ZVariant::Type type) 631 | { 632 | switch(type) { 633 | case ZVariant::Int: { 634 | ZVariant *val = numberConstantMap.value(value); 635 | 636 | if(!val) { 637 | val = new ZVariant(value.toInt()); 638 | numberConstantMap[value] = val; 639 | } 640 | 641 | return new ZSharedVariant(*val); 642 | } 643 | case ZVariant::Double: { 644 | ZVariant *val = numberConstantMap.value(value); 645 | 646 | if(!val) { 647 | val = new ZVariant(value.toDouble()); 648 | numberConstantMap[value] = val; 649 | } 650 | 651 | return new ZSharedVariant(*val); 652 | } 653 | case ZVariant::String: { 654 | ZVariant *val = stringConstantMap.value(value); 655 | 656 | if(!val) { 657 | val = new ZVariant(QString(value)); 658 | stringConstantMap[value] = val; 659 | } 660 | 661 | return new ZSharedVariant(*val); 662 | } 663 | case ZVariant::Bool: 664 | if(value == "true") 665 | return new ZSharedVariant(constTrue); 666 | else 667 | return new ZSharedVariant(constFalse); 668 | default: 669 | return new ZSharedVariant(constUndefined); 670 | } 671 | } 672 | 673 | ZSharedVariantPointer ZCodeExecuter::createFunction(ZCodeExecuter *executer) 674 | { 675 | return ZSharedVariantPointer(new ZSharedVariant(ZVariant(new ZUserFunction(executer)))); 676 | } 677 | 678 | ZCode *ZCodeExecuter::createCode(const ZCode::Action &action, const ZSharedVariantPointer &val) 679 | { 680 | if(val) { 681 | ValueCode *code = new ValueCode; 682 | 683 | code->action = action; 684 | code->value = val; 685 | 686 | return code; 687 | } 688 | 689 | ZCode *code = new ZCode; 690 | 691 | code->action = action; 692 | 693 | return code; 694 | } 695 | 696 | void ZCodeExecuter::beginCodeBlock(CodeBlock::Type type) 697 | { 698 | CodeBlock *block; 699 | 700 | if (type == CodeBlock::NormalFor || type == CodeBlock::While) { 701 | block = new LoopStructureCodeBlock; 702 | } else { 703 | block = new CodeBlock; 704 | } 705 | 706 | codeBlockList << block; 707 | 708 | block->type = type; 709 | block->beginCodeIndex = codeList.count(); 710 | block->parent = currentCodeBlock; 711 | 712 | currentCodeBlock = block; 713 | } 714 | 715 | void ZCodeExecuter::endCodeBlock() 716 | { 717 | for(ZSharedVariantPointer &val_pointer : currentCodeBlock->undefinedIdentifier) { 718 | const QByteArray &name = currentCodeBlock->undefinedIdentifier.key(val_pointer); 719 | CodeBlock *block = currentCodeBlock->parent; 720 | 721 | while(block) { 722 | ZSharedVariantPointer val = block->identifiers.value(name); 723 | 724 | if(val) { 725 | *val_pointer.data() = *val.constData(); 726 | break; 727 | } 728 | 729 | block = block->parent; 730 | } 731 | 732 | if(!block) { 733 | ZSharedVariant *val = globalIdentifierHash.value(name); 734 | 735 | if(val) { 736 | *val_pointer.data() = *val; 737 | } else { 738 | zError << "undefined reference:" << name; 739 | } 740 | } 741 | } 742 | 743 | currentCodeBlock->undefinedIdentifier.clear(); 744 | currentCodeBlock = currentCodeBlock->parent; 745 | } 746 | 747 | ZCodeExecuter *ZCodeExecuter::beginCodeExecuter() 748 | { 749 | ZCodeExecuter *executer = new ZCodeExecuter(); 750 | 751 | executer->parent = currentCodeExecuter; 752 | 753 | if(currentCodeExecuter) { 754 | executer->currentCodeBlock = currentCodeExecuter->currentCodeBlock; 755 | } 756 | 757 | currentCodeExecuter = executer; 758 | 759 | return executer; 760 | } 761 | 762 | ZCodeExecuter *ZCodeExecuter::endCodeExecuter() 763 | { 764 | ZCodeExecuter *executer = currentCodeExecuter; 765 | 766 | if(!executer) 767 | return executer; 768 | 769 | executer->deleteAllCodeBlock(); 770 | executer->gotoLabelMap.clear(); 771 | 772 | currentCodeExecuter = executer->parent; 773 | 774 | return executer; 775 | } 776 | 777 | Z_END_NAMESPACE 778 | 779 | QT_BEGIN_NAMESPACE 780 | QDebug operator<<(QDebug deg, const ZCode &var) 781 | { 782 | QString actionName = ZCode::actionName(var.action); 783 | 784 | deg << actionName.sprintf("%-10s", actionName.toLatin1().constData()); 785 | 786 | if(var.action == ZCode::Push) { 787 | deg << *var.toValueCode()->value.constData(); 788 | } else if(var.action == ZCode::Goto) { 789 | deg << var.toValueCode()->value->toInt(); 790 | } else if(var.action == ZCode::If) { 791 | deg << "if false goto:" << var.toValueCode()->value->toInt(); 792 | } else if(var.action == ZCode::Switch) { 793 | deg << "switch value:" << *var.toValueCode()->value; 794 | } 795 | 796 | return deg; 797 | } 798 | QT_END_NAMESPACE 799 | 800 | //#include "zcode.moc" 801 | --------------------------------------------------------------------------------