コード例 #1
0
        public ScriptEngine()
        {
            currentLexer = null;

            scopes    = new List <ScriptVar>();
            callStack = new Stack <ScriptVarLink>();

            Root = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            objectClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            stringClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            arrayClass  = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            Root.AddChild("Object", objectClass);
            Root.AddChild("String", stringClass);
            Root.AddChild("Array", arrayClass);
        }
コード例 #2
0
        public ScriptEngine(bool loadProviders = true)
        {
            _currentLexer = null;

            _scopes    = new Stack <ScriptVar>();
            _callStack = new Stack <string>();

            Root = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            _stringClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            _objectClass = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();
            _arrayClass  = (new ScriptVar(null, ScriptVar.Flags.Object)).Ref();

            Root.AddChild("String", _stringClass);
            Root.AddChild("Object", _objectClass);
            Root.AddChild("Array", _arrayClass);

            if (loadProviders)
            {
                LoadAllFunctionProviders();
            }
        }
コード例 #3
0
        public void AddObject(String[] ns, String objectName, ScriptVar val)
        {
            ScriptVar baseVar = Root;

            if (ns != null)
            {
                int x = 0;
                for (; x < ns.Length; x++)
                {
                    ScriptVarLink link = baseVar.FindChild(ns[x]);

                    if (link == null)
                    {
                        link = baseVar.AddChild(ns[x], new ScriptVar(null, ScriptVar.Flags.Object));
                    }

                    baseVar = link.Var;
                }
            }

            baseVar.AddChild(objectName, val);
        }
コード例 #4
0
        public void AddMethod(String funcProto, ScriptCallbackCB callback, Object userdata)
        {
            ScriptLex oldLex = _currentLexer;

            using (_currentLexer = new ScriptLex(funcProto))
            {
                ScriptVar baseVar = Root;

                _currentLexer.Match(ScriptLex.LexTypes.RFunction);
                String funcName = _currentLexer.TokenString;
                _currentLexer.Match(ScriptLex.LexTypes.Id);

                while (_currentLexer.TokenType == (ScriptLex.LexTypes) '.')
                {
                    _currentLexer.Match((ScriptLex.LexTypes) '.');
                    ScriptVarLink link = baseVar.FindChild(funcName);

                    if (link == null)
                    {
                        link = baseVar.AddChild(funcName, new ScriptVar(null, ScriptVar.Flags.Object));
                    }

                    baseVar  = link.Var;
                    funcName = _currentLexer.TokenString;
                    _currentLexer.Match(ScriptLex.LexTypes.Id);
                }

                ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native);
                funcVar.SetCallback(callback, userdata);

                ParseFunctionArguments(funcVar);

                baseVar.AddChild(funcName, funcVar);
            }

            _currentLexer = oldLex;
        }
コード例 #5
0
        public void AddMethod(String[] ns, String funcName, String[] args, ScriptCallbackCB callback, Object userdata)
        {
            String    fName   = funcName;
            ScriptVar baseVar = Root;

            if (ns != null)
            {
                int x = 0;
                for (; x < ns.Length; x++)
                {
                    ScriptVarLink link = baseVar.FindChild(ns[x]);

                    if (link == null)
                    {
                        link = baseVar.AddChild(ns[x], new ScriptVar(null, ScriptVar.Flags.Object));
                    }

                    baseVar = link.Var;
                }
            }


            ScriptVar funcVar = new ScriptVar(null, ScriptVar.Flags.Function | ScriptVar.Flags.Native);

            funcVar.SetCallback(callback, userdata);

            //do we have any arguments to create?
            if (args != null)
            {
                foreach (string arg in args)
                {
                    funcVar.AddChildNoDup(arg, null);
                }
            }

            baseVar.AddChild(fName, funcVar);
        }
コード例 #6
0
        public ScriptVar DeepCopy()
        {
            ScriptVar newVar = new ScriptVar();

            newVar.CopySimpleData(this);

            ScriptVarLink link = FirstChild;

            while (link != null)
            {
                ScriptVar copied = link.Name != PrototypeClassName?link.Var.DeepCopy() : link.Var;

                newVar.AddChild(link.Name, copied);

                link = link.Next;
            }

            return(newVar);
        }
コード例 #7
0
        private ScriptVarLink FunctionCall(ref bool execute, ScriptVarLink function, ScriptVar parent)
        {
            if (execute)
            {
                if (!function.Var.IsFunction)
                {
                    throw new ScriptException(String.Format("{0} is not a function", function.Name));
                }

                currentLexer.Match((ScriptLex.LexTypes) '(');
                var functionRoot = new ScriptVar(null, ScriptVar.Flags.Function);

                if (parent != null)
                {
                    functionRoot.AddChildNoDup("this", parent);
                }

                var v = function.Var.FirstChild;
                while (v != null)
                {
                    var value = Base(ref execute);
                    if (execute)
                    {
                        if (value.Var.IsBasic)
                        {
                            //pass by val
                            functionRoot.AddChild(v.Name, value.Var.DeepCopy());
                        }
                        else
                        {
                            //pass by ref
                            functionRoot.AddChild(v.Name, value.Var);
                        }
                    }

                    if (currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) ',');
                    }

                    v = v.Next;
                }

                currentLexer.Match((ScriptLex.LexTypes) ')');

                var returnVarLink = functionRoot.AddChild(ScriptVar.ReturnVarName, null);

                scopes.PushBack(functionRoot);

                //callStack.PushBack(string.Format("{0} from line {1}", function.Name, currentLexer.LineNumber));

                callStack.Push(function);

                if (function.Var.IsNative)
                {
                    var func = function.Var.GetCallback();
                    func?.Invoke(functionRoot, function.Var.GetCallbackUserData());
                }
                else
                {
                    var oldLex = currentLexer;
                    var newLex = new ScriptLex(function.Var.String);
                    currentLexer = newLex;

                    try
                    {
                        Block(ref execute);

                        execute = true;
                    }
                    catch
                    {
                        throw;
                    }
                    finally
                    {
                        currentLexer = oldLex;
                    }
                }

                callStack.Pop();
                scopes.PopBack();

                var returnVar = new ScriptVarLink(returnVarLink.Var, null);
                functionRoot.RemoveLink(returnVarLink);

                return(returnVar);
            }
            else
            {
                //not executing the function, just parsing it out
                currentLexer.Match((ScriptLex.LexTypes) '(');

                while (currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                {
                    Base(ref execute);

                    if (currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) ',');
                    }
                }

                currentLexer.Match((ScriptLex.LexTypes) ')');

                if (currentLexer.TokenType == (ScriptLex.LexTypes) '{') //WTF?
                {
                    Block(ref execute);
                }

                return(function);
            }
        }
コード例 #8
0
        private ScriptVarLink FunctionCall(ref bool execute, ScriptVarLink function, ScriptVar parent)
        {
            if (execute)
            {
                if (!function.Var.IsFunction)
                {
                    throw new ScriptException(String.Format("{0} is not a function", function.Name));
                }

                _currentLexer.Match((ScriptLex.LexTypes) '(');
                ScriptVar functionRoot = new ScriptVar(null, ScriptVar.Flags.Function);

                if (parent != null)
                {
                    functionRoot.AddChildNoDup("this", parent);
                }

                ScriptVarLink v = function.Var.FirstChild;
                while (v != null)
                {
                    ScriptVarLink value = Base(ref execute);
                    if (value.Var.IsBasic)
                    {
                        //pass by val
                        functionRoot.AddChild(v.Name, value.Var.DeepCopy());
                    }
                    else
                    {
                        //pass by ref
                        functionRoot.AddChild(v.Name, value.Var);
                    }

                    if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) ',');
                    }

                    v = v.Next;
                }

                _currentLexer.Match((ScriptLex.LexTypes) ')');

                ScriptVarLink returnVarLink = functionRoot.AddChild(ScriptVar.ReturnVarName, null);

                _scopes.Push(functionRoot);

                _callStack.Push(String.Format("{0} from line {1}", function.Name, _currentLexer.LineNumber));

                if (function.Var.IsNative)
                {
                    ScriptCallbackCB func = function.Var.GetCallback();
                    if (func != null)
                    {
                        func(functionRoot, function.Var.GetCallbackUserData(), parent);
                    }
                }
                else
                {
                    ScriptException ex     = null;
                    ScriptLex       oldLex = _currentLexer;
                    ScriptLex       newLex = new ScriptLex(function.Var.GetString());
                    _currentLexer = newLex;

                    try
                    {
                        Block(ref execute);

                        execute = true;
                    }
                    catch (ScriptException e)
                    {
                        ex = e;
                    }

                    _currentLexer = oldLex;

                    if (ex != null)
                    {
                        throw ex;
                    }
                }

                _callStack.Pop();
                _scopes.Pop();

                ScriptVarLink returnVar = new ScriptVarLink(returnVarLink.Var, null);
                functionRoot.RemoveLink(returnVarLink);

                return(returnVar);
            }

            //not executing the function, just parsing it out
            _currentLexer.Match((ScriptLex.LexTypes) '(');

            while (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
            {
                Base(ref execute);

                if (_currentLexer.TokenType != (ScriptLex.LexTypes) ')')
                {
                    _currentLexer.Match((ScriptLex.LexTypes) ',');
                }
            }

            _currentLexer.Match((ScriptLex.LexTypes) ')');

            if (_currentLexer.TokenType == (ScriptLex.LexTypes) '{')             //WTF?
            {
                Block(ref execute);
            }

            return(function);
        }
コード例 #9
0
        private void Statement(ref bool execute)
        {
            if (currentLexer.TokenType == (ScriptLex.LexTypes) '{')
            {
                //code block
                Block(ref execute);
            }
            else if (currentLexer.TokenType == (ScriptLex.LexTypes) ';')
            {
                //allow for multiple semi colon such as ;;;
                currentLexer.Match((ScriptLex.LexTypes) ';');
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RVar || currentLexer.TokenType == ScriptLex.LexTypes.RConst)
            {
                //creating variables
                //TODO: make this less shit

                var readOnly = currentLexer.TokenType == ScriptLex.LexTypes.RConst;

                currentLexer.Match(currentLexer.TokenType);

                while (currentLexer.TokenType != (ScriptLex.LexTypes) ';')
                {
                    ScriptVarLink a = null;
                    if (execute)
                    {
                        a = scopes.Back().FindChildOrCreate(currentLexer.TokenString, ScriptVar.Flags.Undefined, readOnly);
                    }

                    currentLexer.Match(ScriptLex.LexTypes.Id);

                    //get through the dots
                    while (currentLexer.TokenType == (ScriptLex.LexTypes) '.')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) '.');
                        if (execute)
                        {
                            var aLast = a;
                            if (aLast != null)
                            {
                                a = aLast.Var.FindChildOrCreate(currentLexer.TokenString);
                            }
                        }

                        currentLexer.Match(ScriptLex.LexTypes.Id);
                    }

                    //initialiser
                    if (currentLexer.TokenType == (ScriptLex.LexTypes) '=')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) '=');
                        var varLink = Base(ref execute);
                        if (execute)
                        {
                            if (a != null)
                            {
                                a.ReplaceWith(varLink);
                            }
                        }
                    }

                    if (currentLexer.TokenType != (ScriptLex.LexTypes) ';')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) ',');
                    }
                }

                currentLexer.Match((ScriptLex.LexTypes) ';');
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RIf)
            {
                //if condition
                currentLexer.Match(ScriptLex.LexTypes.RIf);
                currentLexer.Match((ScriptLex.LexTypes) '(');
                var varLink = Base(ref execute);
                currentLexer.Match((ScriptLex.LexTypes) ')');

                bool condition = execute && varLink.Var.Bool;
                bool noExecute = false;
                if (condition)
                {
                    Statement(ref execute);
                }
                else
                {
                    Statement(ref noExecute);
                }

                if (currentLexer.TokenType == ScriptLex.LexTypes.RElse)
                {
                    //else part of an if
                    currentLexer.Match(ScriptLex.LexTypes.RElse);

                    if (condition)
                    {
                        Statement(ref noExecute);
                    }
                    else
                    {
                        Statement(ref execute);
                    }
                }
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RWhile)
            {
                //while loop
                currentLexer.Match(ScriptLex.LexTypes.RWhile);
                currentLexer.Match((ScriptLex.LexTypes) '(');

                var whileConditionStart = currentLexer.TokenStart;
                var noExecute           = false;
                var condition           = Base(ref execute);
                var loopCondition       = execute && condition.Var.Bool;

                var whileCond = currentLexer.GetSubLex(whileConditionStart);
                currentLexer.Match((ScriptLex.LexTypes) ')');

                var whileBodyStart = currentLexer.TokenStart;

                if (loopCondition)
                {
                    Statement(ref execute);
                }
                else
                {
                    Statement(ref noExecute);
                }

                var whileBody = currentLexer.GetSubLex(whileBodyStart);
                var oldLex    = currentLexer;

                //TODO: possible maximum itteration limit?
                while (loopCondition)
                {
                    whileCond.Reset();

                    currentLexer = whileCond;

                    condition = Base(ref execute);

                    loopCondition = execute && condition.Var.Bool;

                    if (loopCondition)
                    {
                        whileBody.Reset();
                        currentLexer = whileBody;
                        Statement(ref execute);
                    }
                }

                currentLexer = oldLex;
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RFor)
            {
                //for loop
                currentLexer.Match(ScriptLex.LexTypes.RFor);
                currentLexer.Match((ScriptLex.LexTypes) '(');

                Statement(ref execute); //init

                var forConditionStart = currentLexer.TokenStart;
                var condition         = Base(ref execute);
                var noExecute         = false;
                var loopCondition     = execute && condition.Var.Bool;

                var forCondition = currentLexer.GetSubLex(forConditionStart);

                currentLexer.Match((ScriptLex.LexTypes) ';');

                var forIterStart = currentLexer.TokenStart;

                Base(ref noExecute);

                var forIter = currentLexer.GetSubLex(forIterStart);

                currentLexer.Match((ScriptLex.LexTypes) ')');

                var forBodyStart = currentLexer.TokenStart;

                if (loopCondition)
                {
                    Statement(ref execute);
                }
                else
                {
                    Statement(ref noExecute);
                }

                var forBody = currentLexer.GetSubLex(forBodyStart);
                var oldLex  = currentLexer;
                if (loopCondition)
                {
                    forIter.Reset();
                    currentLexer = forIter;

                    Base(ref execute);
                }

                //TODO: limit number of iterations?
                while (execute && loopCondition)
                {
                    forCondition.Reset();
                    currentLexer = forCondition;

                    condition = Base(ref execute);

                    loopCondition = condition.Var.Bool;

                    if (execute && loopCondition)
                    {
                        forBody.Reset();
                        currentLexer = forBody;

                        Statement(ref execute);
                    }

                    if (execute && loopCondition)
                    {
                        forIter.Reset();
                        currentLexer = forIter;

                        Base(ref execute);
                    }
                }

                currentLexer = oldLex;
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RReturn)
            {
                currentLexer.Match(ScriptLex.LexTypes.RReturn);

                ScriptVarLink res = null;
                if (currentLexer.TokenType != (ScriptLex.LexTypes) ';')
                {
                    res = Base(ref execute);
                }
                if (execute)
                {
                    var resultVar = scopes.Back().FindChild(ScriptVar.ReturnVarName);
                    if (resultVar != null)
                    {
                        resultVar.ReplaceWith(res);
                    }
                    else
                    {
                        //return statement outside of function???
                        System.Diagnostics.Trace.TraceWarning("Return statement outside of a function, what is going on?");
                    }
                    execute = false;
                }

                currentLexer.Match((ScriptLex.LexTypes) ';');
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RFunction)
            {
                //function
                var funcVar = ParseFunctionDefinition();
                if (execute)
                {
                    if (funcVar.Name == string.Empty)
                    {
                        //functions must have a name at statement level
                    }
                    else
                    {
                        var v = scopes.Back();
                        v.AddChildNoDup(funcVar.Name, funcVar.Var);
                    }
                }
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RTry)
            {
                var           tryBlock = ParseDefinition(ScriptLex.LexTypes.RTry);
                ScriptVarLink catchBlock = null, finallyBlock = null;

                var originalLexer = currentLexer;

                if (currentLexer.TokenType == ScriptLex.LexTypes.RCatch)
                {
                    catchBlock = ParseDefinition(ScriptLex.LexTypes.RCatch);
                }

                if (currentLexer.TokenType == ScriptLex.LexTypes.RFinally)
                {
                    finallyBlock = ParseDefinition(ScriptLex.LexTypes.RFinally);
                }

                try
                {
                    var oldLex = currentLexer;
                    var newLex = new ScriptLex(tryBlock.Var.String);
                    currentLexer = newLex;

                    Block(ref execute);

                    execute = true;

                    currentLexer = oldLex;
                }
                catch (JITException ex)
                {
                    if (catchBlock != null)
                    {
                        var catchScope = new ScriptVar(null, ScriptVar.Flags.Object);

                        var v = catchBlock?.Var?.FirstChild;
                        if (v != null)
                        {
                            catchScope.AddChild(v.Name, ex.VarObj);
                        }

                        var oldLex = currentLexer;
                        var newLex = new ScriptLex(catchBlock.Var.String);
                        currentLexer = newLex;

                        scopes.PushBack(catchScope);

                        Block(ref execute);

                        scopes.PopBack();

                        execute = true;

                        currentLexer = oldLex;
                    }
                    else
                    {
                        throw new ScriptException(ex.Message, ex);
                    }
                }
                finally
                {
                    if (finallyBlock != null)
                    {
                        var oldLex = currentLexer;
                        var newLex = new ScriptLex(finallyBlock.Var.String);
                        currentLexer = newLex;

                        Block(ref execute);

                        execute = true;

                        currentLexer = oldLex;
                    }
                }

                currentLexer = originalLexer;
            }
            else if (currentLexer.TokenType == ScriptLex.LexTypes.RThrow)
            {
                currentLexer.Match(ScriptLex.LexTypes.RThrow);

                ScriptVar message = new ScriptVar();

                if (currentLexer.TokenType == (ScriptLex.LexTypes) ';')
                {
                    currentLexer.Match((ScriptLex.LexTypes) ';');
                }
                else
                {
                    var res = Base(ref execute);
                    message = res.Var;
                }

                throw new JITException(message);
            }
            else
            {
                //execute a basic statement
                Base(ref execute);
                currentLexer.Match((ScriptLex.LexTypes) ';');
            }
        }
コード例 #10
0
        private ScriptVarLink Factor(ref bool execute)
        {
            if (currentLexer.TokenType == (ScriptLex.LexTypes) '(')
            {
                currentLexer.Match((ScriptLex.LexTypes) '(');
                var a = Base(ref execute);
                currentLexer.Match((ScriptLex.LexTypes) ')');
                return(a);
            }
            if (currentLexer.TokenType == ScriptLex.LexTypes.RTrue)
            {
                currentLexer.Match(ScriptLex.LexTypes.RTrue);
                return(new ScriptVarLink(new ScriptVar(1), null));
            }
            if (currentLexer.TokenType == ScriptLex.LexTypes.RFalse)
            {
                currentLexer.Match(ScriptLex.LexTypes.RFalse);
                return(new ScriptVarLink(new ScriptVar(0), null));
            }
            if (currentLexer.TokenType == ScriptLex.LexTypes.RNull)
            {
                currentLexer.Match(ScriptLex.LexTypes.RNull);
                return(new ScriptVarLink(new ScriptVar(null, ScriptVar.Flags.Null), null));
            }
            if (currentLexer.TokenType == ScriptLex.LexTypes.RUndefined)
            {
                currentLexer.Match(ScriptLex.LexTypes.RUndefined);
                return(new ScriptVarLink(new ScriptVar(null, ScriptVar.Flags.Undefined), null));
            }
            if (currentLexer.TokenType == ScriptLex.LexTypes.Id)
            {
                var a = execute ? FindInScopes(currentLexer.TokenString) : new ScriptVarLink(new ScriptVar(), null);

                ScriptVar parent = null;

                if (execute && a == null)
                {
                    a = new ScriptVarLink(new ScriptVar(), currentLexer.TokenString);
                }

                currentLexer.Match(ScriptLex.LexTypes.Id);

                while (currentLexer.TokenType == (ScriptLex.LexTypes) '(' || currentLexer.TokenType == (ScriptLex.LexTypes) '.' || currentLexer.TokenType == (ScriptLex.LexTypes) '[')
                {
                    if (currentLexer.TokenType == (ScriptLex.LexTypes) '(') // function call
                    {
                        a = FunctionCall(ref execute, a, parent);
                    }
                    else if (currentLexer.TokenType == (ScriptLex.LexTypes) '.') // child access
                    {
                        currentLexer.Match((ScriptLex.LexTypes) '.');
                        if (execute)
                        {
                            var name  = currentLexer.TokenString;
                            var child = a.Var.FindChild(name);

                            if (child == null)
                            {
                                child = FindInParentClasses(a.Var, name);
                            }

                            if (child == null)
                            {
                                if (a.Var.IsArray && name == "length")
                                {
                                    var length = a.Var.GetArrayLength();
                                    child = new ScriptVarLink(new ScriptVar(length), null);
                                }
                                else if (a.Var.IsString && name == "length")
                                {
                                    var length = a.Var.String.Length;
                                    child = new ScriptVarLink(new ScriptVar(length), null);
                                }
                                else
                                {
                                    child = a.Var.AddChild(name, null);
                                }
                            }

                            parent = a.Var;
                            a      = child;
                        }

                        currentLexer.Match(ScriptLex.LexTypes.Id);
                    }
                    else if (currentLexer.TokenType == (ScriptLex.LexTypes) '[') // array access
                    {
                        currentLexer.Match((ScriptLex.LexTypes) '[');
                        var index = Base(ref execute);
                        currentLexer.Match((ScriptLex.LexTypes) ']');

                        if (execute)
                        {
                            var child = a.Var.FindChildOrCreate(index.Var.String);
                            parent = a.Var;
                            a      = child;
                        }
                    }
                    else
                    {
                        throw new ScriptException("WTF?");
                    }
                }

                return(a);
            }

            if (currentLexer.TokenType == ScriptLex.LexTypes.Int || currentLexer.TokenType == ScriptLex.LexTypes.Float)
            {
                var a = new ScriptVar(currentLexer.TokenString, currentLexer.TokenType == ScriptLex.LexTypes.Int ? ScriptVar.Flags.Integer : ScriptVar.Flags.Double);
                currentLexer.Match(currentLexer.TokenType);
                return(new ScriptVarLink(a, null));
            }

            if (currentLexer.TokenType == ScriptLex.LexTypes.Str)
            {
                var a = new ScriptVar(currentLexer.TokenString, ScriptVar.Flags.String);
                currentLexer.Match(currentLexer.TokenType);
                return(new ScriptVarLink(a, null));
            }

            if (currentLexer.TokenType == (ScriptLex.LexTypes) '{')
            {
                var contents = new ScriptVar(null, ScriptVar.Flags.Object);
                //looking for JSON like objects
                currentLexer.Match((ScriptLex.LexTypes) '{');
                while (currentLexer.TokenType != (ScriptLex.LexTypes) '}')
                {
                    var id = currentLexer.TokenString;

                    if (currentLexer.TokenType == ScriptLex.LexTypes.Str)
                    {
                        currentLexer.Match(ScriptLex.LexTypes.Str);
                    }
                    else
                    {
                        currentLexer.Match(ScriptLex.LexTypes.Id);
                    }

                    currentLexer.Match((ScriptLex.LexTypes) ':');

                    if (execute)
                    {
                        var a = Base(ref execute);
                        contents.AddChild(id, a.Var);
                    }

                    if (currentLexer.TokenType != (ScriptLex.LexTypes) '}')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) ',');
                    }
                }
                currentLexer.Match((ScriptLex.LexTypes) '}');

                return(new ScriptVarLink(contents, null));
            }

            if (currentLexer.TokenType == (ScriptLex.LexTypes) '[')
            {
                int idx      = 0;
                var contents = new ScriptVar(null, ScriptVar.Flags.Array);
                //looking for JSON like arrays
                currentLexer.Match((ScriptLex.LexTypes) '[');
                while (currentLexer.TokenType != (ScriptLex.LexTypes) ']')
                {
                    if (execute)
                    {
                        var id = string.Format("{0}", idx);

                        var a = Base(ref execute);
                        contents.AddChild(id, a.Var);
                    }

                    if (currentLexer.TokenType != (ScriptLex.LexTypes) ']')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) ',');
                    }

                    idx++;
                }
                currentLexer.Match((ScriptLex.LexTypes) ']');

                return(new ScriptVarLink(contents, null));
            }

            if (currentLexer.TokenType == ScriptLex.LexTypes.RFunction)
            {
                var funcVar = ParseFunctionDefinition();
                if (funcVar.Name != string.Empty)
                {
                    System.Diagnostics.Trace.TraceWarning("Functions not defined at statement level are not supposed to have a name");
                }
                return(funcVar);
            }

            if (currentLexer.TokenType == ScriptLex.LexTypes.RNew) // new
            {
                currentLexer.Match(ScriptLex.LexTypes.RNew);

                var className = currentLexer.TokenString;
                if (execute)
                {
                    var classOrFuncObject = FindInScopes(className);
                    if (classOrFuncObject == null)
                    {
                        System.Diagnostics.Trace.TraceWarning("{0} is not a valid class name", className);
                        return(new ScriptVarLink(new ScriptVar(), null));
                    }

                    currentLexer.Match(ScriptLex.LexTypes.Id);

                    var obj     = new ScriptVar(null, ScriptVar.Flags.Object);
                    var objLink = new ScriptVarLink(obj, null);

                    if (classOrFuncObject.Var.IsFunction)
                    {
                        FunctionCall(ref execute, classOrFuncObject, obj);
                    }
                    else
                    {
                        obj.AddChild(ScriptVar.PrototypeClassName, classOrFuncObject.Var);

                        if (currentLexer.TokenType == (ScriptLex.LexTypes) '(')
                        {
                            currentLexer.Match((ScriptLex.LexTypes) '(');
                            currentLexer.Match((ScriptLex.LexTypes) ')');
                        }
                    }

                    return(objLink);
                }
                else
                {
                    currentLexer.Match(ScriptLex.LexTypes.Id);
                    if (currentLexer.TokenType == (ScriptLex.LexTypes) '(')
                    {
                        currentLexer.Match((ScriptLex.LexTypes) '(');
                        currentLexer.Match((ScriptLex.LexTypes) ')');
                    }
                }
            }

            if (currentLexer.TokenType == ScriptLex.LexTypes.RegExp)
            {
                var a = new ScriptVar(currentLexer.TokenString, ScriptVar.Flags.Regexp);
                currentLexer.Match(currentLexer.TokenType);
                return(new ScriptVarLink(a, null));
            }

            currentLexer.Match(ScriptLex.LexTypes.Eof);

            return(null);
        }
コード例 #11
0
        private ScriptVarLink Factor(ref bool execute)
        {
            if (_currentLexer.TokenType == (ScriptLex.LexTypes) '(')
            {
                _currentLexer.Match((ScriptLex.LexTypes) '(');
                ScriptVarLink a = Base(ref execute);
                _currentLexer.Match((ScriptLex.LexTypes) ')');
                return(a);
            }
            if (_currentLexer.TokenType == ScriptLex.LexTypes.RTrue)
            {
                _currentLexer.Match(ScriptLex.LexTypes.RTrue);
                return(new ScriptVarLink(new ScriptVar(1), null));
            }
            if (_currentLexer.TokenType == ScriptLex.LexTypes.RFalse)
            {
                _currentLexer.Match(ScriptLex.LexTypes.RTrue);
                return(new ScriptVarLink(new ScriptVar(0), null));
            }
            if (_currentLexer.TokenType == ScriptLex.LexTypes.RNull)
            {
                _currentLexer.Match(ScriptLex.LexTypes.RUndefined);
                return(new ScriptVarLink(new ScriptVar(null, ScriptVar.Flags.Null), null));
            }
            if (_currentLexer.TokenType == ScriptLex.LexTypes.RUndefined)
            {
                _currentLexer.Match(ScriptLex.LexTypes.RUndefined);
                return(new ScriptVarLink(new ScriptVar(null, ScriptVar.Flags.Undefined), null));
            }
            if (_currentLexer.TokenType == ScriptLex.LexTypes.Id)
            {
                ScriptVarLink a = execute ? FindInScopes(_currentLexer.TokenString) : new ScriptVarLink(new ScriptVar(), null);

                ScriptVar parent = null;

                if (execute && a == null)
                {
                    a = new ScriptVarLink(new ScriptVar(), _currentLexer.TokenString);
                }

                _currentLexer.Match(ScriptLex.LexTypes.Id);

                while (_currentLexer.TokenType == (ScriptLex.LexTypes) '(' || _currentLexer.TokenType == (ScriptLex.LexTypes) '.' || _currentLexer.TokenType == (ScriptLex.LexTypes) '[')
                {
                    if (_currentLexer.TokenType == (ScriptLex.LexTypes) '(')                    // function call
                    {
                        a = FunctionCall(ref execute, a, parent);
                    }
                    else if (_currentLexer.TokenType == (ScriptLex.LexTypes) '.')                    // child access
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) '.');
                        if (execute)
                        {
                            if (!a.Var.IsObject)
                            {
                                throw new ScriptException("Trying to call object member on non object type");
                            }

                            String        name  = _currentLexer.TokenString;
                            ScriptVarLink child = a.Var.FindChild(name);

                            if (child == null)
                            {
                                child = FindInParentClasses(a.Var, name);
                            }

                            if (child == null)
                            {
                                if (a.Var.IsArray && name == "length")
                                {
                                    Int32 length = a.Var.GetArrayLength();
                                    child = new ScriptVarLink(new ScriptVar(length), null);
                                }
                                else if (a.Var.IsString && name == "length")
                                {
                                    Int32 length = a.Var.GetString().Length;
                                    child = new ScriptVarLink(new ScriptVar(length), null);
                                }
                                else
                                {
                                    child = a.Var.AddChild(name, null);
                                }
                            }

                            parent = a.Var;
                            a      = child;
                        }

                        _currentLexer.Match(ScriptLex.LexTypes.Id);
                    }
                    else if (_currentLexer.TokenType == (ScriptLex.LexTypes) '[')                    // array access
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) '[');
                        ScriptVarLink index = Base(ref execute);
                        _currentLexer.Match((ScriptLex.LexTypes) ']');

                        if (execute)
                        {
                            ScriptVarLink child = a.Var.FindChildOrCreate(index.Var.GetString());
                            parent = a.Var;
                            a      = child;
                        }
                    }
                    else
                    {
                        throw new ScriptException("WTF?");
                    }
                }

                return(a);
            }

            if (_currentLexer.TokenType == ScriptLex.LexTypes.Int || _currentLexer.TokenType == ScriptLex.LexTypes.Float)
            {
                ScriptVar a = new ScriptVar(_currentLexer.TokenString, _currentLexer.TokenType == ScriptLex.LexTypes.Int ? ScriptVar.Flags.Integer : ScriptVar.Flags.Double);
                _currentLexer.Match(_currentLexer.TokenType);
                return(new ScriptVarLink(a, null));
            }

            if (_currentLexer.TokenType == ScriptLex.LexTypes.Str)
            {
                ScriptVar a = new ScriptVar(_currentLexer.TokenString, ScriptVar.Flags.String);
                _currentLexer.Match(_currentLexer.TokenType);
                return(new ScriptVarLink(a, null));
            }

            if (_currentLexer.TokenType == (ScriptLex.LexTypes) '{')
            {
                ScriptVar contents = new ScriptVar(null, ScriptVar.Flags.Object);
                //looking for JSON like objects
                _currentLexer.Match((ScriptLex.LexTypes) '{');
                while (_currentLexer.TokenType != (ScriptLex.LexTypes) '}')
                {
                    String id = _currentLexer.TokenString;

                    if (_currentLexer.TokenType == ScriptLex.LexTypes.Str)
                    {
                        _currentLexer.Match(ScriptLex.LexTypes.Str);
                    }
                    else
                    {
                        _currentLexer.Match(ScriptLex.LexTypes.Id);
                    }

                    _currentLexer.Match((ScriptLex.LexTypes) ':');

                    if (execute)
                    {
                        ScriptVarLink a = Base(ref execute);
                        contents.AddChild(id, a.Var);
                    }

                    if (_currentLexer.TokenType != (ScriptLex.LexTypes) '}')
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) ',');
                    }
                }
                _currentLexer.Match((ScriptLex.LexTypes) '}');

                return(new ScriptVarLink(contents, null));
            }

            if (_currentLexer.TokenType == (ScriptLex.LexTypes) '[')
            {
                Int32     idx      = 0;
                ScriptVar contents = new ScriptVar(null, ScriptVar.Flags.Array);
                //looking for JSON like arrays
                _currentLexer.Match((ScriptLex.LexTypes) '[');
                while (_currentLexer.TokenType != (ScriptLex.LexTypes) ']')
                {
                    if (execute)
                    {
                        String id = String.Format("{0}", idx);

                        ScriptVarLink a = Base(ref execute);
                        contents.AddChild(id, a.Var);
                    }

                    if (_currentLexer.TokenType != (ScriptLex.LexTypes) ']')
                    {
                        _currentLexer.Match((ScriptLex.LexTypes) ',');
                    }

                    idx++;
                }
                _currentLexer.Match((ScriptLex.LexTypes) ']');

                return(new ScriptVarLink(contents, null));
            }

            if (_currentLexer.TokenType == ScriptLex.LexTypes.RFunction)
            {
                ScriptVarLink funcVar = ParseFunctionDefinition();
                if (funcVar.Name != String.Empty)
                {
                    System.Diagnostics.Trace.TraceWarning("Functions not defined at statement level are not supposed to have a name");
                }
                return(funcVar);
            }

            if (_currentLexer.TokenType == ScriptLex.LexTypes.RNew)             // new
            {
                _currentLexer.Match(ScriptLex.LexTypes.RNew);

                String className = _currentLexer.TokenString;
                if (execute)
                {
                    ScriptVarLink classOrFuncObject = FindInScopes(className);
                    if (classOrFuncObject == null)
                    {
                        System.Diagnostics.Trace.TraceWarning("{0} is not a valid class name", className);
                        return(new ScriptVarLink(new ScriptVar(), null));
                    }

                    _currentLexer.Match(ScriptLex.LexTypes.Id);

                    ScriptVar     obj     = new ScriptVar(null, ScriptVar.Flags.Object);
                    ScriptVarLink objLink = new ScriptVarLink(obj, null);

                    if (classOrFuncObject.Var.IsFunction)
                    {
                        FunctionCall(ref execute, classOrFuncObject, obj);
                    }
                    else
                    {
                        //creating new instance of a class
                        if (classOrFuncObject.Var.ClassType != null)
                        {
                            obj.ClassInstance = Activator.CreateInstance(classOrFuncObject.Var.ClassType);
                        }

                        obj.AddChild(ScriptVar.PrototypeClassName, classOrFuncObject.Var);

                        if (_currentLexer.TokenType == (ScriptLex.LexTypes) '(')
                        {
                            _currentLexer.Match((ScriptLex.LexTypes) '(');
                            _currentLexer.Match((ScriptLex.LexTypes) ')');
                        }
                    }

                    return(objLink);
                }

                _currentLexer.Match(ScriptLex.LexTypes.Id);
                if (_currentLexer.TokenType == (ScriptLex.LexTypes) '(')
                {
                    _currentLexer.Match((ScriptLex.LexTypes) '(');
                    _currentLexer.Match((ScriptLex.LexTypes) ')');
                }
            }

            _currentLexer.Match(ScriptLex.LexTypes.Eof);

            return(null);
        }