Beispiel #1
0
        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);
        }