public ArithmeticNode ParseString(string var) { try { string[] pieces = SplitAndKeepDelims(var, new char[] { '+', '-', '*', '/', '(', ')' }); ArithmeticNode curRoot = new ArithmeticNode(parent: null); for (int i = 0; i < pieces.Length; i++) { if (pieces[i].Trim() != "") { ArithmeticNode curNode = new ArithmeticNode(pieces[i]); if (curNode.arithemeticType == ArithmeticNode.ArithmeticType.Paren) { // go one stack down (opening paren) if (curNode.paren.opening) { ArithmeticNode newRoot = new ArithmeticNode(curRoot); curRoot.AddChild(newRoot); curRoot = newRoot; } else { // go one stack up (closing paren) if (curRoot.parent != null) { curRoot = curRoot.parent; } else { throw new ArithmeticException("Unmatched closing paren"); } } } else { curRoot.AddChild(curNode); } } } // we should get back up to root with no parent if we have balanced parens if (curRoot.parent != null) { throw new ArithmeticException("Unmatched opening paren"); } curRoot.MergeOperators(); //Debug.Log("parsed " + var + " and got " + curRoot + " which evaluates with state=0 to " + curRoot.GetValue(0) + " and state=1 to " + curRoot.GetValue(1) + " and state=-1 to" + curRoot.GetValue(-1)); return(curRoot); } catch (ArithmeticException arithException) { throw new ArithmeticException("Exception in processing string " + var + " of " + arithException); } }
public ArithmeticNode(ArithmeticNode opHolder, ArithmeticOp unaryOp, ArithmeticNode applyTo) { this.op = unaryOp.op; this.ops.Add(unaryOp); this.children.Add(applyTo); applyTo.parent = this; applyTo.merged = true; opHolder.parent = this; opHolder.merged = true; this.arithemeticType = ArithmeticType.MergedUnaryOperator; }
public void AddChild(ArithmeticNode child) { if (this.arithemeticType == ArithmeticType.Operator) { throw new ArithmeticException("Cannot add child to type " + this.arithemeticType); } else { this.children.Add(child); } }
public ArithmeticNode(ArithmeticNode opHolder, ArithmeticOp binaryOp, ArithmeticNode applyToA, ArithmeticNode applyToB) { this.op = binaryOp.op; this.ops.Add(binaryOp); this.children.Add(applyToA); applyToA.parent = this; applyToA.merged = true; applyToB.parent = this; applyToB.merged = true; opHolder.parent = this; opHolder.merged = true; this.children.Add(applyToB); this.arithemeticType = ArithmeticType.MergedBinaryOperator; }
public override void OnClick(Node source, Vector2 mousePosition) { ArithmeticNode node = source as ArithmeticNode; NodeEditorUtility.AddNewNode(graph.editorData, null, null, mousePositionOnCanvas, (MultiArithmeticNode n) => { n.targets[0] = node.targetA; n.targets[1] = node.targetB; n.operatorType = node.operatorType; n.editorRect = node.editorRect; RefactorUtility.RetargetValueNode(node, n); }); NodeEditorUtility.RemoveNode(graph.editorData, node); graph.Refresh(); }
public AddNode(ArithmeticNode left, ArithmeticNode right) : base(left, right, "+") { }
protected OperatorNode(ArithmeticNode left, ArithmeticNode right, string symbol) { Left = left; Right = right; Symbol = symbol; }
public AssignmentNode(string name, ArithmeticNode body) { Name = name; Body = body; }
public void MergeOperators() { // merge operators of children recursively for (int i = 0; i < children.Count; i++) { if (children[i].arithemeticType == ArithmeticType.Scope) { children[i].MergeOperators(); } } // now actually do the work. First, check if unary (precedence == 2), then merge * and / (precedence == 1), then merge + and - (precedence == 0) for (int curPrecedence = 2; curPrecedence >= 0; curPrecedence--) { bool mergedSomething = true; while (mergedSomething) { mergedSomething = false; //Debug.Log("cur loop"); bool prevWasNonOp = false; List <ArithmeticNode> newChildren = new List <ArithmeticNode>(); for (int i = 0; i < children.Count; i++) { ArithmeticNode cur = children[i]; //Debug.Log(cur + " " + cur.arithemeticType); if (cur.arithemeticType == ArithmeticType.Operator) { prevWasNonOp = false; if (!mergedSomething) { bool foundSomethingThatFits = false; foreach (ArithmeticOp possibleOp in cur.ops) { if (possibleOp.precedence == curPrecedence) { // unary if we are first or prev is also an operator if ((i == 0 || children[i - 1].arithemeticType == ArithmeticType.Operator) && possibleOp.opType == ArithmeticOp.ArithmeticOpType.Unary) { if (i + 1 < children.Count && children[i + 1].arithemeticType != ArithmeticType.Operator) { ArithmeticNode newChild = new ArithmeticNode(cur, possibleOp, children[i + 1]); i += 1; // skip past next one that we just used newChildren.Add(newChild); mergedSomething = true; foundSomethingThatFits = true; break; } else { throw new ArithmeticException("- sign does not have term it can apply to, current scope is " + this); } } // otherwise we are a binary operator else if (possibleOp.opType == ArithmeticOp.ArithmeticOpType.Binary) { if (i == 0 || i == children.Count - 1 || children[i + 1].IsBinaryOperator() || children[i - 1].IsBinaryOperator()) { throw new ArithmeticException("operator " + possibleOp.op + " does not have a term on both sides it can apply to, current scope is " + this); } else { ArithmeticNode beforeChild = children[i - 1]; ArithmeticNode afterChild = children[i + 1]; // go up if previous has already been used (say, for (-3 + 2) or (3 + 4 + 5) (we are the rightmost plus in both of these examples)) while (beforeChild.merged) { beforeChild = beforeChild.parent; } while (afterChild.merged) { afterChild = afterChild.parent; } ArithmeticNode newChild = new ArithmeticNode(cur, possibleOp, beforeChild, afterChild); i += 1; // skip past next one that we just used newChildren.Add(newChild); mergedSomething = true; foundSomethingThatFits = true; break; } } } } if (!foundSomethingThatFits) { // in case we have the processing happen after us if (i != 0 && !children[i - 1].merged) { newChildren.Add(children[i - 1]); } newChildren.Add(cur); } } else { newChildren.Add(cur); } } else { if (prevWasNonOp) { throw new ArithmeticException("multiple non-operators next to each other, this is invalid with us " + this.ToString()); } prevWasNonOp = true; if (mergedSomething) { newChildren.Add(cur); } } } if (mergedSomething) { this.children = newChildren; } } } }
public ArithmeticNode(ArithmeticNode parent) { this.parent = parent; this.arithemeticType = ArithmeticType.Scope; }
public static BlockNode ProcessTokens(List <ScriptToken> tokens) { List <AstTreeNode> blockNodes = new List <AstTreeNode>(); AstTreeNode node = new BlockNode(null); int count = 0; StripWhiteSpace(tokens); while (tokens.Count > 0) { count++; if (count > 1000) { break; // Limit to 1000 iterations while in development } if (tokens[0].Type == EScriptTokenType.RETURN) { tokens.RemoveAt(0); // Last value in block is returned by default } ScriptToken scriptToken = tokens[0]; if (scriptToken.Type == EScriptTokenType.NAME) { node = new RootScopeMemberNode( new LiteralNode <string>(scriptToken.Value) ); tokens.RemoveAt(0); } else if (scriptToken.Type == EScriptTokenType.ASSIGN) { node = AssignmentNode.Parse(node, scriptToken, tokens); } else if (scriptToken.Type == EScriptTokenType.IF) { node = IfStatementNode.Parse(node, scriptToken, tokens); blockNodes.Add(node); node = null; } else if (scriptToken.Type == EScriptTokenType.FOR) { node = ForStatementNode.Parse(node, scriptToken, tokens); blockNodes.Add(node); node = null; } else if (scriptToken.Type == EScriptTokenType.STRING_LITERAL) { node = new LiteralNode <string>(scriptToken.Value); tokens.RemoveAt(0); } else if (scriptToken.Type == EScriptTokenType.NUMBER_LITERAL) { AstTreeNode _node; if (scriptToken.Value.Contains(".")) { _node = new FloatLiteralNode(scriptToken.Value); } else { _node = new IntegerLiteralNode(scriptToken.Value); } node = _node; tokens.RemoveAt(0); } else if (scriptToken.Type == EScriptTokenType.PERIOD) { if (tokens[1].Type == EScriptTokenType.NAME) { node = new ScopeMemberNode( node, new LiteralNode <string>(tokens[1].Value) ); tokens.RemoveAt(0); tokens.RemoveAt(0); } } else if (scriptToken.Type == EScriptTokenType.L_BRACKET) { if (node.GetType() == typeof(RootScopeMemberNode)) { // indice } else { node = ArrayNode.Parse(node, scriptToken, tokens); } } else if (scriptToken.Type == EScriptTokenType.L_PAREN) { List <List <ScriptToken> > funcArgs = GetBlockTokens(tokens); List <AstTreeNode> nodes = new List <AstTreeNode>(); ; foreach (List <ScriptToken> arg in funcArgs) { nodes.Add(ProcessTokens(arg)); } node = new FunctionCallNode( node, // Previous node should be a NAME new FunctionArgumentNode(nodes) ); } else if (scriptToken.Type == EScriptTokenType.SEMI_COLON) { if (node != null) { blockNodes.Add(node); } node = null; tokens.RemoveAt(0); } else if (ComparisonNode.Matches(tokens)) { node = ComparisonNode.Parse(node, scriptToken, tokens); } else if (ArithmeticNode.Matches(tokens)) { AstTreeNode _node = ArithmeticNode.Parse(node, scriptToken, tokens); node = _node; } else if (ArithmeticAssignmentNode.Matches(tokens)) { node = ArithmeticAssignmentNode.Parse(node, scriptToken, tokens); } else if (scriptToken.Type == EScriptTokenType.WHITESPACE) { tokens.RemoveAt(0); } else if (scriptToken.Type == EScriptTokenType.BOOLEAN_LITERAL) { node = new BooleanLiteralNode(tokens[0].Value); tokens.RemoveAt(0); } else if (scriptToken.Type == EScriptTokenType.NULL_LITERAL) { node = new LiteralNode <object>(null); tokens.RemoveAt(0); } else { string code = ScriptTree.ToCode(tokens, 10); Console.WriteLine($"Syntax Error.Near {code}"); } } if (node != null) { blockNodes.Add(node); } return(new BlockNode(blockNodes)); }