コード例 #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));
        }
コード例 #2
0
        public Element ParseExpression(ScopeGroup getter, ScopeGroup scope, Node expression)
        {
            switch (expression)
            {
            // Math and boolean operations.
            case OperationNode operationNode:
            {
                Element left  = ParseExpression(getter, scope, operationNode.Left);
                Element right = ParseExpression(getter, 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(left * right);

                case "%":
                    return(left % right);

                case "/":
                    return(left / right);

                case "+":
                    return(left + right);

                case "-":
                    return(left - right);


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

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

                // Compare: <, <=, ==, >=, >, !=
                case "<":
                    return(left < right);

                case "<=":
                    return(left <= right);

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

                case ">=":
                    return(left >= right);

                case ">":
                    return(left > 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(numberNode.Value);

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

            // Not operation
            case NotNode notNode:
                return(!(ParseExpression(getter, scope, notNode.Value)));

            case InvertNode invertNode:
                return(-ParseExpression(getter, scope, invertNode.Value));

            // Strings
            case StringNode stringNode:

                Element[] stringFormat = new Element[stringNode.Format?.Length ?? 0];
                for (int i = 0; i < stringFormat.Length; i++)
                {
                    stringFormat[i] = ParseExpression(getter, scope, stringNode.Format[i]);
                }
                if (stringNode.Localized)
                {
                    return(V_String.ParseString(stringNode.Location, stringNode.Value, stringFormat));
                }
                else
                {
                    return(V_CustomString.ParseString(stringNode.Location, 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(getter, scope, methodNode, true));

            // Variable
            case VariableNode variableNode:

                Element[] index = new Element[variableNode.Index.Length];
                for (int i = 0; i < index.Length; i++)
                {
                    index[i] = ParseExpression(getter, scope, variableNode.Index[i]);
                }

                Var var = scope.GetVar(getter, variableNode.Name, variableNode.Location);
                if (!var.Gettable())
                {
                    throw SyntaxErrorException.VariableIsReadonly(var.Name, variableNode.Location);
                }

                Element result = var.GetVariable();
                for (int i = 0; i < index.Length; i++)
                {
                    result = Element.Part <V_ValueInArray>(result, index[i]);
                }

                return(result);

            // Get value in array
            case ValueInArrayNode viaNode:
                return(Element.Part <V_ValueInArray>(ParseExpression(getter, scope, viaNode.Value), ParseExpression(getter, 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(getter, scope, createArrayNode.Values[i]);
                    prev = current;
                }

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

            // Ternary Conditional (a ? b : c)
            case TernaryConditionalNode ternaryNode:
                return(Element.TernaryConditional
                       (
                           ParseExpression(getter, scope, ternaryNode.Condition),
                           ParseExpression(getter, scope, ternaryNode.Consequent),
                           ParseExpression(getter, scope, ternaryNode.Alternative)
                       ));

            // Enums
            case EnumNode enumNode:
                return(EnumData.ToElement(enumNode.EnumMember)
                       ?? throw SyntaxErrorException.EnumCantBeValue(enumNode.Type, enumNode.Location));

            // New object
            case CreateObjectNode createObjectNode:
                DefinedType typeData = ParserData.GetDefinedType(createObjectNode.TypeName, createObjectNode.Location);
                return(typeData.New(createObjectNode, getter, scope, this));

            // Expression tree
            case ExpressionTreeNode expressionTree:
                return(new ParseExpressionTree(this, getter, scope, expressionTree).ResultingElement);

            // This
            case ThisNode thisNode:
                return(getter.GetThis(thisNode.Location));

            // Type convert
            case TypeConvertNode typeConvertNode:
                DefinedType type    = ParserData.GetDefinedType(typeConvertNode.Type, typeConvertNode.Location);
                Element     element = ParseExpression(getter, scope, typeConvertNode.Expression);
                type.GetSource(this, element, typeConvertNode.Location);
                return(element);

            case RootNode rootNode: throw new SyntaxErrorException("'root' cannot be used like an expression.", rootNode.Location);
            }

            throw new Exception();
        }
コード例 #3
0
            public ParseExpressionTree(TranslateRule translator, ScopeGroup getter, ScopeGroup scope, Node root)
            {
                if (root is VariableNode)
                {
                    VariableNode variableNode = (VariableNode)root;

                    Var var = scope.GetVar(getter, ((VariableNode)root).Name, root.Location);
                    ResultingVariable = var;

                    //if (!ResultingVariable.Gettable()) throw SyntaxErrorException.CantReadVariable(ResultingVariable.Name, root.Location);

                    if (ResultingVariable.Gettable())
                    {
                        ResultingElement = var.GetVariable();
                    }

                    VariableIndex = new Element[variableNode.Index.Length];
                    for (int i = 0; i < VariableIndex.Length; i++)
                    {
                        VariableIndex[i] = translator.ParseExpression(getter, scope, variableNode.Index[i]);
                    }

                    for (int i = 0; i < VariableIndex.Length; i++)
                    {
                        if (!ResultingVariable.Gettable())
                        {
                            throw SyntaxErrorException.CantReadVariable(ResultingVariable.Name, root.Location);
                        }
                        ResultingElement = Element.Part <V_ValueInArray>(ResultingElement, VariableIndex[i]);
                    }

                    return;
                }

                if (root is ExpressionTreeNode == false)
                {
                    throw new SyntaxErrorException("Error", root.Location);
                }

                List <Node> nodes        = flatten((ExpressionTreeNode)root);
                ScopeGroup  currentScope = scope;

                Element nodeResult = null;

                for (int index = 0; index < nodes.Count; index++)
                {
                    if (nodes[index] is RootNode)
                    {
                        currentScope = translator.ParserData.Root;
                        nodeResult   = new V_Null();
                    }
                    // If the node is a variable node, get the value.
                    else if (nodes[index] is VariableNode)
                    {
                        VariableNode variableNode = (VariableNode)nodes[index];
                        Var          var          = currentScope.GetVar(getter, variableNode.Name, variableNode.Location);

                        // If this is the last node, set the resulting var.
                        if (index == nodes.Count - 1)
                        {
                            ResultingVariable = var;
                        }

                        // Get the variable index
                        VariableIndex = new Element[variableNode.Index.Length];
                        for (int i = 0; i < VariableIndex.Length; i++)
                        {
                            VariableIndex[i] = translator.ParseExpression(getter, scope, variableNode.Index[i]);
                        }

                        // Set the nodeResult.
                        nodeResult = var.GetVariable(Target);

                        // Apply the index
                        for (int i = 0; i < VariableIndex.Length; i++)
                        {
                            nodeResult = Element.Part <V_ValueInArray>(nodeResult, VariableIndex[i]);
                        }
                    }
                    // If not, parse the node as an expression.
                    else
                    {
                        nodeResult = translator.ParseExpression(getter, currentScope, nodes[index]);
                    }

                    // SupportedType will equal null if the element is not a defined type.
                    if (nodeResult.SupportedType == null)
                    {
                        // If there is no supported type, assume the element or variable is containing a player.
                        // Reset the scope.
                        //currentScope = scope;
                        currentScope = translator.ParserData.Root;

                        // If this isn't the last node, set the target and reset the nodeResult.
                        if (index < nodes.Count - 1)
                        {
                            Target     = nodeResult;
                            nodeResult = null;
                        }
                    }
                    else
                    {
                        // Set the target scope to the type.
                        currentScope = nodeResult.SupportedType.Type.GetRootScope(nodeResult, nodeResult.SupportedType, translator.ParserData, Target);
                    }
                }
                ResultingElement = nodeResult;
            }