예제 #1
0
        public override void Compile(CompiledStatement parent, string token, LinkedList <string> tokens, LinkedList <string> lines)
        {
            base.Compile(parent, token, tokens, lines);

            // We know the token will at least start with the start delimiter
            if (token.Length > 1)
            {
                // In here if the start delimiter and another token are smushed together with no space
                // Split the start delimiter and the rest of the token and add the rest of the token to the start of our tokens list
                string rest = token.Remove(0, 1);
                tokens.AddFirst(rest);
            }

            // We keep parsing until we find a closing character for our list
            bool foundClosing = false;

            while (!foundClosing)
            {
                Debug.Assert(tokens.Count > 0 || lines.Count > 0, "List requires a closing " + endDelimiter);

                // Create a new set of tokens if we have run out for this line
                if (tokens.Count == 0)
                {
                    CelesteCompiler.TokenizeNextLine();
                }

                string nextToken = CelesteCompiler.PopToken();
                if (nextToken.EndsWith(endDelimiter) && nextToken.Length > 1)
                {
                    // Our token has the end delimiter squashed at the end of it, so we split the token in two and add the delimiter to the tokens list
                    // This will mean we still compile this token and finish our list the next iteration round
                    nextToken = nextToken.Remove(nextToken.Length - 1);
                    tokens.AddFirst(endDelimiter);
                }

                if (nextToken == endDelimiter)
                {
                    foundClosing = true;
                }
                else if (CelesteCompiler.CompileToken(nextToken, parent))
                {
                    // Take the value that has been created from compiling this token and add it to our list
                    // Then remove the compiled statement - we do not want objects in our list pushed onto the stack
                    CompiledStatement valueCreated = parent.ChildCompiledStatements[parent.ChildCount - 1];
                    parent.RemoveAt(parent.ChildCount - 1);

                    // The value we created MUST be a value
                    Debug.Assert(valueCreated is Value);
                    ListRef.Add((valueCreated as Value)._Value);
                }
                else
                {
                    // Error message if we cannot parse the next token
                    Debug.Fail("Error parsing token: " + token + " in list");
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Reads in the condition for the while loop and then the body to perform while the condition is true.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="token"></param>
        /// <param name="tokens"></param>
        /// <param name="lines"></param>
        public override void Compile(CompiledStatement parent, string token, LinkedList <string> tokens, LinkedList <string> lines)
        {
            base.Compile(parent, token, tokens, lines);

            KeyValuePair <CompiledStatement, CompiledStatement> whileCondBody = new KeyValuePair <CompiledStatement, CompiledStatement>(new CompiledStatement(), new CompiledStatement());

            ConditionsAndBodies.Add(whileCondBody);

            Debug.Assert(tokens.Count > 0, "Tokens required for while condition");
            while (tokens.Count > 0)
            {
                CelesteCompiler.CompileToken(CelesteCompiler.PopToken(), whileCondBody.Key);
            }

            // We keep parsing until we find the closing keyword for our while control
            bool foundClosing = false;

            while (!foundClosing)
            {
                Debug.Assert(tokens.Count > 0 || lines.Count > 0, "Function requires a closing " + endDelimiter);

                // Create a new set of tokens if we have run out for this line
                if (tokens.Count == 0)
                {
                    CelesteCompiler.TokenizeNextLine();
                }

                string nextToken = CelesteCompiler.PopToken();
                if (nextToken == endDelimiter)
                {
                    foundClosing = true;
                }
                else if (CelesteCompiler.CompileToken(nextToken, whileCondBody.Value))
                {
                }
                else
                {
                    // Error message if we cannot parse the next token
                    Debug.Fail("Operator invalid on token: " + token);
                }
            }

            // Close the scope that is automatically opened in our constructor
            CelesteStack.CurrentScope = FlowScope.ParentScope;
        }
예제 #3
0
        public override void Compile(CompiledStatement parent, string token, LinkedList <string> tokens, LinkedList <string> lines)
        {
            base.Compile(parent, token, tokens, lines);

            // We know the token will at least start with the start delimiter
            if (token.Length > 1)
            {
                // In here if the start delimiter and another token are smushed together with no space
                // Split the start delimiter and the rest of the token and add the rest of the token to the start of our tokens list
                string rest = token.Remove(0, 1);
                tokens.AddFirst(rest);
            }

            // We keep parsing until we find a closing character for our list
            bool foundClosing = false;

            while (!foundClosing)
            {
                Debug.Assert(tokens.Count > 0 || lines.Count > 0, "Table requires a closing " + endDelimiter);

                // Create a new set of tokens if we have run out for this line
                if (tokens.Count == 0)
                {
                    CelesteCompiler.TokenizeNextLine();
                }

                string nextToken = CelesteCompiler.PopToken();
                if (nextToken == AssignmentOperator.scriptToken)
                {
                    string valueToken = tokens.First.Value;
                    if (valueToken.EndsWith(endDelimiter) && valueToken.Length > 1)
                    {
                        valueToken         = valueToken.Remove(valueToken.Length - 1, 1);
                        tokens.First.Value = valueToken;
                        foundClosing       = true;
                    }
                }

                if (nextToken == endDelimiter)
                {
                    foundClosing = true;
                }
                else if (CelesteCompiler.CompileToken(nextToken, parent))
                {
                    CompiledStatement compiledStatement = parent.ChildCompiledStatements[parent.ChildCount - 1];

                    if (!gotKey)
                    {
                        // The statement we created for our key MUST be a value type
                        Debug.Assert(compiledStatement is Value, "Key in table must be a valid value type");
                        gotKey = true;
                    }
                    else if (!gotEquality)
                    {
                        // The statement we created after our key MUST be the equality operator
                        Debug.Assert(compiledStatement is AssignmentOperator, "Equality expected after key");
                        gotEquality = true;
                        gotValue    = compiledStatement.ChildCount == 2;
                    }

                    if (gotValue)
                    {
                        // We have an equals parented under the 'parent' parameter (along with this table), with the key and value parented under that
                        // We insert the key and value into our dictionary, discard the equals statement and adjust our flags
                        Debug.Assert(parent.ChildCount >= 2);
                        Debug.Assert(parent.ChildCompiledStatements[parent.ChildCount - 1].ChildCount == 2);
                        Debug.Assert(parent.ChildCompiledStatements[parent.ChildCount - 1] is AssignmentOperator);

                        AssignmentOperator equals = parent.ChildCompiledStatements[parent.ChildCount - 1] as AssignmentOperator;
                        Debug.Assert(equals.ChildCompiledStatements[0] is Value);
                        Debug.Assert(equals.ChildCompiledStatements[1] is Value);

                        DictionaryRef.Add((equals.ChildCompiledStatements[0] as Value)._Value, (equals.ChildCompiledStatements[1] as Value)._Value);
                        parent.ChildCompiledStatements.RemoveAt(parent.ChildCount - 1);

                        gotKey      = false;
                        gotEquality = false;
                        gotValue    = false;
                    }
                }
                else
                {
                    // Error message if we cannot parse the next token
                    Debug.Fail("Operator invalid on token: " + token);
                }
            }

            Debug.Assert(!gotKey && !gotEquality && !gotValue, "Incomplete key value pair in table");
        }
예제 #4
0
        public override void Compile(CompiledStatement parent, string token, LinkedList <string> tokens, LinkedList <string> lines)
        {
            base.Compile(parent, token, tokens, lines);

            // Now check that there is another element after our keyword that we can use as the function name
            Debug.Assert(tokens.Count > 0 || lines.Count > 0, "No parameters or body found for the keyword: " + token);

            // The first token should be the function name
            string functionName = CelesteCompiler.PopToken();

            Debug.Assert(!CelesteStack.CurrentScope.VariableExists(functionName), "Variable with the same name already exists in this scope");

            // Get the next token - this should be an opening parenthesis
            string openingParenthesis = CelesteCompiler.PopToken();

            Debug.Assert(openingParenthesis == OpenParenthesis.scriptToken, "No opening parenthesis found for function " + functionName);

            // Creates a new function, but does not call Compile - Compile for function assigns a reference from the stored function in CelesteStack
            Function function = CelesteStack.CurrentScope.CreateLocalVariable <Function>(functionName);

            // Obtain the parameter names from the strings/tokens between the brackets
            List <string> paramNames = new List <string>();
            string        parameters = CelesteCompiler.PopToken();

            while (parameters != CloseParenthesis.scriptToken)
            {
                // Clean the parameter array of empty strings and remove any delimiter characters from parameter names
                List <string> parameterList = new List <string>(parameters.Split(Delimiter.scriptTokenChar));
                parameterList.RemoveAll(x => string.IsNullOrEmpty(x));
                parameterList = new List <string>(parameterList.Select(x => x = x.Replace(Delimiter.scriptToken, "")));

                // Add any parameters which are of this form 'param1,param2'
                paramNames.AddRange(parameterList);

                parameters = CelesteCompiler.PopToken();// This algorithm should completely take care of any mix of parameters separated with a space or not
            }

            function.SetParameters(paramNames.ToArray());

            // We keep parsing until we find the closing keyword for our function
            bool foundClosing = false;

            while (!foundClosing)
            {
                Debug.Assert(tokens.Count > 0 || lines.Count > 0, "Function requires a closing " + endDelimiter);

                // Create a new set of tokens if we have run out for this line
                if (tokens.Count == 0)
                {
                    CelesteCompiler.TokenizeNextLine();
                }

                string nextToken = CelesteCompiler.PopToken();
                if (nextToken == endDelimiter)
                {
                    foundClosing = true;
                }
                else if (CelesteCompiler.CompileToken(nextToken, function.FuncImpl))
                {
                }
                else
                {
                    // Error message if we cannot parse the next token
                    Debug.Fail("Operator invalid on token: " + token);
                }
            }

            // Do not add the function - it will be looked up to and called rather than pushed onto the stack (much like a variable)
            // Close the function's scope now - we have added all the appropriate variables to it
            // This scope is automatically opened in the Function constructor
            CelesteStack.CurrentScope = function.FunctionScope.ParentScope;
        }