コード例 #1
0
        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);
            }
        }
コード例 #2
0
 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;
 }
コード例 #3
0
 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);
     }
 }
コード例 #4
0
 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;
 }
コード例 #5
0
        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();
        }
コード例 #6
0
 public AddNode(ArithmeticNode left, ArithmeticNode right)
     : base(left, right, "+")
 {
 }
コード例 #7
0
 protected OperatorNode(ArithmeticNode left, ArithmeticNode right, string symbol)
 {
     Left   = left;
     Right  = right;
     Symbol = symbol;
 }
コード例 #8
0
 public AssignmentNode(string name, ArithmeticNode body)
 {
     Name = name;
     Body = body;
 }
コード例 #9
0
            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;
                        }
                    }
                }
            }
コード例 #10
0
 public ArithmeticNode(ArithmeticNode parent)
 {
     this.parent          = parent;
     this.arithemeticType = ArithmeticType.Scope;
 }
コード例 #11
0
        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));
        }