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)); }
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(); }
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; }