Exemplo n.º 1
0
        void ParseVarset(ScopeGroup scope, VarSetNode varSetNode)
        {
            DefinedVar variable = scope.GetVar(varSetNode.Variable, varSetNode.Range, Diagnostics);

            Element target = null;

            if (varSetNode.Target != null)
            {
                target = ParseExpression(scope, varSetNode.Target);
            }

            Element value = ParseExpression(scope, varSetNode.Value);

            Element initialVar = variable.GetVariable(target);

            Element index = null;

            if (varSetNode.Index != null)
            {
                index      = ParseExpression(scope, varSetNode.Index);
                initialVar = Element.Part <V_ValueInArray>(initialVar, index);
            }


            switch (varSetNode.Operation)
            {
            case "+=":
                value = Element.Part <V_Add>(initialVar, value);
                break;

            case "-=":
                value = Element.Part <V_Subtract>(initialVar, value);
                break;

            case "*=":
                value = Element.Part <V_Multiply>(initialVar, value);
                break;

            case "/=":
                value = Element.Part <V_Divide>(initialVar, value);
                break;

            case "^=":
                value = Element.Part <V_RaiseToPower>(initialVar, value);
                break;

            case "%=":
                value = Element.Part <V_Modulo>(initialVar, value);
                break;
            }

            Actions.Add(variable.SetVariable(value, target, index));
        }
Exemplo n.º 2
0
        void ParseStatement(DeltinScriptParser.StatementContext statementContext)
        {
            #region Method
            if (statementContext.GetChild(0) is DeltinScriptParser.MethodContext)
            {
                Actions.Add(ParseMethod(statementContext.GetChild(0) as DeltinScriptParser.MethodContext, false));
                return;
            }
            #endregion

            #region Variable set

            if (statementContext.STATEMENT_OPERATION() != null)
            {
                DefinedVar variable;
                Element    target;
                Element    index     = null;
                string     operation = statementContext.STATEMENT_OPERATION().GetText();

                Element value;

                value = ParseExpression(statementContext.expr(1) as DeltinScriptParser.ExprContext);

                /*  Format if the variable has an expression beforehand (sets the target player)
                 *               expr(0)           .ChildCount
                 *                 v                   v
                 *  Statement (    v                   v          ) | Operation | Set to variable
                 *             Variable to set (       v         )
                 *                 ^            expr | . | expr
                 *                 ^                   ^
                 *               expr(0)          .GetChild(1) == '.'                               */
                if (statementContext.expr(0).ChildCount == 3 &&
                    statementContext.expr(0).GetChild(1).GetText() == ".")
                {
                    /*  Get Variable:  .expr(0)              .expr(1)
                     *                   v                     v  .expr(1) (if the value to be set is an array)
                     *  Statement (      v                     v      v    ) | Operation | Set to variable
                     *             Variable to set (           v      v  )
                     *                   ^          expr | . | expr | []
                     *                   ^           ^
                     *  Get  Target:  .expr(0)    .expr(0)                                            */

                    variable = DefinedVar.GetVar(statementContext.expr(0).expr(1).GetChild(0).GetText(),
                                                 statementContext.expr(0).expr(1).start);
                    target = ParseExpression(statementContext.expr(0).expr(0));

                    // Get the index if the variable has []
                    var indexExpression = statementContext.expr(0).expr(1).expr(1);
                    if (indexExpression != null)
                    {
                        index = ParseExpression(indexExpression);
                    }
                }
                else
                {
                    /*               .expr(0)             .expr(1)
                     *                  v                   v
                     *  Statement (     v                   v  ) | Operation | Set to variable
                     *             Variable to set (expr) | []
                     */
                    variable = DefinedVar.GetVar(statementContext.expr(0).GetChild(0).GetText(),
                                                 statementContext.expr(0).start);
                    target = new V_EventPlayer();

                    // Get the index if the variable has []
                    var indexExpression = statementContext.expr(0).expr(1);
                    if (indexExpression != null)
                    {
                        index = ParseExpression(indexExpression);
                    }
                }

                switch (operation)
                {
                case "+=":
                    value = Element.Part <V_Add>(variable.GetVariable(target, index), value);
                    break;

                case "-=":
                    value = Element.Part <V_Subtract>(variable.GetVariable(target, index), value);
                    break;

                case "*=":
                    value = Element.Part <V_Multiply>(variable.GetVariable(target, index), value);
                    break;

                case "/=":
                    value = Element.Part <V_Divide>(variable.GetVariable(target, index), value);
                    break;

                case "^=":
                    value = Element.Part <V_RaiseToPower>(variable.GetVariable(target, index), value);
                    break;

                case "%=":
                    value = Element.Part <V_Modulo>(variable.GetVariable(target, index), value);
                    break;
                }

                Actions.Add(variable.SetVariable(value, target, index));
                return;
            }

            #endregion

            #region for

            if (statementContext.GetChild(0) is DeltinScriptParser.ForContext)
            {
                /*
                 * CreateInitialSkip = true;
                 *
                 * if (SkipCountIndex == -1)
                 *  SkipCountIndex = Assign();
                 */

                // The action the for loop starts on.
                // +1 for the counter reset.
                int forActionStartIndex = Actions.Count() + 1;

                // The target array in the for statement.
                Element forArrayElement = ParseExpression(statementContext.@for().expr());

                // Use skipIndex with Get/SetIVarAtIndex to get the bool to determine if the loop is running.
                Var isBoolRunningSkipIf = Var.AssignVar(IsGlobal);
                // Insert the SkipIf at the start of the rule.
                Actions.Insert(0,
                               Element.Part <A_SkipIf>
                               (
                                   // Condition
                                   isBoolRunningSkipIf.GetVariable(),
                                   // Number of actions
                                   new V_Number(forActionStartIndex)
                               )
                               );

                // Create the for's temporary variable.
                DefinedVar forTempVar = Var.AssignDefinedVar(
                    name: statementContext.@for().PART().GetText(),
                    isGlobal: IsGlobal,
                    token: statementContext.@for().start
                    );

                // Reset the counter.
                Actions.Add(forTempVar.SetVariable(new V_Number(0)));

                // Parse the for's block.
                ParseBlock(statementContext.@for().block());

                // Take the variable out of scope.
                forTempVar.OutOfScope();

                // Add the for's finishing elements
                //Actions.Add(SetIVarAtIndex(skipIndex, new V_Number(forActionStartIndex))); // Sets how many variables to skip in the next iteraction.
                Actions.Add(isBoolRunningSkipIf.SetVariable(new V_True())); // Enables the skip.

                Actions.Add(forTempVar.SetVariable(                         // Indent the index by 1.
                                Element.Part <V_Add>
                                (
                                    forTempVar.GetVariable(),
                                    new V_Number(1)
                                )
                                ));

                Actions.Add(Element.Part <A_Wait>(new V_Number(0.06), WaitBehavior.IgnoreCondition)); // Add the Wait() required by the workshop.
                Actions.Add(Element.Part <A_LoopIf>(                                                  // Loop if the for condition is still true.
                                Element.Part <V_Compare>
                                (
                                    forTempVar.GetVariable(),
                                    Operators.LessThan,
                                    Element.Part <V_CountOf>(forArrayElement)
                                )
                                ));
                Actions.Add(isBoolRunningSkipIf.SetVariable(new V_False()));
                return;
            }

            #endregion

            #region if

            if (statementContext.GetChild(0) is DeltinScriptParser.IfContext)
            {
                /*
                 * Syntax after parse:
                 *
                 * If:
                 *  Skip If (Not (expr))
                 *  (body)
                 *  Skip - Only if there is if-else or else statements.
                 * Else if:
                 *  Skip If (Not (expr))
                 *  (body)
                 *  Skip - Only if there is more if-else or else statements.
                 * Else:
                 *  (body)
                 *
                 */

                // Add dummy action, create after body is created.
                int skipIfIndex = Actions.Count();
                Actions.Add(null);

                // Parse the if body.
                ParseBlock(statementContext.@if().block());

                // Determines if the "Skip" action after the if block will be created.
                // Only if there is if-else or else statements.
                bool addIfSkip = statementContext.@if().else_if().Count() > 0 || statementContext.@if().@else() != null;

                // Create the inital "SkipIf" action now that we know how long the if's body is.
                // Add one to the body length if a Skip action is going to be added.
                Actions.RemoveAt(skipIfIndex);
                Actions.Insert(skipIfIndex, Element.Part <A_SkipIf>(Element.Part <V_Not>(ParseExpression(statementContext.@if().expr())), new V_Number(Actions.Count - skipIfIndex + (addIfSkip ? 1 : 0))));

                // Create the "Skip" dummy action.
                int skipIndex = -1;
                if (addIfSkip)
                {
                    skipIndex = Actions.Count();
                    Actions.Add(null);
                }

                // Parse else-ifs
                var   skipIfContext = statementContext.@if().else_if();
                int[] skipIfData    = new int[skipIfContext.Length]; // The index where the else if's "Skip" action is.
                for (int i = 0; i < skipIfContext.Length; i++)
                {
                    // Create the dummy action.
                    int skipIfElseIndex = Actions.Count();
                    Actions.Add(null);

                    // Parse the else-if body.
                    ParseBlock(skipIfContext[i].block());

                    // Determines if the "Skip" action after the else-if block will be created.
                    // Only if there is additional if-else or else statements.
                    bool addIfElseSkip = i < skipIfContext.Length - 1 || statementContext.@if().@else() != null;

                    // Create the "Skip If" action.
                    Actions.RemoveAt(skipIfElseIndex);
                    Actions.Insert(skipIfElseIndex, Element.Part <A_SkipIf>(Element.Part <V_Not>(ParseExpression(skipIfContext[i].expr())), new V_Number(Actions.Count - skipIfElseIndex + (addIfElseSkip ? 1 : 0))));

                    // Create the "Skip" dummy action.
                    if (addIfElseSkip)
                    {
                        skipIfData[i] = Actions.Count();
                        Actions.Add(null);
                    }
                }

                // Parse else body.
                if (statementContext.@if().@else() != null)
                {
                    ParseBlock(statementContext.@if().@else().block());
                }

                // Replace dummy skip with real skip now that we know the length of the if, if-else, and else's bodies.
                // Replace if's dummy.
                if (skipIndex != -1)
                {
                    Actions.RemoveAt(skipIndex);
                    Actions.Insert(skipIndex, Element.Part <A_Skip>(new V_Number(Actions.Count - skipIndex)));
                }

                // Replace else-if's dummy.
                for (int i = 0; i < skipIfData.Length; i++)
                {
                    if (skipIfData[i] != 0)
                    {
                        Actions.RemoveAt(skipIfData[i]);
                        Actions.Insert(skipIfData[i], Element.Part <A_Skip>(new V_Number(Actions.Count - skipIfData[i])));
                    }
                }

                return;
            }

            #endregion

            throw new Exception($"What's a {statementContext.GetChild(0)} ({statementContext.GetChild(0).GetType()})?");
        }
Exemplo n.º 3
0
        void ParseStatement(ScopeGroup scope, IStatementNode statement, Var returnVar, bool isLast)
        {
            switch (statement)
            {
            // Method
            case MethodNode methodNode:
                Element method = ParseMethod(scope, methodNode, false);
                if (method != null)
                {
                    Actions.Add(method);
                }
                return;

            // Variable set
            case VarSetNode varSetNode:
                ParseVarset(scope, varSetNode);
                return;

            // For
            case ForEachNode forEachNode:
            {
                ContinueSkip.Setup();

                // The action the for loop starts on.
                int forActionStartIndex = Actions.Count() - 1;

                ScopeGroup forGroup = scope.Child();

                // Create the for's temporary variable.
                DefinedVar forTempVar = VarCollection.AssignDefinedVar(
                    scopeGroup: forGroup,
                    name: forEachNode.Variable,
                    isGlobal: IsGlobal,
                    range: forEachNode.Range
                    );

                // Reset the counter.
                Actions.Add(forTempVar.SetVariable(new V_Number(0)));

                // Parse the for's block.
                ParseBlock(forGroup, forEachNode.Block, false, returnVar);

                // Add the for's finishing elements
                Actions.Add(forTempVar.SetVariable(     // Indent the index by 1.
                                Element.Part <V_Add>
                                (
                                    forTempVar.GetVariable(),
                                    new V_Number(1)
                                )
                                ));

                ContinueSkip.SetSkipCount(forActionStartIndex);

                // The target array in the for statement.
                Element forArrayElement = ParseExpression(scope, forEachNode.Array);

                Actions.Add(Element.Part <A_LoopIf>(    // Loop if the for condition is still true.
                                Element.Part <V_Compare>
                                (
                                    forTempVar.GetVariable(),
                                    EnumData.GetEnumValue(Operators.LessThan),
                                    Element.Part <V_CountOf>(forArrayElement)
                                )
                                ));

                ContinueSkip.ResetSkip();
                return;
            }

            // For
            case ForNode forNode:
            {
                ContinueSkip.Setup();

                // The action the for loop starts on.
                int forActionStartIndex = Actions.Count() - 1;

                ScopeGroup forGroup = scope.Child();

                // Set the variable
                if (forNode.VarSetNode != null)
                {
                    ParseVarset(scope, forNode.VarSetNode);
                }
                if (forNode.DefineNode != null)
                {
                    ParseDefine(scope, forNode.DefineNode);
                }

                // Parse the for's block.
                ParseBlock(forGroup, forNode.Block, false, returnVar);

                Element expression = null;
                if (forNode.Expression != null)
                {
                    expression = ParseExpression(forGroup, forNode.Expression);
                }

                // Check the expression
                if (forNode.Expression != null)     // If it has an expression
                {
                    // Parse the statement
                    if (forNode.Statement != null)
                    {
                        ParseStatement(forGroup, forNode.Statement, returnVar, false);
                    }

                    ContinueSkip.SetSkipCount(forActionStartIndex);
                    Actions.Add(Element.Part <A_LoopIf>(expression));
                }
                // If there is no expression but there is a statement, parse the statement.
                else if (forNode.Statement != null)
                {
                    ParseStatement(forGroup, forNode.Statement, returnVar, false);
                    ContinueSkip.SetSkipCount(forActionStartIndex);
                    // Add the loop
                    Actions.Add(Element.Part <A_Loop>());
                }

                ContinueSkip.ResetSkip();
                return;
            }

            // While
            case WhileNode whileNode:
            {
                ContinueSkip.Setup();

                // The action the while loop starts on.
                int whileStartIndex = Actions.Count() - 2;

                ScopeGroup whileGroup = scope.Child();

                ParseBlock(whileGroup, whileNode.Block, false, returnVar);

                ContinueSkip.SetSkipCount(whileStartIndex);

                // Add the loop-if
                Element expression = ParseExpression(scope, whileNode.Expression);
                Actions.Add(Element.Part <A_LoopIf>(expression));

                ContinueSkip.ResetSkip();
                return;
            }

            // If
            case IfNode ifNode:
            {
                A_SkipIf if_SkipIf = new A_SkipIf();
                Actions.Add(if_SkipIf);

                var ifScope = scope.Child();

                // Parse the if body.
                ParseBlock(ifScope, ifNode.IfData.Block, false, returnVar);

                // Determines if the "Skip" action after the if block will be created.
                // Only if there is if-else or else statements.
                bool addIfSkip = ifNode.ElseIfData.Length > 0 || ifNode.ElseBlock != null;

                // Update the initial SkipIf's skip count now that we know the number of actions the if block has.
                // Add one to the body length if a Skip action is going to be added.
                if_SkipIf.ParameterValues = new IWorkshopTree[]
                {
                    Element.Part <V_Not>(ParseExpression(scope, ifNode.IfData.Expression)),
                    new V_Number(Actions.Count - 1 - Actions.IndexOf(if_SkipIf) + (addIfSkip ? 1 : 0))
                };

                // Create the "Skip" action.
                A_Skip if_Skip = new A_Skip();
                if (addIfSkip)
                {
                    Actions.Add(if_Skip);
                }

                // Parse else-ifs
                A_Skip[] elseif_Skips = new A_Skip[ifNode.ElseIfData.Length];     // The ElseIf's skips
                for (int i = 0; i < ifNode.ElseIfData.Length; i++)
                {
                    // Create the SkipIf action for the else if.
                    A_SkipIf elseif_SkipIf = new A_SkipIf();
                    Actions.Add(elseif_SkipIf);

                    // Parse the else-if body.
                    var elseifScope = scope.Child();
                    ParseBlock(elseifScope, ifNode.ElseIfData[i].Block, false, returnVar);

                    // Determines if the "Skip" action after the else-if block will be created.
                    // Only if there is additional if-else or else statements.
                    bool addIfElseSkip = i < ifNode.ElseIfData.Length - 1 || ifNode.ElseBlock != null;

                    // Set the SkipIf's parameters.
                    elseif_SkipIf.ParameterValues = new IWorkshopTree[]
                    {
                        Element.Part <V_Not>(ParseExpression(scope, ifNode.ElseIfData[i].Expression)),
                        new V_Number(Actions.Count - 1 - Actions.IndexOf(elseif_SkipIf) + (addIfElseSkip ? 1 : 0))
                    };

                    // Create the "Skip" action for the else-if.
                    if (addIfElseSkip)
                    {
                        elseif_Skips[i] = new A_Skip();
                        Actions.Add(elseif_Skips[i]);
                    }
                }

                // Parse else body.
                if (ifNode.ElseBlock != null)
                {
                    var elseScope = scope.Child();
                    ParseBlock(elseScope, ifNode.ElseBlock, false, returnVar);
                }

                // Replace dummy skip with real skip now that we know the length of the if, if-else, and else's bodies.
                // Replace if's dummy.
                if_Skip.ParameterValues = new IWorkshopTree[]
                {
                    new V_Number(Actions.Count - 1 - Actions.IndexOf(if_Skip))
                };

                // Replace else-if's dummy.
                for (int i = 0; i < elseif_Skips.Length; i++)
                {
                    if (elseif_Skips[i] != null)
                    {
                        elseif_Skips[i].ParameterValues = new IWorkshopTree[]
                        {
                            new V_Number(Actions.Count - 1 - Actions.IndexOf(elseif_Skips[i]))
                        };
                    }
                }

                return;
            }

            // Return
            case ReturnNode returnNode:

                if (returnNode.Value != null)
                {
                    Element result = ParseExpression(scope, returnNode.Value);
                    if (returnVar != null)
                    {
                        Actions.Add(returnVar.SetVariable(result));
                    }
                }

                if (!isLast)
                {
                    A_Skip returnSkip = new A_Skip();
                    Actions.Add(returnSkip);
                    ReturnSkips.Add(returnSkip);
                }

                return;

            // Define
            case ScopedDefineNode defineNode:
                ParseDefine(scope, defineNode);
                return;
            }
        }