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