예제 #1
0
        private T BuildTree <T>(Queue <Token <TokenType> > tokens, ref InterpreterState state, bool getNodesOnly = false) where T : BlockNode, new()
        {
            T root = new T();             // Create a new node

            while (tokens.Count > 0)
            {
                TokenList expr = new TokenList();
                // If we hit EOS we are done
                Token <TokenType> token = tokens.Dequeue();
                if (token == null || token.IsEOS)
                {
#if DEBUG
                    WriteLineColor("EOS", Cyan);
#endif
                    break;
                }
                // While i is in bounds of tokens AND we have not hit an "expression ending" (; or {)
                while (tokens.Count() > 0 && !token.IsEnding() && !token.IsEOS)
                {
                    expr.Add(token);
                    token = tokens.Dequeue();
                }
                expr.Add(token);
                // If expression starts with }, remove it
                if (expr.Count > 0 && expr[0].TokenID == RBRACE)
                {
                    expr = expr.Skip(1).ToList();
                }
                // Dont run empty expression
                if (expr.Count == 0)
                {
                    continue;
                }
#if DEBUG
                expr.TokenDump();
#endif
                LexerPosition exprPos = expr[0].Position.Adjust();
                state.Location = exprPos;
                bool built = false;
                // Loop over every expression type
                foreach (ExpressionType type in Enum.GetValues(typeof(ExpressionType)).Cast <ExpressionType>())
                {
                    if (type.Matches(expr))
                    {
                        Node node = type.GetNode(expr, exprPos, ref state);
                        if (type.IsBlock())
                        {
                            BlockNode tmp = (BlockNode)node;
                            Queue <Token <TokenType> > block = GetBlock(ref tokens);
                            BuildTree <RootNode>(block, ref state, getNodesOnly).Children.ForEach(c => tmp.Add(c));
                            node = tmp;
                        }
                        if (type.WillRun() || getNodesOnly)
                        {
                            root.Add(node);
                        }
                        if (!getNodesOnly)
                        {
                            if (node is FunctionDefinitionNode funcDefNode)
                            {
                                state.UserFuncs.Add(new UserFunction(
                                                        funcDefNode.Name,
                                                        funcDefNode.Args,
                                                        funcDefNode.Children
                                                        ));
                            }
                            if (node is ImportNode impNode)
                            {
                                state.Import(impNode.Library);
                            }
                        }
                        built = true;
                        break;
                    }
                }
                if (!built)                 // Unknown Expression
                {
                    throw new InterpreterException($"Unknown expression at {exprPos}");
                }
            }

            return(root);
        }