예제 #1
0
        internal ScriptContext(ScriptProcessor processor, ScriptContext parent)
        {
            _processor = processor;
            Parent = parent;

            This = parent != null ? parent.This : new GlobalContextObject(this);
        }
예제 #2
0
        private SObject ExecuteAsync(ScriptStatement statement)
        {
            // statement inside async block gets executed in its own thread.
            // cannot rely on any variables from outside being set on time.

            string taskName = statement.Code.Remove(0, statement.Code.IndexOf("(") + 1);
            taskName = taskName.Remove(taskName.LastIndexOf(")")).Trim();

            if (string.IsNullOrWhiteSpace(taskName))
                taskName = Guid.NewGuid().ToString();

            _index++;
            var nextStatement = _statements[_index];

            var processor = new ScriptProcessor(Context, GetLineNumber());

            lock (Context.AsyncTasks)
                Context.AsyncTasks.Add(taskName);

            Console.WriteLine($"Start async task ({taskName})");

            Task.Run(() =>
            {
                processor.ExecuteStatement(nextStatement);

                lock (Context.AsyncTasks)
                    Context.AsyncTasks.Remove(taskName);
            });

            return Undefined;
        }
예제 #3
0
        static void Main(string[] args)
        {
            bool exit = false;
            var processor = new ScriptProcessor();

            while (!exit)
            {
                Console.Write("< ");
                string input = Console.ReadLine();
                
                var result = processor.Run(input);

                if (result.TypeOf() == Types.SObject.LITERAL_TYPE_ERROR)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Types.SError error = (Types.SError)result;

                    Console.WriteLine("x " + ((Types.SString)error.Members["type"].Data).Value + ": " +
                                      ((Types.SString)error.Members["message"].Data).Value);

                    Console.ForegroundColor = ConsoleColor.White;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.WriteLine("> " + result.ToScriptSource());
                    Console.ForegroundColor = ConsoleColor.White;
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Creates a new <see cref="ScriptProcessor"/> and runs the provided source code.
        /// </summary>
        internal static ScriptProcessor GetRun(string source)
        {
            var processor = new ScriptProcessor();

            processor.Run(source);

            return processor;
        }
예제 #5
0
        private static ScriptProcessor CreateProcessor()
        {
            var processor = new ScriptProcessor(_prototypeBuffer);

            ScriptContextManipulator.SetCallbackExecuteMethod(processor, ExecuteMethod);

            return processor;
        }
예제 #6
0
파일: World.cs 프로젝트: nilllzz/Pokemon3D
        public static SObject getEntity(ScriptProcessor processor, SObject[] parameters)
        {
            object[] netObjects;
            if (EnsureTypeContract(parameters, new[] { typeof(string) }, out netObjects))
            {
                var entity = new EntityWrapper {id = (string)netObjects[0]};

                return ScriptInAdapter.Translate(processor, entity);
            }

            return ScriptInAdapter.GetUndefined(processor);
        }
예제 #7
0
        public static SObject Eval(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
                return processor.Undefined;

            string code;
            if (parameters[0] is SString)
                code = ((SString)parameters[0]).Value;
            else
                code = parameters[0].ToString(processor).Value;

            var evalProcessor = new ScriptProcessor(processor.Context);
            return evalProcessor.Run(code);
        }
예제 #8
0
        public static SObject ToComplex(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
                return processor.Undefined;

            if (parameters[0] is SString)
                return processor.Context.CreateInstance("String", new SObject[] { parameters[0] });
            else if (parameters[0] is SNumber)
                return processor.Context.CreateInstance("Number", new SObject[] { parameters[0] });
            else if (parameters[0] is SBool)
                return processor.Context.CreateInstance("Boolean", new SObject[] { parameters[0] });
            else
                return parameters[0]; // returns the input object, if no conversion was conducted.
        }
예제 #9
0
        private static void InitializePrototypeBuffer()
        {
            // load all defined prototypes once to store them in a buffer.
            // these prototypes get added to all newly created ScriptProcessors.

            _prototypeBuffer = new List<SObject>();
            var processor = new ScriptProcessor();

            foreach (var assembly in GetSourceAssemblies())
            {
                foreach (var t in assembly.GetTypes().Where(t => t.GetCustomAttributes(typeof(ScriptPrototypeAttribute), true).Length > 0))
                    _prototypeBuffer.Add(ScriptInAdapter.Translate(processor, t));
            }
        }
예제 #10
0
파일: World.cs 프로젝트: nilllzz/Pokemon3D
        public static SObject load(ScriptProcessor processor, SObject[] parameters)
        {
            object[] netObjects;
            if (EnsureTypeContract(parameters, new[] { typeof(string), typeof(Vector3Wrapper) }, out netObjects))
            {
                var screen = (OverworldScreen)GameProvider.GameInstance.GetService<ScreenManager>().CurrentScreen;

                var position = netObjects[1] as Vector3Wrapper;
                if (position != null)
                    screen.ActiveWorld.LoadMap(netObjects[0] as string, position.X, position.Y, position.Z);
            }

            return ScriptInAdapter.GetUndefined(processor);
        }
예제 #11
0
        public static SObject NameOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
                return processor.Undefined;

            if (parameters[0] is SProtoObject)
            {
                var protoObj = (SProtoObject)parameters[0];
                return processor.CreateString(protoObj.IsProtoInstance ? protoObj.Prototype.Name : protoObj.TypeOf());
            }
            else
            {
                return processor.CreateString(parameters[0].TypeOf());
            }
        }
예제 #12
0
        private static SObject ExecuteMethod(ScriptProcessor processor, string className, string methodName, SObject[] parameters)
        {
            if (_apiClasses.ContainsKey(className))
            {
                var method = _apiClasses[className].FirstOrDefault(m => m.Name == methodName);

                if (method != null)
                {
                    var result = method.Invoke(null, new object[] { processor, parameters });
                    return (SObject)result;
                }
            }

            // fallback, in case no class/method was found:
            return ScriptInAdapter.GetUndefined(processor);
        }
예제 #13
0
        public static SObject NameOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
            {
                return(processor.Undefined);
            }

            if (parameters[0] is SProtoObject)
            {
                var protoObj = (SProtoObject)parameters[0];
                return(processor.CreateString(protoObj.IsProtoInstance ? protoObj.Prototype.Name : protoObj.TypeOf()));
            }
            else
            {
                return(processor.CreateString(parameters[0].TypeOf()));
            }
        }
예제 #14
0
        public static SObject show(ScriptProcessor processor, SObject[] parameters)
        {
            object[] netObjects;
            if (EnsureTypeContract(parameters, new[] { typeof(string) }, out netObjects))
            {
                var text = (string)netObjects[0];

                var screen = (OverworldScreen)GameProvider.GameInstance.GetService<ScreenManager>().CurrentScreen;
                var uiElement = new MessageOverworldUIElement(text);

                screen.AddUiElement(uiElement);
                uiElement.IsActive = true;

                BlockThreadUntilCondition(() => !uiElement.IsActive);

                screen.RemoveUiElement(uiElement);
            }

            return ScriptInAdapter.GetUndefined(processor);
        }
예제 #15
0
        public static SObject IsFinite(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
            {
                return(processor.Undefined);
            }

            double dbl;

            if (parameters[0] is SNumber)
            {
                dbl = ((SNumber)parameters[0]).Value;
            }
            else
            {
                dbl = parameters[0].ToNumber(processor).Value;
            }

            return(processor.CreateBool(!(double.IsNaN(dbl) || double.IsInfinity(dbl))));
        }
예제 #16
0
        public static SObject DoSync(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            string[] tasks = processor.Context.Parent.AsyncTasks.ToArray();
            if (parameters.Length >= 1)
            {
                var param = SObject.Unbox(parameters[0]);
                if (param is SString)
                {
                    tasks = new[] { (param as SString).Value }
                }
                ;
                else if (param is SArray)
                {
                    tasks = (param as SArray).ArrayMembers.Select(m => m.ToString(processor).Value).ToArray();
                }
            }

            Console.WriteLine($"Sync tasks: ({string.Join(",", tasks)})");

            SpinWait.SpinUntil(() => tasks.All(t => !processor.Context.Parent.AsyncTasks.Contains(t)));
            return(processor.Undefined);
        }
예제 #17
0
        public static SObject Eval(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
            {
                return(processor.Undefined);
            }

            string code;

            if (parameters[0] is SString)
            {
                code = ((SString)parameters[0]).Value;
            }
            else
            {
                code = parameters[0].ToString(processor).Value;
            }

            var evalProcessor = new ScriptProcessor(processor.Context);

            return(evalProcessor.Run(code));
        }
예제 #18
0
        public static SObject ToPrimitive(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
            {
                return(processor.Undefined);
            }

            if (parameters[0] is SString)
            {
                return(processor.CreateString(((SString)parameters[0]).Value));
            }
            else if (parameters[0] is SNumber)
            {
                return(processor.CreateNumber(((SNumber)parameters[0]).Value));
            }
            else if (parameters[0] is SBool)
            {
                return(processor.CreateBool(((SBool)parameters[0]).Value));
            }
            else
            {
                return(parameters[0]); // returns the input object, if no conversion was conducted.
            }
        }
예제 #19
0
        public static SObject ToComplex(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
            {
                return(processor.Undefined);
            }

            if (parameters[0] is SString)
            {
                return(processor.Context.CreateInstance("String", new SObject[] { parameters[0] }));
            }
            else if (parameters[0] is SNumber)
            {
                return(processor.Context.CreateInstance("Number", new SObject[] { parameters[0] }));
            }
            else if (parameters[0] is SBool)
            {
                return(processor.Context.CreateInstance("Boolean", new SObject[] { parameters[0] }));
            }
            else
            {
                return(parameters[0]); // returns the input object, if no conversion was conducted.
            }
        }
예제 #20
0
        private SObject ExecuteExecutable(ScriptStatement statement)
        {
            if (statement.IsCompoundStatement)
            {
                var processor = new ScriptProcessor(Context, GetLineNumber());

                // Remove { and }:
                var code = statement.Code.Remove(0, 1);
                code = code.Remove(code.Length - 1, 1);

                var returnObject = processor.Run(code);

                _breakIssued    = processor._breakIssued;
                _continueIssued = processor._continueIssued;
                _returnIssued   = processor._returnIssued;

                return(returnObject);
            }
            else
            {
                var exp = ResolveParentheses(statement.Code).Trim();

                #region QuickConvert

                // have quick conversions for small statements here
                // parameter statements are much faster that way:
                if (exp == SObject.LITERAL_BOOL_TRUE)
                {
                    return(CreateBool(true));
                }
                else if (exp == SObject.LITERAL_BOOL_FALSE)
                {
                    return(CreateBool(false));
                }
                else if (exp == SObject.LITERAL_UNDEFINED || exp == "")
                {
                    return(Undefined);
                }
                else if (exp == SObject.LITERAL_NULL)
                {
                    return(Null);
                }
                else if (exp.StartsWith("\"") && exp.EndsWith("\"") && !exp.Remove(exp.Length - 1, 1).Remove(0, 1).Contains("\""))
                {
                    return(CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 1)));
                }
                else if (exp.All(char.IsDigit))
                {
                    double num;
                    SNumber.TryParse(exp, out num);
                    return(CreateNumber(num));
                }

                #endregion

                if (exp.Contains("=>"))
                {
                    exp = EvaluateLambda(exp);
                }
                if (exp.Contains("."))
                {
                    exp = EvaluateOperator(exp, ".");
                }
                if (exp.Contains("++"))
                {
                    exp = EvaluateOperator(exp, "++");
                }
                if (exp.Contains("--"))
                {
                    exp = EvaluateOperator(exp, "--");
                }
                if (exp.Contains("!"))
                {
                    exp = EvaluateReverseBool(exp);
                }
                if (exp.Contains("**"))
                {
                    exp = EvaluateOperator(exp, "**");
                }
                if (exp.Contains("*"))
                {
                    exp = EvaluateOperator(exp, "*");
                }
                if (exp.Contains("/"))
                {
                    exp = EvaluateOperator(exp, "/");
                }
                if (exp.Contains("%"))
                {
                    exp = EvaluateOperator(exp, "%");
                }
                if (exp.Contains("+"))
                {
                    exp = EvaluateOperator(exp, "+");
                }
                if (exp.Contains("-"))
                {
                    exp = EvaluateOperator(exp, "-");
                }
                if (exp.Contains("<="))
                {
                    exp = EvaluateOperator(exp, "<=");
                }
                if (exp.Contains(">="))
                {
                    exp = EvaluateOperator(exp, ">=");
                }
                if (exp.Contains("<"))
                {
                    exp = EvaluateOperator(exp, "<");
                }
                if (exp.Contains(">"))
                {
                    exp = EvaluateOperator(exp, ">");
                }
                if (exp.Contains("==="))
                {
                    exp = EvaluateOperator(exp, "===");
                }
                if (exp.Contains("!=="))
                {
                    exp = EvaluateOperator(exp, "!==");
                }
                if (exp.Contains("=="))
                {
                    exp = EvaluateOperator(exp, "==");
                }
                if (exp.Contains("!="))
                {
                    exp = EvaluateOperator(exp, "!=");
                }
                if (exp.Contains("&&"))
                {
                    exp = EvaluateOperator(exp, "&&");
                }
                if (exp.Contains("||"))
                {
                    exp = EvaluateOperator(exp, "||");
                }

                return(ToScriptObject(exp));
            }
        }
예제 #21
0
        private SObject ExecuteFor(ScriptStatement statement)
        {
            var exp = statement.Code;

            var forCode = exp.Remove(0, exp.IndexOf("for") + "for".Length).Trim().Remove(0, 1); // Remove "for" and "(".
            forCode = forCode.Remove(forCode.Length - 1, 1); // Remove ")".

            var forStatements = StatementProcessor.GetStatements(this, forCode);

            if (forStatements.Length == 0)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")");
            else if (forStatements.Length == 1)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_INITIALIZER);
            else if (forStatements.Length == 2)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONDITION);
            else if (forStatements.Length > 3)
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONTROL);

            var processor = new ScriptProcessor(Context, GetLineNumber());

            var forInitializer = forStatements[0];
            var forCondition = forStatements[1];
            var forControl = forStatements[2];

            if (forInitializer.Code.Length > 0)
                processor.ExecuteStatement(forInitializer);

            _index++;

            if (_statements.Length > _index)
            {
                var stayInFor = true;
                var executeStatement = _statements[_index];
                var returnObject = Undefined;

                while (stayInFor)
                {
                    if (forCondition.Code.Length > 0)
                    {
                        var conditionResult = processor.ExecuteStatement(forCondition);

                        if (conditionResult is SBool)
                            stayInFor = ((SBool)conditionResult).Value;
                        else
                            stayInFor = conditionResult.ToBool(this).Value;
                    }

                    if (stayInFor)
                    {
                        returnObject = processor.ExecuteStatement(executeStatement);

                        if (processor._returnIssued || processor._breakIssued)
                        {
                            _breakIssued = false;
                            _returnIssued = processor._returnIssued;
                            stayInFor = false;
                        }
                        else if (forControl.Code.Length > 0)
                        {
                            processor.ExecuteStatement(forControl);
                        }
                    }
                }

                return returnObject;
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
예제 #22
0
        public static SObject ToPrimitive(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
                return processor.Undefined;

            if (parameters[0] is SString)
                return processor.CreateString(((SString)parameters[0]).Value);
            else if (parameters[0] is SNumber)
                return processor.CreateNumber(((SNumber)parameters[0]).Value);
            else if (parameters[0] is SBool)
                return processor.CreateBool(((SBool)parameters[0]).Value);
            else
                return parameters[0]; // returns the input object, if no conversion was conducted.
        }
예제 #23
0
 public static SObject TypeOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) =>
     parameters.Length == 0 ? processor.Undefined : processor.CreateString(parameters[0].TypeOf());
예제 #24
0
        private SObject ExecuteExecutable(ScriptStatement statement)
        {
            if (statement.IsCompoundStatement)
            {
                var processor = new ScriptProcessor(Context, GetLineNumber());

                // Remove { and }:
                var code = statement.Code.Remove(0, 1);
                code = code.Remove(code.Length - 1, 1);

                var returnObject = processor.Run(code);

                _breakIssued = processor._breakIssued;
                _continueIssued = processor._continueIssued;
                _returnIssued = processor._returnIssued;

                return returnObject;
            }
            else
            {
                var exp = ResolveParentheses(statement.Code).Trim();

                #region QuickConvert

                // have quick conversions for small statements here
                // parameter statements are much faster that way:
                if (exp == SObject.LITERAL_BOOL_TRUE)
                {
                    return CreateBool(true);
                }
                else if (exp == SObject.LITERAL_BOOL_FALSE)
                {
                    return CreateBool(false);
                }
                else if (exp == SObject.LITERAL_UNDEFINED || exp == "")
                {
                    return Undefined;
                }
                else if (exp == SObject.LITERAL_NULL)
                {
                    return Null;
                }
                else if (exp.StartsWith("\"") && exp.EndsWith("\"") && !exp.Remove(exp.Length - 1, 1).Remove(0, 1).Contains("\""))
                {
                    return CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 1));
                }
                else if (exp.All(char.IsDigit))
                {
                    double num;
                    SNumber.TryParse(exp, out num);
                    return CreateNumber(num);
                }

                #endregion

                if (exp.Contains("=>"))
                    exp = EvaluateLambda(exp);
                if (exp.Contains("."))
                    exp = EvaluateOperator(exp, ".");
                if (exp.Contains("++"))
                    exp = EvaluateOperator(exp, "++");
                if (exp.Contains("--"))
                    exp = EvaluateOperator(exp, "--");
                if (exp.Contains("!"))
                    exp = EvaluateReverseBool(exp);
                if (exp.Contains("**"))
                    exp = EvaluateOperator(exp, "**");
                if (exp.Contains("*"))
                    exp = EvaluateOperator(exp, "*");
                if (exp.Contains("/"))
                    exp = EvaluateOperator(exp, "/");
                if (exp.Contains("%"))
                    exp = EvaluateOperator(exp, "%");
                if (exp.Contains("+"))
                    exp = EvaluateOperator(exp, "+");
                if (exp.Contains("-"))
                    exp = EvaluateOperator(exp, "-");
                if (exp.Contains("<="))
                    exp = EvaluateOperator(exp, "<=");
                if (exp.Contains(">="))
                    exp = EvaluateOperator(exp, ">=");
                if (exp.Contains("<"))
                    exp = EvaluateOperator(exp, "<");
                if (exp.Contains(">"))
                    exp = EvaluateOperator(exp, ">");
                if (exp.Contains("==="))
                    exp = EvaluateOperator(exp, "===");
                if (exp.Contains("!=="))
                    exp = EvaluateOperator(exp, "!==");
                if (exp.Contains("=="))
                    exp = EvaluateOperator(exp, "==");
                if (exp.Contains("!="))
                    exp = EvaluateOperator(exp, "!=");
                if (exp.Contains("&&"))
                    exp = EvaluateOperator(exp, "&&");
                if (exp.Contains("||"))
                    exp = EvaluateOperator(exp, "||");

                return ToScriptObject(exp);
            }
        }
예제 #25
0
 public static SObject TypeOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) =>
 parameters.Length == 0 ? processor.Undefined : processor.CreateString(parameters[0].TypeOf());
예제 #26
0
 public static SObject SizeOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) =>
     parameters.Length == 0 ? processor.Undefined : processor.CreateNumber(parameters[0].SizeOf());
예제 #27
0
        public static SObject IsFinite(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            if (parameters.Length == 0)
                return processor.Undefined;

            double dbl;
            if (parameters[0] is SNumber)
                dbl = ((SNumber)parameters[0]).Value;
            else
                dbl = parameters[0].ToNumber(processor).Value;

            return processor.CreateBool(!(double.IsNaN(dbl) || double.IsInfinity(dbl)));
        }
예제 #28
0
        public static SObject DoSync(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters)
        {
            string[] tasks = processor.Context.Parent.AsyncTasks.ToArray();
            if (parameters.Length >= 1)
            {
                var param = SObject.Unbox(parameters[0]);
                if (param is SString)
                    tasks = new[] { (param as SString).Value };
                else if (param is SArray)
                {
                    tasks = (param as SArray).ArrayMembers.Select(m => m.ToString(processor).Value).ToArray();
                }
            }

            Console.WriteLine($"Sync tasks: ({string.Join(",", tasks)})");

            SpinWait.SpinUntil(() => tasks.All(t => !processor.Context.Parent.AsyncTasks.Contains(t)));
            return processor.Undefined;
        }
예제 #29
0
        private SObject ExecuteTry(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp != "try")
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_BEFORE_TRY);

            _index++;
            if (_statements.Length > _index)
            {
                var executeStatement = _statements[_index];
                var encounteredError = false;
                var foundCatch = false;
                var foundFinally = false;
                var foundMatchingCatch = false;
                SObject errorObject = null;
                var returnObject = Undefined;

                try
                {
                    returnObject = ExecuteStatement(executeStatement);
                }
                catch (ScriptException ex)
                {
                    encounteredError = true;
                    errorObject = ex.ErrorObject;
                }

                if (encounteredError)
                {
                    var endedCatchSearch = false;
                    var findCatchIndex = _index + 1;
                    while (findCatchIndex < _statements.Length && !endedCatchSearch)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            _index = findCatchIndex + 1;

                            if (_statements.Length > _index)
                            {
                                if (!foundMatchingCatch)
                                {
                                    var catchExecuteStatement = _statements[_index];
                                    foundCatch = true;

                                    var catchCode = _statements[findCatchIndex].Code;
                                    var errorVarName = "";

                                    if (catchCode != "catch")
                                    {
                                        catchCode = catchCode.Remove(0, "catch".Length).Trim().Remove(0, 1);
                                        catchCode = catchCode.Remove(catchCode.Length - 1, 1);
                                        errorVarName = catchCode.Trim();
                                    }

                                    if (Regex.IsMatch(catchCode, REGEX_CATCHCONDITION))
                                    {
                                        errorVarName = catchCode.Remove(catchCode.IndexOf(" "));
                                        string conditionCode = catchCode.Remove(0, catchCode.IndexOf("if") + 3);

                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);

                                        var conditionResult = processor.ExecuteStatement(new ScriptStatement(conditionCode));

                                        if (conditionResult is SBool)
                                            foundMatchingCatch = ((SBool)conditionResult).Value;
                                        else
                                            foundMatchingCatch = conditionResult.ToBool(this).Value;

                                        if (foundMatchingCatch)
                                            returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                    }
                                    else
                                    {
                                        foundMatchingCatch = true;
                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);
                                        returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                    }
                                }
                            }
                            else
                            {
                                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
                            }
                        }
                        else
                        {
                            // end search if different statement type appears:
                            endedCatchSearch = true;
                        }

                        findCatchIndex += 2;
                    }
                }
                else
                {
                    var findCatchIndex = _index + 1;
                    while (findCatchIndex < _statements.Length)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            foundCatch = true;
                            _index = findCatchIndex + 1;
                        }
                        else
                        {
                            findCatchIndex = _statements.Length;
                        }

                        findCatchIndex += 2;
                    }
                }

                // if no matching catch was found when an error occurred, it was not caught: throw it!
                if (encounteredError && !foundMatchingCatch)
                    return ErrorHandler.ThrowError(errorObject);

                // now, try to find finally statement:
                var findFinallyIndex = _index + 1;
                while (findFinallyIndex < _statements.Length && !foundFinally)
                {
                    if (_statements[findFinallyIndex].StatementType == StatementType.Finally)
                    {
                        _index = findFinallyIndex + 1;

                        if (_statements.Length > _index)
                        {
                            var finallyExecuteStatement = _statements[_index];
                            foundFinally = true;

                            returnObject = ExecuteStatement(finallyExecuteStatement);
                        }
                        else
                        {
                            return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
                        }
                    }
                    else
                    {
                        findFinallyIndex = _statements.Length;
                    }

                    findFinallyIndex += 2;
                }

                if (!foundCatch && !foundFinally) // when no catch or finally block has been found, throw an error.
                    return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_CATCH_OR_FINALLY);
                else
                    return returnObject;
            }
            else
            {
                return ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }
        }
예제 #30
0
 public ErrorHandler(ScriptProcessor processor)
 {
     _processor = processor;
 }
예제 #31
0
 public ErrorHandler(ScriptProcessor processor)
 {
     _processor = processor;
 }
예제 #32
0
        private SObject ExecuteFor(ScriptStatement statement)
        {
            var exp = statement.Code;

            var forCode = exp.Remove(0, exp.IndexOf("for") + "for".Length).Trim().Remove(0, 1); // Remove "for" and "(".

            forCode = forCode.Remove(forCode.Length - 1, 1);                                    // Remove ")".

            var forStatements = StatementProcessor.GetStatements(this, forCode);

            if (forStatements.Length == 0)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, ")"));
            }
            else if (forStatements.Length == 1)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_INITIALIZER));
            }
            else if (forStatements.Length == 2)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONDITION));
            }
            else if (forStatements.Length > 3)
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_FOR_CONTROL));
            }

            var processor = new ScriptProcessor(Context, GetLineNumber());

            var forInitializer = forStatements[0];
            var forCondition   = forStatements[1];
            var forControl     = forStatements[2];

            if (forInitializer.Code.Length > 0)
            {
                processor.ExecuteStatement(forInitializer);
            }

            _index++;

            if (_statements.Length > _index)
            {
                var stayInFor        = true;
                var executeStatement = _statements[_index];
                var returnObject     = Undefined;

                while (stayInFor)
                {
                    if (forCondition.Code.Length > 0)
                    {
                        var conditionResult = processor.ExecuteStatement(forCondition);

                        if (conditionResult is SBool)
                        {
                            stayInFor = ((SBool)conditionResult).Value;
                        }
                        else
                        {
                            stayInFor = conditionResult.ToBool(this).Value;
                        }
                    }

                    if (stayInFor)
                    {
                        returnObject = processor.ExecuteStatement(executeStatement);

                        if (processor._returnIssued || processor._breakIssued)
                        {
                            _breakIssued  = false;
                            _returnIssued = processor._returnIssued;
                            stayInFor     = false;
                        }
                        else if (forControl.Code.Length > 0)
                        {
                            processor.ExecuteStatement(forControl);
                        }
                    }
                }

                return(returnObject);
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
예제 #33
0
        private SObject ExecuteTry(ScriptStatement statement)
        {
            var exp = statement.Code;

            if (exp != "try")
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_BEFORE_TRY));
            }

            _index++;
            if (_statements.Length > _index)
            {
                var     executeStatement   = _statements[_index];
                var     encounteredError   = false;
                var     foundCatch         = false;
                var     foundFinally       = false;
                var     foundMatchingCatch = false;
                SObject errorObject        = null;
                var     returnObject       = Undefined;

                try
                {
                    returnObject = ExecuteStatement(executeStatement);
                }
                catch (ScriptException ex)
                {
                    encounteredError = true;
                    errorObject      = ex.ErrorObject;
                }

                if (encounteredError)
                {
                    var endedCatchSearch = false;
                    var findCatchIndex   = _index + 1;
                    while (findCatchIndex < _statements.Length && !endedCatchSearch)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            _index = findCatchIndex + 1;

                            if (_statements.Length > _index)
                            {
                                if (!foundMatchingCatch)
                                {
                                    var catchExecuteStatement = _statements[_index];
                                    foundCatch = true;

                                    var catchCode    = _statements[findCatchIndex].Code;
                                    var errorVarName = "";

                                    if (catchCode != "catch")
                                    {
                                        catchCode    = catchCode.Remove(0, "catch".Length).Trim().Remove(0, 1);
                                        catchCode    = catchCode.Remove(catchCode.Length - 1, 1);
                                        errorVarName = catchCode.Trim();
                                    }

                                    if (Regex.IsMatch(catchCode, REGEX_CATCHCONDITION))
                                    {
                                        errorVarName = catchCode.Remove(catchCode.IndexOf(" "));
                                        string conditionCode = catchCode.Remove(0, catchCode.IndexOf("if") + 3);

                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);

                                        var conditionResult = processor.ExecuteStatement(new ScriptStatement(conditionCode));

                                        if (conditionResult is SBool)
                                        {
                                            foundMatchingCatch = ((SBool)conditionResult).Value;
                                        }
                                        else
                                        {
                                            foundMatchingCatch = conditionResult.ToBool(this).Value;
                                        }

                                        if (foundMatchingCatch)
                                        {
                                            returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                        }
                                    }
                                    else
                                    {
                                        foundMatchingCatch = true;
                                        var processor = new ScriptProcessor(Context, GetLineNumber());
                                        processor.Context.AddVariable(errorVarName, errorObject);
                                        returnObject = processor.ExecuteStatement(catchExecuteStatement);
                                    }
                                }
                            }
                            else
                            {
                                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
                            }
                        }
                        else
                        {
                            // end search if different statement type appears:
                            endedCatchSearch = true;
                        }

                        findCatchIndex += 2;
                    }
                }
                else
                {
                    var findCatchIndex = _index + 1;
                    while (findCatchIndex < _statements.Length)
                    {
                        if (_statements[findCatchIndex].StatementType == StatementType.Catch)
                        {
                            foundCatch = true;
                            _index     = findCatchIndex + 1;
                        }
                        else
                        {
                            findCatchIndex = _statements.Length;
                        }

                        findCatchIndex += 2;
                    }
                }

                // if no matching catch was found when an error occurred, it was not caught: throw it!
                if (encounteredError && !foundMatchingCatch)
                {
                    return(ErrorHandler.ThrowError(errorObject));
                }

                // now, try to find finally statement:
                var findFinallyIndex = _index + 1;
                while (findFinallyIndex < _statements.Length && !foundFinally)
                {
                    if (_statements[findFinallyIndex].StatementType == StatementType.Finally)
                    {
                        _index = findFinallyIndex + 1;

                        if (_statements.Length > _index)
                        {
                            var finallyExecuteStatement = _statements[_index];
                            foundFinally = true;

                            returnObject = ExecuteStatement(finallyExecuteStatement);
                        }
                        else
                        {
                            return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
                        }
                    }
                    else
                    {
                        findFinallyIndex = _statements.Length;
                    }

                    findFinallyIndex += 2;
                }

                if (!foundCatch && !foundFinally) // when no catch or finally block has been found, throw an error.
                {
                    return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_CATCH_OR_FINALLY));
                }
                else
                {
                    return(returnObject);
                }
            }
            else
            {
                return(ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script"));
            }
        }
예제 #34
0
        internal static ScriptStatement[] GetStatements(ScriptProcessor processor, string code)
        {
            var statements = new List<ScriptStatement>();

            var statement = new StringBuilder();

            var index = 0;
            var depth = 0;
            var lineNumber = 1;
            var lineNumberBuffer = 0; // buffers line counts from the start of a statement.
            var isComment = false;
            var isControlStatement = false; // If the current statement is a control statement.
            var isCompoundStatement = false; // If the current statement is bunch of statements wrapped in { ... }

            StringEscapeHelper escaper = new LeftToRightStringEscapeHelper(code, 0);

            while (index < code.Length)
            {
                var t = code[index];

                if (!isComment)
                    escaper.CheckStartAt(index);
                else
                    escaper.JumpTo(index);

                if (!escaper.IsString)
                {
                    // Check if a block comment is starting (/*):
                    if (!isComment && t == '/' && index + 1 < code.Length && code[index + 1] == '*')
                    {
                        isComment = true;
                        index++; // Jump over * char.
                    }

                    if (!isComment)
                    {
                        // Check if a line comment is starting (//):
                        if (t == '/' && index + 1 < code.Length && code[index + 1] == '/')
                        {
                            // We jump to the end of the line and ignore everything between the current index and the end of the line:
                            if (code.IndexOf("\n", index + 1) > -1)
                                index = code.IndexOf("\n", index + 1) + 1;
                            else
                                index = code.Length;

                            continue;
                        }

                        statement.Append(t);

                        if (t == '(')
                        {
                            depth++;
                        }
                        else if (t == ')')
                        {
                            depth--;

                            if (isControlStatement)
                            {
                                var statementStr = statement.ToString();
                                var s = statementStr.Trim();
                                if (s.StartsWith("if") || s.StartsWith("else if") || s.StartsWith("function") || s.StartsWith("for") || s.StartsWith("while") || s.StartsWith("catch"))
                                {
                                    var extraLines = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                                    statements.Add(new ScriptStatement(s, GetStatementType(s, true), lineNumber + extraLines));
                                    statement.Clear();
                                    lineNumber += lineNumberBuffer;
                                    lineNumberBuffer = 0;

                                    isControlStatement = false;
                                }
                            }
                        }
                        else if (t == '{')
                        {
                            depth++;

                            if (depth == 1)
                            {
                                var statementStr = statement.ToString();
                                var s = statementStr.Trim();

                                if (isControlStatement)
                                {
                                    var extraLines = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines

                                    s = s.Remove(s.Length - 1, 1).Trim();
                                    statements.Add(new ScriptStatement(s, GetStatementType(s, true), lineNumber + extraLines));

                                    lineNumber += lineNumberBuffer;
                                    lineNumberBuffer = 0;

                                    statement.Clear();
                                    statement.Append('{');
                                    isCompoundStatement = true;
                                    isControlStatement = false;
                                }
                                else
                                {
                                    if (s == "{")
                                    {
                                        isCompoundStatement = true;
                                    }
                                }
                            }
                        }
                        else if (t == '}')
                        {
                            depth--;
                            if (depth == 0 && isCompoundStatement)
                            {
                                // This could also be an object declaration...
                                // In the case that the statement started with "{" (example statement: {} + []), this will happen.
                                // To check if this is in fact an object, we look right and see if there is:
                                //   - an operator => object ("+*-/&|<>.[(")
                                //   - nothing => statement

                                var foundOperator = false;
                                var charFindIndex = index + 1;

                                while (!foundOperator && charFindIndex < code.Length)
                                {
                                    var testChar = code[charFindIndex];
                                    if (OBJECT_DISCOVER_TOKEN.Contains(testChar))
                                    {
                                        if (testChar == '/' && // next statement is actually a comment, not a / operator (followed by / or *)
                                            charFindIndex + 1 < code.Length && 
                                            (code[charFindIndex + 1] == '/' || code[charFindIndex + 1] == '*'))
                                            charFindIndex = code.Length;
                                        else
                                            foundOperator = true;
                                    }
                                    else if (!char.IsWhiteSpace(testChar)) // We found something that is not an operator or whitespace, so this is the end of a compound statement.
                                    {
                                        charFindIndex = code.Length;
                                    }

                                    charFindIndex++;
                                }

                                if (!foundOperator)
                                {
                                    var statementStr = statement.ToString();
                                    var extraLines = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                                    var s = statementStr.Trim();
                                    statements.Add(new ScriptStatement(s, StatementType.Executable, lineNumber + extraLines) { IsCompoundStatement = true });
                                    statement.Clear();
                                    lineNumber += lineNumberBuffer;
                                    lineNumberBuffer = 0;
                                }

                                isCompoundStatement = false;
                            }
                        }
                        else if (t == ';' && depth == 0)
                        {
                            var statementStr = statement.ToString();
                            var extraLines = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                            var s = statementStr.Trim().TrimEnd(new char[] { ';' });
                            statements.Add(new ScriptStatement(s, GetStatementType(s, false), lineNumber + extraLines));
                            statement.Clear();
                            lineNumber += lineNumberBuffer;
                            lineNumberBuffer = 0;
                        }
                        else if (!isCompoundStatement && !isControlStatement)
                        {
                            var statementStr = statement.ToString();
                            var extraLines = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                            var s = statementStr.TrimStart();

                            var nextChar = 'X'; // Set to something that is not matching with the condition below.
                            if (code.Length > index + 1)
                                nextChar = code[index + 1];

                            // Check if it's actually a control statement by looking if the next char matches (whitespace, ";" or "(")
                            if ((char.IsWhiteSpace(nextChar) || nextChar == ';' || nextChar == '(') && ControlStatements.Contains(s))
                            {
                                isControlStatement = true;
                                if (s.StartsWith("else"))
                                {
                                    if (index + 3 < code.Length)
                                    {
                                        var check = code.Substring(index + 1, 3);
                                        if (check != " if")
                                        {
                                            statements.Add(new ScriptStatement("else", StatementType.Else, lineNumber + extraLines));
                                            statement.Clear();
                                            isControlStatement = false;
                                            lineNumber += lineNumberBuffer;
                                            lineNumberBuffer = 0;
                                        }
                                    }
                                }
                            }
                        }

                    }
                    else
                    {
                        // Check if a block comment is ending (/*):
                        if (t == '*' && index + 1 < code.Length && code[index + 1] == '/')
                        {
                            isComment = false;
                            index++; // Jump over / char.
                        }
                    }
                }
                else
                {
                    statement.Append(t);
                }

                if (t == '\n')
                    lineNumberBuffer++;

                index++;
            }

            if (isCompoundStatement)
                processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_END_OF_COMPOUND_STATEMENT);

            if (isComment)
                processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_UNTERMINATED_COMMENT);

            if (isControlStatement)
                processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");

            // an executable statement not closed with ";" is getting added here:
            var leftOver = statement.ToString().Trim();
            if (leftOver.Length > 0)
            {
                statements.Add(new ScriptStatement(leftOver, GetStatementType(leftOver, false), lineNumber));
            }

            return statements.ToArray();
        }
예제 #35
0
        internal static ScriptStatement[] GetStatements(ScriptProcessor processor, string code)
        {
            var statements = new List <ScriptStatement>();

            var statement = new StringBuilder();

            var index               = 0;
            var depth               = 0;
            var lineNumber          = 1;
            var lineNumberBuffer    = 0;     // buffers line counts from the start of a statement.
            var isComment           = false;
            var isControlStatement  = false; // If the current statement is a control statement.
            var isCompoundStatement = false; // If the current statement is bunch of statements wrapped in { ... }

            StringEscapeHelper escaper = new LeftToRightStringEscapeHelper(code, 0);

            while (index < code.Length)
            {
                var t = code[index];

                if (!isComment)
                {
                    escaper.CheckStartAt(index);
                }
                else
                {
                    escaper.JumpTo(index);
                }

                if (!escaper.IsString)
                {
                    // Check if a block comment is starting (/*):
                    if (!isComment && t == '/' && index + 1 < code.Length && code[index + 1] == '*')
                    {
                        isComment = true;
                        index++; // Jump over * char.
                    }

                    if (!isComment)
                    {
                        // Check if a line comment is starting (//):
                        if (t == '/' && index + 1 < code.Length && code[index + 1] == '/')
                        {
                            // We jump to the end of the line and ignore everything between the current index and the end of the line:
                            if (code.IndexOf("\n", index + 1) > -1)
                            {
                                index = code.IndexOf("\n", index + 1) + 1;
                            }
                            else
                            {
                                index = code.Length;
                            }

                            continue;
                        }

                        statement.Append(t);

                        if (t == '(')
                        {
                            depth++;
                        }
                        else if (t == ')')
                        {
                            depth--;

                            if (isControlStatement)
                            {
                                var statementStr = statement.ToString();
                                var s            = statementStr.Trim();
                                if (s.StartsWith("if") || s.StartsWith("else if") || s.StartsWith("function") || s.StartsWith("for") || s.StartsWith("while") || s.StartsWith("catch"))
                                {
                                    var extraLines = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                                    statements.Add(new ScriptStatement(s, GetStatementType(s, true), lineNumber + extraLines));
                                    statement.Clear();
                                    lineNumber      += lineNumberBuffer;
                                    lineNumberBuffer = 0;

                                    isControlStatement = false;
                                }
                            }
                        }
                        else if (t == '{')
                        {
                            depth++;

                            if (depth == 1)
                            {
                                var statementStr = statement.ToString();
                                var s            = statementStr.Trim();

                                if (isControlStatement)
                                {
                                    var extraLines = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines

                                    s = s.Remove(s.Length - 1, 1).Trim();
                                    statements.Add(new ScriptStatement(s, GetStatementType(s, true), lineNumber + extraLines));

                                    lineNumber      += lineNumberBuffer;
                                    lineNumberBuffer = 0;

                                    statement.Clear();
                                    statement.Append('{');
                                    isCompoundStatement = true;
                                    isControlStatement  = false;
                                }
                                else
                                {
                                    if (s == "{")
                                    {
                                        isCompoundStatement = true;
                                    }
                                }
                            }
                        }
                        else if (t == '}')
                        {
                            depth--;
                            if (depth == 0 && isCompoundStatement)
                            {
                                // This could also be an object declaration...
                                // In the case that the statement started with "{" (example statement: {} + []), this will happen.
                                // To check if this is in fact an object, we look right and see if there is:
                                //   - an operator => object ("+*-/&|<>.[(")
                                //   - nothing => statement

                                var foundOperator = false;
                                var charFindIndex = index + 1;

                                while (!foundOperator && charFindIndex < code.Length)
                                {
                                    var testChar = code[charFindIndex];
                                    if (OBJECT_DISCOVER_TOKEN.Contains(testChar))
                                    {
                                        if (testChar == '/' && // next statement is actually a comment, not a / operator (followed by / or *)
                                            charFindIndex + 1 < code.Length &&
                                            (code[charFindIndex + 1] == '/' || code[charFindIndex + 1] == '*'))
                                        {
                                            charFindIndex = code.Length;
                                        }
                                        else
                                        {
                                            foundOperator = true;
                                        }
                                    }
                                    else if (!char.IsWhiteSpace(testChar)) // We found something that is not an operator or whitespace, so this is the end of a compound statement.
                                    {
                                        charFindIndex = code.Length;
                                    }

                                    charFindIndex++;
                                }

                                if (!foundOperator)
                                {
                                    var statementStr = statement.ToString();
                                    var extraLines   = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                                    var s            = statementStr.Trim();
                                    statements.Add(new ScriptStatement(s, StatementType.Executable, lineNumber + extraLines)
                                    {
                                        IsCompoundStatement = true
                                    });
                                    statement.Clear();
                                    lineNumber      += lineNumberBuffer;
                                    lineNumberBuffer = 0;
                                }

                                isCompoundStatement = false;
                            }
                        }
                        else if (t == ';' && depth == 0)
                        {
                            var statementStr = statement.ToString();
                            var extraLines   = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                            var s            = statementStr.Trim().TrimEnd(new char[] { ';' });
                            statements.Add(new ScriptStatement(s, GetStatementType(s, false), lineNumber + extraLines));
                            statement.Clear();
                            lineNumber      += lineNumberBuffer;
                            lineNumberBuffer = 0;
                        }
                        else if (!isCompoundStatement && !isControlStatement)
                        {
                            var statementStr = statement.ToString();
                            var extraLines   = statementStr.Replace("\r", "").TakeWhile(c => c == '\n').Count(); // count the starting lines
                            var s            = statementStr.TrimStart();

                            var nextChar = 'X'; // Set to something that is not matching with the condition below.
                            if (code.Length > index + 1)
                            {
                                nextChar = code[index + 1];
                            }

                            // Check if it's actually a control statement by looking if the next char matches (whitespace, ";" or "(")
                            if ((char.IsWhiteSpace(nextChar) || nextChar == ';' || nextChar == '(') && ControlStatements.Contains(s))
                            {
                                isControlStatement = true;
                                if (s.StartsWith("else"))
                                {
                                    if (index + 3 < code.Length)
                                    {
                                        var check = code.Substring(index + 1, 3);
                                        if (check != " if")
                                        {
                                            statements.Add(new ScriptStatement("else", StatementType.Else, lineNumber + extraLines));
                                            statement.Clear();
                                            isControlStatement = false;
                                            lineNumber        += lineNumberBuffer;
                                            lineNumberBuffer   = 0;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // Check if a block comment is ending (/*):
                        if (t == '*' && index + 1 < code.Length && code[index + 1] == '/')
                        {
                            isComment = false;
                            index++; // Jump over / char.
                        }
                    }
                }
                else
                {
                    statement.Append(t);
                }

                if (t == '\n')
                {
                    lineNumberBuffer++;
                }

                index++;
            }

            if (isCompoundStatement)
            {
                processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_MISSING_END_OF_COMPOUND_STATEMENT);
            }

            if (isComment)
            {
                processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_UNTERMINATED_COMMENT);
            }

            if (isControlStatement)
            {
                processor.ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_EXPECTED_EXPRESSION, "end of script");
            }

            // an executable statement not closed with ";" is getting added here:
            var leftOver = statement.ToString().Trim();

            if (leftOver.Length > 0)
            {
                statements.Add(new ScriptStatement(leftOver, GetStatementType(leftOver, false), lineNumber));
            }

            return(statements.ToArray());
        }
예제 #36
0
        public void ObjectTranslateTest()
        {
            var processor = new ScriptProcessor();
            ScriptContextManipulator.AddPrototype(processor, typeof(Pokemon));

            processor.Run("var p = new Pokemon(); p.SetName(\"Pika\");");

            object objp = ScriptContextManipulator.GetVariableTranslated(processor, "p");

            Assert.IsTrue(objp.GetType() == typeof(Pokemon));

            Pokemon p = (Pokemon)objp;

            Assert.AreEqual("Pikachu", p.OriginalName);
            Assert.AreEqual("Pika", p.Name);
        }
예제 #37
0
 public static SObject SizeOf(ScriptProcessor processor, SObject instance, SObject This, SObject[] parameters) =>
 parameters.Length == 0 ? processor.Undefined : processor.CreateNumber(parameters[0].SizeOf());