private IExpr _Parse(string scriptName, string s, ref List <ParseErrorInst> errors, bool verbose = false, bool createTempScope = true, bool hardTerminal = false) { errors.Clear(); // Save this for LogCompileErrors. _parseErrors = errors; Buffer buffer = new SimpleBuffer(s); Scanner scanner = new Scanner(buffer); Parser parser = new Parser(scanner); parser.context = defaultContext; parser.scriptName = scriptName; parser.Parse(); if (parser.errors.count > 0) { if (logCompileErrors) { for (int ii = 0; ii < parser.errors.errors.Count; ++ii) { LogError(parser.errors.errors[ii].ToString()); } } errors.AddRange(parser.errors.errors); _parseErrors = null; return(null); } IExpr expr = parser._headExpr; if (null == expr) { // This can happen if, for example, you try to parse ";". // Upon reflection I don't think this should be an error. Maybe someone is // compiling a commented out file. //LogCompileError(ParseErrorType.NullExpression, "Script parses to no expression."); //_parseErrors = null; return(null); } defaultContext.BeginCompile(); bool error = false; if (createTempScope) { if (!defaultContext.stack.PushTerminalScope("<Parse>", defaultContext, hardTerminal)) { LogCompileError(ParseErrorType.StackOverflow, "_Parse: stack overflow"); error = true; } } // This is the first pass through the tree. It is where class expressions can add themselves to the type library. // Because it happens earlier than TypeCheck, it allows for code higher in a file than the class declaration to // use the class. // Note that it is a VERY incomplete pass because the only Expr that calls this function on it's child Exprs is Expr_List. // This is because class declarations can ONLY by at the top level, or within Expr_Lists at the top level. // For example, there's no need for Expr_If to call RegisterType on it's true/false blocks because those (currently) // can never contain Expr_Class'es. if (!error) { expr.RegisterTypes(defaultContext, ref error); } // This is the second pass through the tree. It does virtually all the work. if (!error) { expr.TypeCheck(defaultContext, ref error); } if (verbose && !error) { Log(expr.MyToString("")); } // Restore state always. Parsing should never permanently affect the stack. defaultContext.FinishCompile(error); if (error) { _parseErrors = null; return(null); } _parseErrors = null; return(expr); }