Esempio n. 1
0
        public override Node VisitRuleset(DeltinScriptParser.RulesetContext context)
        {
            RuleNode[] rules = new RuleNode[context.ow_rule().Length];
            for (int i = 0; i < rules.Length; i++)
            {
                rules[i] = (RuleNode)VisitOw_rule(context.ow_rule()[i]);
            }

            Variable useGlobalVar;
            Variable usePlayerVar;

            Enum.TryParse <Variable>(context.useGlobalVar()?.PART().GetText(), out useGlobalVar);
            Enum.TryParse <Variable>(context.usePlayerVar()?.PART().GetText(), out usePlayerVar);

            DefinedNode[] definedVars = new DefinedNode[context.vardefine().Length];
            for (int i = 0; i < definedVars.Length; i++)
            {
                definedVars[i] = (DefinedNode)VisitVardefine(context.vardefine()[i]);
            }

            UserMethodNode[] userMethods = new UserMethodNode[context.user_method().Length];
            for (int i = 0; i < userMethods.Length; i++)
            {
                userMethods[i] = (UserMethodNode)VisitUser_method(context.user_method()[i]);
            }

            Node node = new RulesetNode(rules, useGlobalVar, usePlayerVar, definedVars, userMethods, Range.GetRange(context));

            CheckRange(node);
            return(node);
        }
        private TranslateRule(RuleNode ruleNode, ScopeGroup root, ParsingData parserData)
        {
            VarCollection = parserData.VarCollection;
            ParserData    = parserData;

            Rule          = new Rule(ruleNode.Name, ruleNode.Event, ruleNode.Team, ruleNode.Player);
            Rule.Disabled = ruleNode.Disabled;
            IsGlobal      = Rule.IsGlobal;

            ContinueSkip = new ContinueSkip(IsGlobal, Actions, VarCollection);

            ParseConditions(root, ruleNode.Conditions);

            // Parse the block of the rule.
            ScopeGroup ruleScope = root.Child();

            ParseBlock(ruleScope, ruleScope, ruleNode.Block, false, null);

            // Fulfill remaining returns.
            FulfillReturns(0);

            Finish();
        }
Esempio n. 3
0
        public override Node VisitOw_rule(DeltinScriptParser.Ow_ruleContext context)
        {
            string    name  = context.STRINGLITERAL().GetText().Trim('"');
            BlockNode block = (BlockNode)VisitBlock(context.block());

            IExpressionNode[] conditions      = new IExpressionNode[context.rule_if()?.expr().Length ?? 0];
            Range[]           conditionRanges = new Range[context.rule_if()?.expr().Length ?? 0];
            for (int i = 0; i < conditions.Length; i++)
            {
                conditions[i]      = (IExpressionNode)VisitExpr(context.rule_if().expr()[i]);
                conditionRanges[i] = Range.GetRange(context.rule_if().expr()[i]);
            }

            RuleEvent      eventType = RuleEvent.OngoingGlobal;
            TeamSelector   team      = TeamSelector.All;
            PlayerSelector player    = PlayerSelector.All;

            Range eventRange  = null;
            Range teamRange   = null;
            Range playerRange = null;

            foreach (var ruleOption in context.rule_option())
            {
                string option      = ruleOption.PART(0).GetText();
                Range  optionRange = Range.GetRange(ruleOption.PART(0).Symbol);

                string value      = null;
                Range  valueRange = null;
                if (ruleOption.PART().Length == 2)
                {
                    value      = ruleOption.PART(1).GetText();
                    valueRange = Range.GetRange(ruleOption.PART(1).Symbol);
                }

                switch (option)
                {
                case "Event":
                    if (!Enum.TryParse <RuleEvent>(value, out eventType))
                    {
                        _diagnostics.Add(new Diagnostic($"{value} is not a valid Event type.", valueRange));
                    }
                    eventRange = Range.GetRange(ruleOption);
                    break;

                case "Team":
                    if (!Enum.TryParse <TeamSelector>(value, out team))
                    {
                        _diagnostics.Add(new Diagnostic($"{value} is not a valid Team type.", valueRange));
                    }
                    teamRange = Range.GetRange(ruleOption);
                    break;

                case "Player":
                    if (!Enum.TryParse <PlayerSelector>(value, out player))
                    {
                        _diagnostics.Add(new Diagnostic($"{value} is not a valid Player type.", valueRange));
                    }
                    playerRange = Range.GetRange(ruleOption);
                    break;

                default:
                    _diagnostics.Add(new Diagnostic($"{value} is not a valid rule option.", optionRange));
                    break;
                }
            }

            var node = new RuleNode(name, eventType, team, player, conditions, block, eventRange, teamRange, playerRange, Range.GetRange(context));

            CheckRange(node);
            return(node);
        }
Esempio n. 4
0
        private Translate(RuleNode ruleNode, ScopeGroup root, VarCollection varCollection, UserMethod[] userMethods)
        {
            Root          = root;
            VarCollection = varCollection;
            UserMethods   = userMethods;

            Rule     = new Rule(ruleNode.Name, ruleNode.Event, ruleNode.Team, ruleNode.Player);
            IsGlobal = Rule.IsGlobal;

            ContinueSkip = new ContinueSkip(IsGlobal, Actions, varCollection);

            ParseConditions(ruleNode.Conditions);
            ParseBlock(root.Child(), ruleNode.Block, false, null);

            Rule.Actions    = Actions.ToArray();
            Rule.Conditions = Conditions.ToArray();

            // Fufill remaining skips
            foreach (var skip in ReturnSkips)
            {
                skip.ParameterValues = new IWorkshopTree[] { new V_Number(Actions.Count - ReturnSkips.IndexOf(skip)) }
            }
            ;
            ReturnSkips.Clear();
        }

        void ParseConditions(IExpressionNode[] expressions)
        {
            foreach (var expr in expressions)
            {
                Element parsedIf = ParseExpression(Root, expr);
                // If the parsed if is a V_Compare, translate it to a condition.
                // Makes "(value1 == value2) == true" to just "value1 == value2"
                if (parsedIf is V_Compare)
                {
                    Element left = (Element)parsedIf.ParameterValues[0];
                    if (!left.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, left.Name, ((Node)expr).Range);
                    }

                    Element right = (Element)parsedIf.ParameterValues[2];
                    if (!right.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, right.Name, ((Node)expr).Range);
                    }

                    Conditions.Add(
                        new Condition(
                            left,
                            (EnumMember)parsedIf.ParameterValues[1],
                            right
                            )
                        );
                }
                // If not, just do "parsedIf == true"
                else
                {
                    if (!parsedIf.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, parsedIf.Name, ((Node)expr).Range);
                    }

                    Conditions.Add(new Condition(
                                       parsedIf, EnumData.GetEnumValue(Operators.Equal), new V_True()
                                       ));
                }
            }
        }

        Element ParseExpression(ScopeGroup scope, IExpressionNode expression)
        {
            switch (expression)
            {
            // Math and boolean operations.
            case OperationNode operationNode:
            {
                Element left  = ParseExpression(scope, operationNode.Left);
                Element right = ParseExpression(scope, operationNode.Right);

                /*
                 * if (Constants.BoolOperations.Contains(operationNode.Operation))
                 * {
                 *  if (left.ElementData.ValueType != Elements.ValueType.Any && left.ElementData.ValueType != Elements.ValueType.Boolean)
                 *      throw new SyntaxErrorException($"Expected boolean, got {left .ElementData.ValueType.ToString()} instead.", ((Node)operationNode.Left).Range);
                 *
                 *  if (right.ElementData.ValueType != Elements.ValueType.Any && right.ElementData.ValueType != Elements.ValueType.Boolean)
                 *      throw new SyntaxErrorException($"Expected boolean, got {right.ElementData.ValueType.ToString()} instead.", ((Node)operationNode.Right).Range);
                 * }
                 */

                switch (operationNode.Operation)
                {
                // Math: ^, *, %, /, +, -
                case "^":
                    return(Element.Part <V_RaiseToPower>(left, right));

                case "*":
                    return(Element.Part <V_Multiply>(left, right));

                case "%":
                    return(Element.Part <V_Modulo>(left, right));

                case "/":
                    return(Element.Part <V_Divide>(left, right));

                case "+":
                    return(Element.Part <V_Add>(left, right));

                case "-":
                    return(Element.Part <V_Subtract>(left, right));


                // BoolCompare: &, |
                case "&":
                    return(Element.Part <V_And>(left, right));

                case "|":
                    return(Element.Part <V_Or>(left, right));

                // Compare: <, <=, ==, >=, >, !=
                case "<":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.LessThan), right));

                case "<=":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.LessThanOrEqual), right));

                case "==":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.Equal), right));

                case ">=":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.GreaterThanOrEqual), right));

                case ">":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.GreaterThan), right));

                case "!=":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.NotEqual), right));
                }

                throw new Exception($"Operation {operationNode.Operation} not implemented.");
            }

            // Number
            case NumberNode numberNode:
                return(new V_Number(numberNode.Value));

            // Bool
            case BooleanNode boolNode:
                if (boolNode.Value)
                {
                    return(new V_True());
                }
                else
                {
                    return(new V_False());
                }

            // Not operation
            case NotNode notNode:
                return(Element.Part <V_Not>(ParseExpression(scope, notNode.Value)));

            // Strings
            case StringNode stringNode:
                Element[] stringFormat = new Element[stringNode.Format?.Length ?? 0];
                for (int i = 0; i < stringFormat.Length; i++)
                {
                    stringFormat[i] = ParseExpression(scope, stringNode.Format[i]);
                }
                return(V_String.ParseString(stringNode.Range, stringNode.Value, stringFormat));

            // Null
            case NullNode nullNode:
                return(new V_Null());

            // TODO check if groups need to be implemented here

            // Methods
            case MethodNode methodNode:
                return(ParseMethod(scope, methodNode, true));

            // Variable
            case VariableNode variableNode:
                return(scope.GetVar(variableNode.Name, variableNode.Range, Diagnostics)
                       .GetVariable(variableNode.Target != null ? ParseExpression(scope, variableNode.Target) : null));

            // Get value in array
            case ValueInArrayNode viaNode:
                return(Element.Part <V_ValueInArray>(ParseExpression(scope, viaNode.Value), ParseExpression(scope, viaNode.Index)));

            // Create array
            case CreateArrayNode createArrayNode:
            {
                Element prev    = null;
                Element current = null;

                for (int i = 0; i < createArrayNode.Values.Length; i++)
                {
                    current = new V_Append()
                    {
                        ParameterValues = new IWorkshopTree[2]
                    };

                    if (prev != null)
                    {
                        current.ParameterValues[0] = prev;
                    }
                    else
                    {
                        current.ParameterValues[0] = new V_EmptyArray();
                    }

                    current.ParameterValues[1] = ParseExpression(scope, createArrayNode.Values[i]);
                    prev = current;
                }

                return(current ?? new V_EmptyArray());
            }

            case EnumNode enumNode:
                return(EnumData.Special(enumNode.EnumMember)
                       ?? throw SyntaxErrorException.EnumCantBeValue(enumNode.Type, enumNode.Range));

                // Seperator
            }

            throw new Exception();
        }

        Element ParseMethod(ScopeGroup scope, MethodNode methodNode, bool needsToBeValue)
        {
            methodNode.RelatedScopeGroup = scope;

            // Get the kind of method the method is (Method (Overwatch), Custom Method, or User Method.)
            var methodType = GetMethodType(UserMethods, methodNode.Name);

            // Throw exception if the method does not exist.
            if (methodType == null)
            {
                throw SyntaxErrorException.NonexistentMethod(methodNode.Name, methodNode.Range);
            }

            Element method;

            switch (methodType)
            {
            case MethodType.Method:
            {
                Type owMethod = Element.GetMethod(methodNode.Name);

                method = (Element)Activator.CreateInstance(owMethod);
                Parameter[] parameterData = owMethod.GetCustomAttributes <Parameter>().ToArray();

                List <IWorkshopTree> parsedParameters = new List <IWorkshopTree>();
                for (int i = 0; i < parameterData.Length; i++)
                {
                    if (methodNode.Parameters.Length > i)
                    {
                        // Parse the parameter.
                        parsedParameters.Add(ParseParameter(scope, methodNode.Parameters[i], methodNode.Name, parameterData[i]));
                    }
                    else
                    {
                        if (parameterData[i].ParameterType == ParameterType.Value && parameterData[i].DefaultType == null)
                        {
                            // Throw exception if there is no default method to fallback on.
                            throw SyntaxErrorException.MissingParameter(parameterData[i].Name, methodNode.Name, methodNode.Range);
                        }
                        else
                        {
                            parsedParameters.Add(parameterData[i].GetDefault());
                        }
                    }
                }

                method.ParameterValues = parsedParameters.ToArray();
                break;
            }

            case MethodType.CustomMethod:
            {
                MethodInfo  customMethod     = CustomMethods.GetCustomMethod(methodNode.Name);
                Parameter[] parameterData    = customMethod.GetCustomAttributes <Parameter>().ToArray();
                object[]    parsedParameters = new Element[parameterData.Length];

                for (int i = 0; i < parameterData.Length; i++)
                {
                    if (methodNode.Parameters.Length > i)
                    {
                        parsedParameters[i] = ParseParameter(scope, methodNode.Parameters[i], methodNode.Name, parameterData[i]);
                    }
                    else
                    {
                        // Throw exception if there is no default method to fallback on.
                        throw SyntaxErrorException.MissingParameter(parameterData[i].Name, methodNode.Name, methodNode.Range);
                    }
                }

                MethodResult result = (MethodResult)customMethod.Invoke(null, new object[] { IsGlobal, VarCollection, parsedParameters });
                switch (result.MethodType)
                {
                case CustomMethodType.Action:
                    if (needsToBeValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, methodNode.Name, methodNode.Range);
                    }
                    break;

                case CustomMethodType.MultiAction_Value:
                case CustomMethodType.Value:
                    if (!needsToBeValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(false, methodNode.Name, methodNode.Range);
                    }
                    break;
                }

                // Some custom methods have extra actions.
                if (result.Elements != null)
                {
                    Actions.AddRange(result.Elements);
                }
                method = result.Result;

                break;
            }

            case MethodType.UserMethod:
            {
                if (!AllowRecursion)
                {
                    UserMethod userMethod = UserMethod.GetUserMethod(UserMethods, methodNode.Name);

                    if (MethodStackNoRecursive.Contains(userMethod))
                    {
                        throw SyntaxErrorException.RecursionNotAllowed(methodNode.Range);
                    }

                    var methodScope = Root.Child();

                    // Add the parameter variables to the scope.
                    DefinedVar[] parameterVars = new DefinedVar[userMethod.Parameters.Length];
                    for (int i = 0; i < parameterVars.Length; i++)
                    {
                        if (methodNode.Parameters.Length > i)
                        {
                            // Create a new variable using the parameter input.
                            parameterVars[i] = VarCollection.AssignDefinedVar(methodScope, IsGlobal, userMethod.Parameters[i].Name, methodNode.Range);
                            Actions.Add(parameterVars[i].SetVariable(ParseExpression(scope, methodNode.Parameters[i])));
                        }
                        else
                        {
                            throw SyntaxErrorException.MissingParameter(userMethod.Parameters[i].Name, methodNode.Name, methodNode.Range);
                        }
                    }

                    var returns = VarCollection.AssignVar($"{methodNode.Name}: return temp value", IsGlobal);

                    MethodStackNoRecursive.Add(userMethod);

                    var userMethodScope = methodScope.Child();
                    userMethod.Block.RelatedScopeGroup = userMethodScope;

                    ParseBlock(userMethodScope, userMethod.Block, true, returns);

                    MethodStackNoRecursive.Remove(userMethod);

                    // No return value if the method is being used as an action.
                    if (needsToBeValue)
                    {
                        method = returns.GetVariable();
                    }
                    else
                    {
                        method = null;
                    }

                    break;
                }
                else
                {
                    UserMethod userMethod = UserMethod.GetUserMethod(UserMethods, methodNode.Name);

                    MethodStack lastMethod = MethodStack.FirstOrDefault(ms => ms.UserMethod == userMethod);
                    if (lastMethod != null)
                    {
                        ContinueSkip.Setup();

                        for (int i = 0; i < lastMethod.ParameterVars.Length; i++)
                        {
                            if (methodNode.Parameters.Length > i)
                            {
                                Actions.Add(lastMethod.ParameterVars[i].Push(ParseExpression(scope, methodNode.Parameters[i])));
                            }
                        }

                        // ?--- Multidimensional Array
                        Actions.Add(
                            Element.Part <A_SetGlobalVariable>(EnumData.GetEnumValue(Variable.B), lastMethod.ContinueSkipArray.GetVariable())
                            );
                        Actions.Add(
                            Element.Part <A_ModifyGlobalVariable>(EnumData.GetEnumValue(Variable.B), EnumData.GetEnumValue(Operation.AppendToArray), new V_Number(ContinueSkip.GetSkipCount() + 4))
                            );
                        Actions.Add(
                            lastMethod.ContinueSkipArray.SetVariable(Element.Part <V_GlobalVariable>(EnumData.GetEnumValue(Variable.B)))
                            );
                        // ?---

                        ContinueSkip.SetSkipCount(lastMethod.ActionIndex);
                        Actions.Add(Element.Part <A_Loop>());

                        if (needsToBeValue)
                        {
                            method = lastMethod.Return.GetVariable();
                        }
                        else
                        {
                            method = null;
                        }
                    }
                    else
                    {
                        var methodScope = Root.Child();

                        // Add the parameter variables to the scope.
                        ParameterVar[] parameterVars = new ParameterVar[userMethod.Parameters.Length];
                        for (int i = 0; i < parameterVars.Length; i++)
                        {
                            if (methodNode.Parameters.Length > i)
                            {
                                // Create a new variable using the parameter input.
                                parameterVars[i] = VarCollection.AssignParameterVar(Actions, methodScope, IsGlobal, userMethod.Parameters[i].Name, methodNode.Range);
                                Actions.Add(parameterVars[i].Push(ParseExpression(scope, methodNode.Parameters[i])));
                            }
                            else
                            {
                                throw SyntaxErrorException.MissingParameter(userMethod.Parameters[i].Name, methodNode.Name, methodNode.Range);
                            }
                        }

                        var returns = VarCollection.AssignVar($"{methodNode.Name}: return temp value", IsGlobal);

                        Var continueSkipArray = VarCollection.AssignVar($"{methodNode.Name}: continue skip temp value", IsGlobal);
                        var stack             = new MethodStack(userMethod, parameterVars, ContinueSkip.GetSkipCount(), returns, continueSkipArray);
                        MethodStack.Add(stack);

                        var userMethodScope = methodScope.Child();
                        userMethod.Block.RelatedScopeGroup = userMethodScope;

                        ParseBlock(userMethodScope, userMethod.Block, true, returns);

                        // No return value if the method is being used as an action.
                        if (needsToBeValue)
                        {
                            method = returns.GetVariable();
                        }
                        else
                        {
                            method = null;
                        }

                        Actions.Add(Element.Part <A_Wait>(new V_Number(Constants.MINIMUM_WAIT)));
                        for (int i = 0; i < parameterVars.Length; i++)
                        {
                            parameterVars[i].Pop();
                        }

                        ContinueSkip.Setup();
                        ContinueSkip.SetSkipCount(Element.Part <V_LastOf>(continueSkipArray.GetVariable()));

                        // ?--- Multidimensional Array
                        Actions.Add(
                            Element.Part <A_SetGlobalVariable>(EnumData.GetEnumValue(Variable.B), continueSkipArray.GetVariable())
                            );
                        Actions.Add(
                            continueSkipArray.SetVariable(
                                Element.Part <V_ArraySlice>(
                                    Element.Part <V_GlobalVariable>(EnumData.GetEnumValue(Variable.B)),
                                    new V_Number(0),
                                    Element.Part <V_Subtract>(
                                        Element.Part <V_CountOf>(Element.Part <V_GlobalVariable>(EnumData.GetEnumValue(Variable.B))),
                                        new V_Number(1)
                                        )
                                    )
                                )
                            );
                        // ?---

                        Actions.Add(
                            Element.Part <A_LoopIf>(
                                Element.Part <V_Compare>(
                                    Element.Part <V_CountOf>(continueSkipArray.GetVariable()),
                                    EnumData.GetEnumValue(Operators.NotEqual),
                                    new V_Number(0)
                                    )
                                )
                            );
                        ContinueSkip.ResetSkip();

                        MethodStack.Remove(stack);
                    }
                    break;
                }
            }

            default: throw new NotImplementedException();
            }

            methodNode.RelatedElement = method;
            return(method);
        }

        IWorkshopTree ParseParameter(ScopeGroup scope, IExpressionNode node, string methodName, Parameter parameterData)
        {
            IWorkshopTree value = null;

            switch (node)
            {
            case EnumNode enumNode:

                /*
                 * if (parameterData.ParameterType != ParameterType.Enum)
                 *  throw SyntaxErrorException.ExpectedType(true, parameterData.ValueType.ToString(), methodName, parameterData.Name, enumNode.Range);
                 *
                 * if (enumNode.Type != parameterData.EnumType.Name)
                 *  throw SyntaxErrorException.ExpectedType(false, parameterData.EnumType.ToString(), methodName, parameterData.Name, enumNode.Range);
                 */

                value = (IWorkshopTree)EnumData.Special(enumNode.EnumMember) ?? (IWorkshopTree)enumNode.EnumMember;

                //if (value == null)
                //  throw SyntaxErrorException.InvalidEnumValue(enumNode.Type, enumNode.Value, enumNode.Range);

                break;

            default:

                if (parameterData.ParameterType != ParameterType.Value)
                {
                    throw SyntaxErrorException.ExpectedType(false, parameterData.EnumType.Name, methodName, parameterData.Name, ((Node)node).Range);
                }

                value = ParseExpression(scope, node);

                Element     element     = value as Element;
                ElementData elementData = element.GetType().GetCustomAttribute <ElementData>();

                if (elementData.ValueType != Elements.ValueType.Any &&
                    !parameterData.ValueType.HasFlag(elementData.ValueType))
                {
                    throw SyntaxErrorException.InvalidType(parameterData.ValueType, elementData.ValueType, ((Node)node).Range);
                }

                break;
            }

            if (value == null)
            {
                throw new Exception("Failed to parse parameter.");
            }

            return(value);
        }
Esempio n. 5
0
        public static TranslateResult GetRule(RuleNode ruleNode, ScopeGroup root, VarCollection varCollection, UserMethod[] userMethods)
        {
            var result = new Translate(ruleNode, root, varCollection, userMethods);

            return(new TranslateResult(result.Rule, result.Diagnostics.ToArray()));
        }
        public RulesetNode(DeltinScriptParser.RulesetContext context, BuildAstVisitor visitor) : base(new Location(visitor.file, Range.GetRange(context)))
        {
            Imports = new ImportNode[context.import_file().Length];
            for (int i = 0; i < Imports.Length; i++)
            {
                Imports[i] = new ImportNode(context.import_file(i), visitor);
            }

            ObjectImports = new ImportObjectNode[context.import_object().Length];
            for (int i = 0; i < ObjectImports.Length; i++)
            {
                ObjectImports[i] = new ImportObjectNode(context.import_object(i), visitor);
            }

            Rules = new RuleNode[context.ow_rule().Length];
            for (int i = 0; i < Rules.Length; i++)
            {
                Rules[i] = (RuleNode)visitor.VisitOw_rule(context.ow_rule()[i]);
            }

            if (context.useGlobalVar() != null)
            {
                if (Enum.TryParse(context.useGlobalVar().PART().GetText(), out Variable temp))
                {
                    UseGlobalVar = temp;
                }
            }

            if (context.usePlayerVar() != null)
            {
                if (Enum.TryParse(context.usePlayerVar().PART().GetText(), out Variable temp))
                {
                    UsePlayerVar = temp;
                }
            }

            if (context.useDimVar() != null)
            {
                if (Enum.TryParse(context.useDimVar().PART().GetText(), out Variable temp))
                {
                    UseBuilderVar = temp;
                }
            }

            DefinedVars = new RuleDefineNode[context.rule_define().Length];
            for (int i = 0; i < DefinedVars.Length; i++)
            {
                DefinedVars[i] = (RuleDefineNode)visitor.VisitRule_define(context.rule_define(i));
            }

            UserMethods = new UserMethodNode[context.user_method().Length];
            for (int i = 0; i < UserMethods.Length; i++)
            {
                UserMethods[i] = (UserMethodNode)visitor.VisitUser_method(context.user_method(i));
            }

            DefinedTypes = new TypeDefineNode[context.type_define().Length];
            for (int i = 0; i < DefinedTypes.Length; i++)
            {
                DefinedTypes[i] = (TypeDefineNode)visitor.VisitType_define(context.type_define(i));
            }
        }
        public RulesetNode(DeltinScriptParser.RulesetContext context, BuildAstVisitor visitor) : base(new Location(visitor.file, DocRange.GetRange(context)))
        {
            // Get imports
            Imports = new ImportNode[context.import_file().Length];
            for (int i = 0; i < Imports.Length; i++)
            {
                Imports[i] = new ImportNode(context.import_file(i), visitor);
            }

            ObjectImports = new ImportObjectNode[context.import_object().Length];
            for (int i = 0; i < ObjectImports.Length; i++)
            {
                ObjectImports[i] = new ImportObjectNode(context.import_object(i), visitor);
            }

            // Get rules
            Rules = new RuleNode[context.ow_rule().Length];
            for (int i = 0; i < Rules.Length; i++)
            {
                Rules[i] = (RuleNode)visitor.VisitOw_rule(context.ow_rule()[i]);
            }

            // Get defined variables
            DefinedVars = new RuleDefineNode[context.rule_define().Length];
            var reservedGlobalIDs = new List <int>();
            var reservedPlayerIDs = new List <int>();

            for (int i = 0; i < DefinedVars.Length; i++)
            {
                DefinedVars[i] = new RuleDefineNode(context.rule_define(i), visitor);
                if (DefinedVars[i].OverrideID != -1)
                {
                    (DefinedVars[i].IsGlobal ? reservedGlobalIDs : reservedPlayerIDs).Add(DefinedVars[i].OverrideID);
                }
            }
            ReservedGlobalIDs = reservedGlobalIDs.ToArray();
            ReservedPlayerIDs = reservedPlayerIDs.ToArray();

            // Get user methods
            UserMethods = new UserMethodBase[context.user_method().Length + context.macro().Length];
            for (int i = 0; i < context.user_method().Length; i++)
            {
                UserMethods[i] = (UserMethodNode)visitor.VisitUser_method(context.user_method(i));
            }

            // Get macros
            for (int i = 0; i < context.macro().Length; i++)
            {
                UserMethods[i + context.user_method().Length] = new MacroNode(context.macro(i), visitor);
            }

            // Get types
            DefinedTypes = new TypeDefineNode[context.type_define().Length];
            for (int i = 0; i < DefinedTypes.Length; i++)
            {
                DefinedTypes[i] = (TypeDefineNode)visitor.VisitType_define(context.type_define(i));
            }

            // Get reserved global variables
            if (context.reserved_global()?.reserved_list() != null)
            {
                ReservedGlobal = new ReservedNode(context.reserved_global().reserved_list(), visitor);
            }

            // Get reserved player variables
            if (context.reserved_player()?.reserved_list() != null)
            {
                ReservedPlayer = new ReservedNode(context.reserved_player().reserved_list(), visitor);
            }
        }
        public static Rule GetRule(RuleNode ruleNode, ScopeGroup root, ParsingData parserData)
        {
            var result = new TranslateRule(ruleNode, root, parserData);

            return(result.Rule);
        }