Esempio n. 1
0
        private static Expression Parse(IEnumerator <Token> tokens, bool isCompoundArgument)
        {
            Stack <Expression> stack = new Stack <Expression>();

            CommandInvocationExpression lastCommand   = null;
            ConditionalExpression       lastCondition = null;
            SeriesExpression            lastSeries    = null;

            Expression temp = null;

            while (tokens.MoveNext())
            {
                var tok = tokens.Current;

                /*System.Diagnostics.Debug.WriteLine("BEFORE:");
                 * System.Diagnostics.Debug.WriteLine("Token: {0} | \"{1}\" | {2} | {3} | {4}", tok.Type, tok.Content, lastCommand, lastSeries, lastCondition);
                 *
                 * System.Diagnostics.Debug.WriteLine("Stack dump:");
                 *
                 * foreach (var stuff in stack)
                 *  System.Diagnostics.Debug.WriteLine("\t<{0}> ({1})", stuff, stuff.GetType());//*/

                switch (tok.Type)
                {
                case TokenTypes.Toggler:
                    if (tok.Content != "+" && tok.Content != "-")
                    {
                        throw new FormatException("Invalid toggler token!");
                    }

                    lastCommand = new CommandInvocationExpression(toggle: tok.Content == "+" ? Toggler.On : Toggler.Off);

                    //  Conditionals have higher priority than series.

                    if (lastCondition != null)
                    {
                        if (lastCondition.PrimaryAction == null)
                        {
                            lastCondition.PrimaryAction = lastCommand;
                        }
                        else if (lastCondition.SecondaryAction == null)
                        {
                            lastCondition.SecondaryAction = lastCommand;
                        }
                        else
                        {
                            throw new ArgumentException("No series and a full conditional preceeds a toggler.");
                        }
                    }
                    else if (lastSeries != null)
                    {
                        lastSeries.AddExpression(lastCommand);
                    }
                    else if (stack.Count > 0)
                    {
                        throw new FormatException("Toggler follows in a non-empty stack, but there are no preceding series or conditions.");
                    }

                    stack.Push(lastCommand);

                    break;

                case TokenTypes.CommandName:
                    if (lastCommand == null)
                    {
                        stack.Push(lastCommand = new CommandInvocationExpression(commandName: tok.Content));
                    }
                    else if (lastCommand.CommandName == null)
                    {
                        //  This means there was a toggler before.

                        lastCommand.CommandName = tok.Content;

                        break;      //  So the code below already executed.
                    }
                    else
                    {
                        throw new FormatException("Last command execution expression already contains a command name.");
                    }

                    if (lastCondition != null)
                    {
                        if (lastCondition.PrimaryAction == null)
                        {
                            lastCondition.PrimaryAction = lastCommand;
                        }
                        else if (lastCondition.SecondaryAction == null)
                        {
                            lastCondition.SecondaryAction = lastCommand;
                        }
                        else
                        {
                            throw new ArgumentException("No series and a full conditional preceeds a command name.");
                        }
                    }
                    else if (lastSeries != null)
                    {
                        lastSeries.AddExpression(lastCommand);
                    }

                    break;

                case TokenTypes.Argument:
                    //if (lastCommand == null)
                    //    lastCommand = stack.Peek() as CommandExecutionExpression;

                    if (lastCommand == null)
                    {
                        throw new FormatException("An argument seems to not be preceded by a command.");
                    }

                    lastCommand.AddArgument(ConstantExpression.Fetch(tok.Content));

                    break;

                case TokenTypes.Separator:
                    var didNothing = true;

                    if (lastCommand != null)
                    {
                        lastCommand.Seal();
                        lastCommand = null;
                        didNothing  = false;
                        temp        = stack.Pop();
                    }

                    if (lastCondition != null)
                    {
                        lastCondition.Seal();
                        lastCondition = null;
                        didNothing    = false;
                        temp          = stack.Pop();
                    }

                    if (didNothing)
                    {
                        throw new FormatException("Separator does not follow anything.");
                    }

                    if (lastSeries == null)
                    {
                        if (temp != null)
                        {
                            //temp = stack.Pop();

                            lastSeries = new SeriesExpression(new Expression[] { temp });

                            stack.Push(lastSeries);
                        }
                        else
                        {
                            throw new FormatException("A separator does not have any commands to separate.");
                        }
                    }
                    //else
                    //    stack.Pop();    //  Make it ready to receive more commands.

                    break;

                case TokenTypes.Include:
                case TokenTypes.Exclude:
                    if (lastCondition != null)
                    {
                        if (lastCommand != null)
                        {
                            stack.Pop().Seal();
                        }

                        stack.Pop().Seal();

                        lastCondition = new ConditionalExpression(tok.Type == TokenTypes.Include, lastCondition);

                        stack.Push(lastCondition);
                        lastCommand = null;
                    }
                    else if (lastCommand != null)
                    {
                        stack.Pop().Seal();

                        lastCondition = new ConditionalExpression(tok.Type == TokenTypes.Include, lastCommand);

                        stack.Push(lastCondition);
                        lastCommand = null;
                    }
                    else
                    {
                        throw new FormatException("Inclusion does not follow a command.");
                    }

                    if (lastSeries != null)
                    {
                        lastSeries.exprs[lastSeries.exprs.Count - 1] = lastCondition;
                    }

                    break;

                case TokenTypes.Otherwise:
                    if (lastCondition == null)
                    {
                        throw new FormatException("Otherwise token does not follow a conditional.");
                    }
                    else if (lastCondition.PrimaryAction == null)
                    {
                        throw new FormatException("Otherwise follows a conditional with no primary action.");
                    }
                    else if (lastCondition.SecondaryAction != null)
                    {
                        throw new FormatException("Otherwise follows a conditional which already contains a secondary action.");
                    }

                    if (lastCommand == null)
                    {
                        throw new FormatException("Otherwise token does not follow a command (which would be the primary action).");
                    }

                    lastCommand = null;
                    stack.Pop().Seal();        //  Pop the primary action.

                    break;

                case TokenTypes.CompoundArgumentStart:
                    if (lastCommand == null)
                    {
                        throw new FormatException("A compound argument seems to not be preceded by a command.");
                    }

                    lastCommand.AddArgument(Parse(tokens, true));

                    break;

                case TokenTypes.CompoundArgumentEnd:
                    if (lastCommand == null)
                    {
                        throw new FormatException("A compound argument seems to end with no command.");
                    }

                    if (isCompoundArgument)
                    {
                        return(SealAllAndReturnLast(stack));
                    }
                    else
                    {
                        throw new FormatException("A compound argument end token doesn't seem to end any argument.");
                    }
                }

                /*System.Diagnostics.Debug.WriteLine("AFTER:");
                 * System.Diagnostics.Debug.WriteLine("Token: {0} | \"{1}\" | {2} | {3} | {4}", tok.Type, tok.Content, lastCommand, lastSeries, lastCondition);
                 *
                 * System.Diagnostics.Debug.WriteLine("Stack dump:");
                 *
                 * foreach (var stuff in stack)
                 *  System.Diagnostics.Debug.WriteLine("\t<{0}> ({1})", stuff, stuff.GetType());
                 *
                 * System.Diagnostics.Debug.WriteLine("");//*/
            }

            /*System.Diagnostics.Debug.WriteLine("END Stack dump:");
             *
             * foreach (var stuff in stack)
             *  System.Diagnostics.Debug.WriteLine("\t<{0}> ({1})", stuff, stuff.GetType());//*/

            return(SealAllAndReturnLast(stack));
        }