Exemple #1
0
        static List <Variable> Split(ParsingScript script, char[] to)
        {
            List <Variable> listToMerge = new List <Variable>(16);

            if (!script.StillValid() || to.Contains(script.Current))
            {
                listToMerge.Add(Variable.EmptyInstance);
                script.Forward();
                return(listToMerge);
            }

            int    arrayIndexDepth = 0;
            bool   inQuotes        = false;
            int    negated         = 0;
            char   ch;
            string action;

            do
            { // Main processing cycle of the first part.
                string token = ExtractNextToken(script, to, ref inQuotes, ref arrayIndexDepth, ref negated, out ch, out action);

                bool ternary = UpdateIfTernary(script, token, ch, listToMerge, (List <Variable> newList) => { listToMerge = newList; });
                if (ternary)
                {
                    return(listToMerge);
                }

                bool negSign = CheckConsistencyAndSign(script, listToMerge, action, ref token);

                // We are done getting the next token. The GetValue() call below may
                // recursively call SplitAndMerge(). This will happen if extracted
                // item is a function or if the next item is starting with a START_ARG '('.
                ParserFunction func    = new ParserFunction(script, token, ch, ref action);
                Variable       current = func.GetValue(script);

                if (UpdateResult(script, to, listToMerge, token, negSign, ref current, ref negated, ref action))
                {
                    return(listToMerge);
                }
            } while (script.StillValid() &&
                     (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current)));

            // This happens when called recursively inside of the math expression:
            script.MoveForwardIf(Constants.END_ARG);

            return(listToMerge);
        }
Exemple #2
0
 public static void CheckNotEnd(ParsingScript script, string name)
 {
     if (!script.StillValid())
     {
         string realName = Constants.GetRealName(name);
         throw new ArgumentException("Incomplete arguments for [" + realName + "]");
     }
 }
Exemple #3
0
 public static void CheckNotEmpty(ParsingScript script, string varName, string name)
 {
     if (!script.StillValid() || string.IsNullOrWhiteSpace(varName))
     {
         string realName = Constants.GetRealName(name);
         ThrowErrorMsg("Incomplete arguments for [" + realName + "].", script, name);
     }
 }
Exemple #4
0
 public static void CheckNotEnd(ParsingScript script, string name)
 {
     if (!script.StillValid())
     {
         string realName = Constants.GetRealName(name);
         ThrowErrorMsg("Incomplete arguments for [" + realName + "]", script, script.Prev.ToString());
     }
 }
Exemple #5
0
        public static string GetBodyBetween(ParsingScript script, char open = Constants.START_ARG, char close = Constants.END_ARG)
        {
            // We are supposed to be one char after the beginning of the string, i.e.
            // we must not have the opening char as the first one.
            StringBuilder sb          = new StringBuilder(script.Size());
            int           braces      = 0;
            bool          inQuotes    = false;
            bool          inQuotes1   = false;
            bool          inQuotes2   = false;
            bool          checkBraces = true;
            char          prev        = Constants.EMPTY;
            char          prevprev    = Constants.EMPTY;

            for (; script.StillValid(); script.Forward())
            {
                char ch = script.Current;

                if (close != Constants.QUOTE)
                {
                    checkBraces = !inQuotes;
                    if (ch == Constants.QUOTE && !inQuotes1 && (prev != '\\' || prevprev == '\\'))
                    {
                        inQuotes = inQuotes2 = !inQuotes2;
                    }
                    if (ch == Constants.QUOTE1 && !inQuotes2 && (prev != '\\' || prevprev == '\\'))
                    {
                        inQuotes = inQuotes1 = !inQuotes1;
                    }
                }

                if (string.IsNullOrWhiteSpace(ch.ToString()) && sb.Length == 0)
                {
                    continue;
                }
                else if (checkBraces && ch == open)
                {
                    braces++;
                }
                else if (checkBraces && ch == close)
                {
                    braces--;
                }

                sb.Append(ch);
                prevprev = prev;
                prev     = ch;
                if (braces < 0)
                {
                    if (ch == close)
                    {
                        sb.Remove(sb.Length - 1, 1);
                    }
                    break;
                }
            }

            return(sb.ToString());
        }
Exemple #6
0
        private void SkipBlock(ParsingScript script)
        {
            int  blockStart = script.Pointer;
            int  startCount = 0;
            int  endCount   = 0;
            bool inQuotes   = false;
            bool inQuotes1  = false;
            bool inQuotes2  = false;
            char previous   = Constants.EMPTY;
            char prevprev   = Constants.EMPTY;

            while (startCount == 0 || startCount > endCount)
            {
                if (!script.StillValid())
                {
                    throw new ArgumentException("Couldn't skip block [" +
                                                script.Substr(blockStart, Constants.MAX_CHARS_TO_SHOW) + "]");
                }
                char currentChar = script.CurrentAndForward();
                switch (currentChar)
                {
                case Constants.QUOTE1:
                    if (!inQuotes2 && (previous != '\\' || prevprev == '\\'))
                    {
                        inQuotes = inQuotes1 = !inQuotes1;
                    }
                    break;

                case Constants.QUOTE:
                    if (!inQuotes1 && (previous != '\\' || prevprev == '\\'))
                    {
                        inQuotes = inQuotes2 = !inQuotes2;
                    }
                    break;

                case Constants.START_GROUP:
                    if (!inQuotes)
                    {
                        startCount++;
                    }
                    break;

                case Constants.END_GROUP:
                    if (!inQuotes)
                    {
                        endCount++;
                    }
                    break;
                }
                prevprev = previous;
                previous = currentChar;
            }

            if (startCount != endCount)
            {
                throw new ArgumentException("Mismatched parentheses");
            }
        }
Exemple #7
0
        static async Task <List <Variable> > SplitAsync(ParsingScript script, char[] to)
        {
            List <Variable> listToMerge = new List <Variable>(16);

            if (!script.StillValid() || to.Contains(script.Current))
            {
                listToMerge.Add(Variable.EmptyInstance);
                script.Forward();
                return(listToMerge);
            }

            int    arrayIndexDepth = 0;
            bool   inQuotes        = false;
            int    negated         = 0;
            char   ch;
            string action;

            do
            { // Main processing cycle of the first part.
                string token = ExtractNextToken(script, to, ref inQuotes, ref arrayIndexDepth, ref negated, out ch, out action);

                bool ternary = await UpdateIfTernaryAsync(script, token, ch, listToMerge, (List <Variable> newList) => { listToMerge = newList; });

                if (ternary)
                {
                    return(listToMerge);
                }

                bool negSign = CheckConsistencyAndSign(script, listToMerge, action, ref token);

                ParserFunction func    = new ParserFunction(script, token, ch, ref action);
                Variable       current = await func.GetValueAsync(script);

                if (UpdateResult(script, to, listToMerge, token, negSign, ref current, ref negated, ref action))
                {
                    return(listToMerge);
                }
            } while (script.StillValid() &&
                     (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current)));

            // This happens when called recursively inside of the math expression:
            script.MoveForwardIf(Constants.END_ARG);

            return(listToMerge);
        }
Exemple #8
0
        public static string ExtractNextToken(ParsingScript script, char[] to, ref bool inQuotes,
                                              ref int arrayIndexDepth, ref int negated, out char ch, out string action, bool throwExc = true)
        {
            StringBuilder item = new StringBuilder();

            ch     = Constants.EMPTY;
            action = null;
            do
            {
                string negateSymbol = Utils.IsNotSign(script.Rest);
                if (negateSymbol != null && !inQuotes)
                {
                    negated++;
                    script.Forward(negateSymbol.Length);
                    continue;
                }

                ch = script.CurrentAndForward();
                CheckQuotesIndices(script, ch, ref inQuotes, ref arrayIndexDepth);

                bool keepCollecting = inQuotes || arrayIndexDepth > 0 ||
                                      StillCollecting(item.ToString(), to, script, ref action);
                if (keepCollecting)
                {
                    // The char still belongs to the previous operand.
                    item.Append(ch);

                    bool goForMore = script.StillValid() &&
                                     (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current));
                    if (goForMore)
                    {
                        continue;
                    }
                }

                if (SkipOrAppendIfNecessary(item, ch, to))
                {
                    continue;
                }
                break;
            }while (true);

            string result = item.ToString();

            result = result.Replace("\\\\", "\\");
            result = result.Replace("\\\"", "\"");
            result = result.Replace("\\'", "'");

            if (throwExc && string.IsNullOrWhiteSpace(result) && action != "++" && action != "--" &&
                Utils.IsAction(script.Prev) && Utils.IsAction(script.PrevPrev))
            {
                Utils.ThrowErrorMsg("Can't process token [" + script.PrevPrev + script.Prev + script.Current +
                                    "].", script, script.Current.ToString());
            }

            return(result);
        }
        // A "virtual" Constructor
        public ParserFunction(ParsingScript script, string item, char ch, ref string action)
        {
            if (item.Length == 0 && (ch == Constants.START_ARG || !script.StillValid()))
            {
                // There is no function, just an expression in parentheses
                m_impl = s_idFunction;
                return;
            }
            if (item.Length > 1 &&
                ((item[0] == Constants.QUOTE && item[item.Length - 1] == Constants.QUOTE) ||
                 (item[0] == Constants.QUOTE1 && item[item.Length - 1] == Constants.QUOTE1)))
            {
                // We are dealing with a string.
                s_strOrNumFunction.Item = item;
                m_impl = s_strOrNumFunction;
                return;
            }

            item = Constants.ConvertName(item);

            m_impl = GetRegisteredAction(item, ref action);
            if (m_impl != null)
            {
                return;
            }

            m_impl = GetArrayFunction(item, script, action);
            if (m_impl != null)
            {
                return;
            }

            m_impl = GetObjectFunction(item, script);
            if (m_impl != null)
            {
                return;
            }

            m_impl = GetVariable(item, script);
            if (m_impl != null)
            {
                return;
            }

            if (m_impl == s_strOrNumFunction && string.IsNullOrWhiteSpace(item))
            {
                string problem  = (!string.IsNullOrWhiteSpace(action) ? action : ch.ToString());
                string restData = ch.ToString() + script.Rest;
                throw new ArgumentException("Couldn't parse [" + problem + "] in " + restData + "...");
            }

            // Function not found, will try to parse this as a string in quotes or a number.
            s_strOrNumFunction.Item = item;
            m_impl = s_strOrNumFunction;
        }
Exemple #10
0
        public static void SkipRestExpr(ParsingScript script)
        {
            int  argRead  = 0;
            bool inQuotes = false;
            char previous = Constants.EMPTY;

            while (script.StillValid())
            {
                char currentChar = script.Current;
                if (inQuotes && currentChar != Constants.QUOTE)
                {
                    script.Forward();
                    continue;
                }

                switch (currentChar)
                {
                case Constants.QUOTE:
                    if (previous != '\\')
                    {
                        inQuotes = !inQuotes;
                    }
                    break;

                case Constants.START_ARG:
                    argRead++;
                    break;

                case Constants.END_ARG:
                    argRead--;
                    if (argRead < 0)
                    {
                        return;
                    }
                    break;

                case Constants.END_STATEMENT:
                    return;

                case Constants.TERNARY_OPERATOR:
                case Constants.NEXT_ARG:
                    if (argRead <= 0)
                    {
                        return;
                    }
                    break;

                default:
                    break;
                }

                script.Forward();
                previous = currentChar;
            }
        }
Exemple #11
0
        public static List <Variable> GetArgs(ParsingScript script,
                                              char start, char end, out bool isList)
        {
            List <Variable> args = new List <Variable>();

            isList = script.StillValid() && script.Current == Constants.START_GROUP;

            if (!script.StillValid() || script.Current == Constants.END_STATEMENT)
            {
                return(args);
            }

            ParsingScript tempScript = new ParsingScript(script.String, script.Pointer);
            string        body       = Utils.GetBodyBetween(tempScript, start, end);
            string        rest       = script.Rest;

            // After the statement above tempScript.Parent will point to the last
            // character belonging to the body between start and end characters.

            while (script.Pointer < tempScript.Pointer)
            {
                Variable item = Utils.GetItem(script);
                args.Add(item);
                rest = script.Rest;
                if (script.Pointer == tempScript.Pointer)
                {
                    rest = script.Rest;
                }
                script.MoveForwardIf(Constants.NEXT_ARG);
            }

            if (script.Pointer <= tempScript.Pointer)
            {
                // Eat closing parenthesis, if there is one, but only if it closes
                // the current argument list, not one after it.
                script.MoveForwardIf(Constants.END_ARG);
            }

            script.MoveForwardIf(Constants.SPACE);
            //script.MoveForwardIf(Constants.SPACE, Constants.END_STATEMENT);
            return(args);
        }
Exemple #12
0
        int GetCurrentLineNumber(ParsingScript script)
        {
            if (script == m_debugging && !m_debugging.StillValid())
            {
#if UNITY_EDITOR == false && UNITY_STANDALONE == false && __ANDROID__ == false && __IOS__ == false
                return(-1);
#else
                return(-2);
#endif
            }
            return(script.GetOriginalLineNumber());
        }
Exemple #13
0
        private Variable ProcessBlock(ParsingScript script)
        {
            int      blockStart = script.Pointer;
            Variable result     = null;

            if (script.Debugger != null)
            {
                bool done = false;
                result = script.Debugger.DebugBlockIfNeeded(script, ref done);
                if (done)
                {
                    return(result);
                }
            }
            while (script.StillValid())
            {
                int endGroupRead = script.GoToNextStatement();
                if (endGroupRead > 0 || !script.StillValid())
                {
                    return(result != null ? result : new Variable());
                }

                /*if (!script.StillValid())
                 * {
                 *  throw new ArgumentException("Couldn't process block [" +
                 *  script.Substr(blockStart, Constants.MAX_CHARS_TO_SHOW) + "]");
                 * }*/
                result = script.ExecuteTo();

                if (result.IsReturn ||
                    result.Type == Variable.VarType.BREAK ||
                    result.Type == Variable.VarType.CONTINUE)
                {
                    return(result);
                }
            }
            return(result);
        }
Exemple #14
0
        static Variable ExtractArray(ParsingScript script)
        {
            Variable newValue = new Variable(Variable.VarType.ARRAY);

            while (script.StillValid() && (newValue.Count == 0 || script.Current == ','))
            {
                script.Forward();
                Variable addVariable = ExtractValue(script);
                newValue.AddVariable(addVariable);
            }
            script.MoveForwardIf(']');

            return(newValue);
        }
Exemple #15
0
        public static string ReplaceSpaces(ParsingScript script, char replaceChar = ',', char end = Constants.END_STATEMENT)
        {
            StringBuilder sb = new StringBuilder();

            while (script.StillValid() && script.TryCurrent() != end)
            {
                var token = GetBodyBetween(script, '\0', ' ', end);
                sb.Append(token + replaceChar);
            }
            if (sb.Length > 0 && sb[sb.Length - 1] == replaceChar)
            {
                sb.Remove(sb.Length - 1, 1);
            }
            return(sb.ToString());
        }
Exemple #16
0
        private Variable ProcessBlock(ParsingScript script)
        {
            int      blockStart = script.Pointer;
            Variable result     = null;

            while (script.StillValid())
            {
                int endGroupRead = script.GoToNextStatement();
                if (endGroupRead > 0 || !script.StillValid())
                {
                    return(result != null ? result : new Variable());
                }

                result = script.Execute();

                if (result.IsReturn ||
                    result.Type == Variable.VarType.BREAK ||
                    result.Type == Variable.VarType.CONTINUE)
                {
                    return(result);
                }
            }
            return(result);
        }
Exemple #17
0
 private void SkipRestBlocks(ParsingScript script)
 {
     while (script.StillValid())
     {
         int           endOfToken = script.Pointer;
         ParsingScript nextData   = new ParsingScript(script);
         string        nextToken  = Utils.GetNextToken(nextData);
         if (Constants.ELSE_IF != nextToken &&
             Constants.ELSE != nextToken)
         {
             return;
         }
         script.Pointer = nextData.Pointer;
         SkipBlock(script);
     }
 }
Exemple #18
0
        static Variable ExtractObject(ParsingScript script)
        {
            Variable newValue = new Variable(Variable.VarType.ARRAY);

            while (script.StillValid() && (newValue.Count == 0 || script.Current == ','))
            {
                script.Forward();
                string key = Utils.GetToken(script, SEP);
                script.MoveForwardIf(':');

                Variable valueVar = ExtractValue(script);
                newValue.SetHashVariable(key, valueVar);
            }
            script.MoveForwardIf('}');

            return(newValue);
        }
Exemple #19
0
        public static string GetNextToken(ParsingScript script)
        {
            if (!script.StillValid())
            {
                return("");
            }
            int end = script.FindFirstOf(Constants.TOKEN_SEPARATION);

            if (end < 0)
            {
                return("");
            }

            string var = script.Substr(script.Pointer, end - script.Pointer);

            script.Pointer = end;
            return(var);
        }
        internal Variable ProcessSwitch(ParsingScript script)
        {
            Variable switchValue = Utils.GetItem(script);

            script.Forward();

            Variable result  = Variable.EmptyInstance;
            var      caseSep = ":".ToCharArray();

            bool caseDone = false;

            while (script.StillValid())
            {
                var nextToken = Utils.GetBodySize(script, Constants.CASE, Constants.DEFAULT);
                if (string.IsNullOrEmpty(nextToken))
                {
                    break;
                }
                if (nextToken == Constants.DEFAULT && !caseDone)
                {
                    result = ProcessBlock(script);
                    break;
                }
                if (!caseDone)
                {
                    Variable caseValue = script.Execute(caseSep);
                    script.Forward();

                    if (switchValue.Type == caseValue.Type && switchValue.Equals(caseValue))
                    {
                        caseDone = true;
                        result   = ProcessBlock(script);
                        if (script.Prev == '}')
                        {
                            break;
                        }
                        script.Forward();
                    }
                }
            }
            script.MoveForwardIfNotPrevious('}');
            script.GoToNextStatement();
            return(result);
        }
Exemple #21
0
        private static string UpdateAction(ParsingScript script, char[] to)
        {
            // We search a valid action till we get to the End of Argument ')'
            // or pass the end of string.
            if (!script.StillValid() || script.Current == Constants.END_ARG ||
                to.Contains(script.Current))
            {
                return(Constants.NULL_ACTION);
            }

            string action = Utils.ValidAction(script.Rest);

            // We need to advance forward not only the action length but also all
            // the characters we skipped before getting the action.
            int advance = action == null ? 0 : action.Length;

            script.Forward(advance);
            return(action == null ? Constants.NULL_ACTION : action);
        }
        public static string GetBodyBetween(ParsingScript script, char open, char close)
        {
            // We are supposed to be one char after the beginning of the string, i.e.
            // we must not have the opening char as the first one.
            StringBuilder sb     = new StringBuilder(script.Size());
            int           braces = 0;

            for (; script.StillValid(); script.Forward())
            {
                char ch = script.Current;

                if (string.IsNullOrWhiteSpace(ch.ToString()) && sb.Length == 0)
                {
                    continue;
                }
                else if (ch == open)
                {
                    braces++;
                }
                else if (ch == close)
                {
                    braces--;
                }

                sb.Append(ch);
                if (braces == -1)
                {
                    if (ch == close)
                    {
                        sb.Remove(sb.Length - 1, 1);
                    }
                    break;
                }
            }

            return(sb.ToString());
        }
Exemple #23
0
 bool Completed(ParsingScript debugging)
 {
     return((LastResult != null && LastResult.IsReturn) ||
            !debugging.StillValid());
 }
        public static void PreprocessScript(ParsingScript script)
        {
            script.Pointer = 0;
            int    nestedLevel         = 0;
            int    functionNestedLevel = 0;
            int    pointerOffset       = 0;
            string currentFunction     = "";
            string prevToken           = "";

            bool inQuotes        = false;
            int  negated         = 0;
            int  arrayIndexDepth = 0;

            if (script.AllLabels == null)
            {
                script.AllLabels = new Dictionary <string, Dictionary <string, int> >();
            }
            if (script.LabelToFile == null)
            {
                script.LabelToFile = new Dictionary <string, string>();
            }

            while (script.StillValid())
            {
                char ch = script.Current;
                if (ch == '{')
                {
                    nestedLevel++;
                    script.Forward();
                    continue;
                }
                else if (ch == '}')
                {
                    nestedLevel--;
                    if (nestedLevel <= functionNestedLevel)
                    {
                        currentFunction = "";
                        pointerOffset   = 0;
                    }
                    script.Forward();
                    continue;
                }
                else if (ch == ':' && !string.IsNullOrWhiteSpace(prevToken))
                {
                    script.Forward();
                    Dictionary <string, int> labels;
                    if (!script.AllLabels.TryGetValue(currentFunction, out labels))
                    {
                        labels = new Dictionary <string, int>();
                    }
                    labels[prevToken] = script.Pointer + 1 - pointerOffset;
                    script.AllLabels[currentFunction] = labels;
                    script.LabelToFile[prevToken]     = script.Filename;
                    continue;
                }

                try
                {
                    string token = Parser.ExtractNextToken(script, Constants.TOKEN_SEPARATION,
                                                           ref inQuotes, ref arrayIndexDepth, ref negated, out _, out _, false);

                    if (token == Constants.FUNCTION)
                    {
                        script.Forward();
                        currentFunction     = Utils.GetToken(script, Constants.TOKEN_SEPARATION);
                        currentFunction     = Constants.ConvertName(currentFunction);
                        functionNestedLevel = nestedLevel;
                        var sig = Utils.GetFunctionSignature(script);
                        pointerOffset = script.Pointer + (currentFunction == "" ? 1 : 2);
                    }
                    prevToken = token;
                }
                catch (Exception exc)
                {
                    Console.WriteLine(exc.Message);
                    script.Forward();
                }
            }

            script.Pointer = 0;
        }
Exemple #25
0
        protected override Variable Evaluate(ParsingScript script)
        {
            string dirname = (!script.StillValid() || script.Current == Constants.END_STATEMENT) ?
                             Directory.GetCurrentDirectory() :
                             Utils.GetToken(script, Constants.NEXT_OR_END_ARRAY);

            //List<Variable> results = Utils.GetPathnames(dirname);
            List <Variable> results = new List <Variable>();

            int index = dirname.IndexOf('*');

            if (index < 0 && !Directory.Exists(dirname) && !File.Exists(dirname))
            {
                throw new ArgumentException("Directory [" + dirname + "] doesn't exist");
            }

            string pattern = Constants.ALL_FILES;

            try {
                string dir = index < 0 ? Path.GetFullPath(dirname) : dirname;
                if (File.Exists(dir))
                {
                    FileInfo fi = new FileInfo(dir);
                    Interpreter.Instance.AppendOutput(Utils.GetPathDetails(fi, fi.Name), true);
                    results.Add(new Variable(fi.Name));
                    return(new Variable(results));
                }
                // Special dealing if there is a pattern (only * is supported at the moment)
                if (index >= 0)
                {
                    pattern = Path.GetFileName(dirname);

                    if (index > 0)
                    {
                        string        prefix = dirname.Substring(0, index);
                        DirectoryInfo di     = Directory.GetParent(prefix);
                        dirname = di.FullName;
                    }
                    else
                    {
                        dirname = ".";
                    }
                }
                dir = Path.GetFullPath(dirname);
                // First get contents of the directory (unless there is a pattern)
                DirectoryInfo dirInfo = new DirectoryInfo(dir);

                if (pattern == Constants.ALL_FILES)
                {
                    Interpreter.Instance.AppendOutput(Utils.GetPathDetails(dirInfo, "."), true);
                    if (dirInfo.Parent != null)
                    {
                        Interpreter.Instance.AppendOutput(Utils.GetPathDetails(dirInfo.Parent, ".."), true);
                    }
                }

                // Then get contents of all of the files in the directory
                FileInfo[] fileNames = dirInfo.GetFiles(pattern);
                foreach (FileInfo fi in fileNames)
                {
                    try {
                        Interpreter.Instance.AppendOutput(Utils.GetPathDetails(fi, fi.Name), true);
                        results.Add(new Variable(fi.Name));
                    } catch (Exception) {
                        continue;
                    }
                }

                // Then get contents of all of the subdirs in the directory
                DirectoryInfo[] dirInfos = dirInfo.GetDirectories(pattern);
                foreach (DirectoryInfo di in dirInfos)
                {
                    try {
                        Interpreter.Instance.AppendOutput(Utils.GetPathDetails(di, di.Name), true);
                        results.Add(new Variable(di.Name));
                    } catch (Exception) {
                        continue;
                    }
                }
            } catch (Exception exc) {
                throw new ArgumentException("Couldn't list directory: " + exc.Message);
            }

            return(new Variable(results));
        }
Exemple #26
0
        private static List <Variable> Split(ParsingScript script, char[] to)
        {
            List <Variable> listToMerge = new List <Variable>(16);

            if (!script.StillValid() || to.Contains(script.Current))
            {
                listToMerge.Add(Variable.EmptyInstance);
                script.Forward();
                return(listToMerge);
            }

            StringBuilder item            = new StringBuilder();
            int           arrayIndexDepth = 0;
            bool          inQuotes        = false;
            int           negated         = 0;

            string rest = script.Rest;

            //if (rest == "b[a[0]];") {
            //  int stop = 1;
            //}

            do // Main processing cycle of the first part.
            {
                string negateSymbol = Utils.IsNotSign(script.Rest);
                if (negateSymbol != null && !inQuotes)
                {
                    negated++;
                    script.Forward(negateSymbol.Length);
                    continue;
                }

                char ch = script.CurrentAndForward();
                CheckQuotesIndices(script, ch, ref inQuotes, ref arrayIndexDepth);
                string action = null;

                bool keepCollecting = inQuotes || arrayIndexDepth > 0 ||
                                      StillCollecting(item.ToString(), to, script, ref action);
                if (keepCollecting)
                {
                    // The char still belongs to the previous operand.
                    item.Append(ch);

                    bool goForMore = script.StillValid() &&
                                     (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current));
                    if (goForMore)
                    {
                        continue;
                    }
                }

                if (SkipOrAppendIfNecessary(item, ch, to))
                {
                    continue;
                }

                string token = item.ToString();

                bool ternary = UpdateIfTernary(script, token, ch, ref listToMerge);
                if (ternary)
                {
                    return(listToMerge);
                }

                CheckConsistency(token, listToMerge, script);

                script.MoveForwardIf(Constants.SPACE);

                if (action != null && action.Length > 1)
                {
                    script.Forward(action.Length - 1);
                }

                // We are done getting the next token. The getValue() call below may
                // recursively call loadAndCalculate(). This will happen if extracted
                // item is a function or if the next item is starting with a START_ARG '('.
                ParserFunction func    = new ParserFunction(script, token, ch, ref action);
                Variable       current = func.GetValue(script);
                current.ParsingToken = token;

                if (negated > 0 && current.Type == Variable.VarType.NUMBER)
                {
                    // If there has been a NOT sign, this is a boolean.
                    // Use XOR (true if exactly one of the arguments is true).
                    bool neg = !((negated % 2 == 0) ^ Convert.ToBoolean(current.Value));
                    current = new Variable(Convert.ToDouble(neg));
                    negated = 0;
                }

                if (action == null)
                {
                    action = UpdateAction(script, to);
                }
                else
                {
                    script.MoveForwardIf(action[0]);
                }

                char next = script.TryCurrent(); // we've already moved forward
                bool done = listToMerge.Count == 0 &&
                            (next == Constants.END_STATEMENT ||
                             (action == Constants.NULL_ACTION && current.Type != Variable.VarType.NUMBER) ||
                             current.IsReturn);
                if (done)
                {
                    if (action != null && action != Constants.END_ARG_STR)
                    {
                        throw new ArgumentException("Action [" +
                                                    action + "] without an argument.");
                    }
                    // If there is no numerical result, we are not in a math expression.
                    listToMerge.Add(current);
                    return(listToMerge);
                }

                Variable cell = current.Clone();
                cell.Action = action;

                bool addIt = UpdateIfBool(script, ref cell, ref listToMerge);
                if (addIt)
                {
                    listToMerge.Add(cell);
                }
                item.Clear();
            } while (script.StillValid() &&
                     (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current)));

            // This happens when called recursively inside of the math expression:
            script.MoveForwardIf(Constants.END_ARG);

            return(listToMerge);
        }