private static void TestGlr(string title, int count, int trialCount, BenchFlags flags = BenchFlags.All)
        {
            const string path = "EEa.test";

            using (var testFile = new StreamWriter(path))
            {
                testFile.Write("a");

                while (count-- != 0)
                {
                    testFile.Write("+a");
                }
            }

            Benchmarks(path, title, typeof(GlrPerfLang), trialCount, flags: flags);
        }
        private static void TestGlr(string title, int count, int trialCount, BenchFlags flags = BenchFlags.All)
        {
            const string path = "EEa.test";
            using (var testFile = new StreamWriter(path))
            {
                testFile.Write("a");

                while (count-- != 0)
                {
                    testFile.Write("+a");
                }
            }

            Benchmarks(path, title, typeof(GlrPerfLang), trialCount, flags: flags);
        }
        private static void Benchmarks(
            string path,
            string title,
            Type   langDef,
            int    trialCount = 1,
            BenchFlags flags = BenchFlags.All)
        {
            var timer = new Stopwatch();

            timer.Start();
            var lang = Language.Get(langDef);
            using (var interp = new Interpreter(lang))
            {
                interp.Parse("a+a");
            }
            timer.Stop();

            Log("--------------- " + title + " ---------------");
            Log("heatup time  = {0}", timer.Elapsed);

            timer.Reset();
            using (var testFile = new StreamReader(path))
            {
                timer.Start();
                testFile.ReadToEnd();
                timer.Stop();
                Log("read time    = {0}", timer.Elapsed);
            }

            using (var interp = new Interpreter(lang))
            {
                for (int trial = 0; trial != trialCount; ++trial)
                {
                    timer.Reset();
                    using (var testFile = new StreamReader(path))
                    {
                        timer.Start();

                        int count = interp.Scan(testFile, path).Count();

                        timer.Stop();
                        Log("scan time    = {0} tokenCount = {1}", timer.Elapsed, count);
                    }
                }

                // Recognize
                if ((flags & BenchFlags.Recognize) == BenchFlags.Recognize)
                {
                    for (int trial = 0; trial != trialCount; ++trial)
                    {
                        timer.Reset();
                        using (var testFile = new StreamReader(path))
                        {
                            timer.Start();
                            bool success = interp.Recognize(testFile, path);
                            timer.Stop();
                            Assert.IsTrue(success);
                            Log("parse (recognize) = {0}", timer.Elapsed);
                        }
                    }
                }

                // Parse actions
                if ((flags & BenchFlags.ParseActions) == BenchFlags.ParseActions)
                {
                    for (int trial = 0; trial != trialCount; ++trial)
                    {
                        timer.Reset();
                        using (var testFile = new StreamReader(path))
                        {
                            timer.Start();
                            bool success = interp.Parse(testFile, path);
                            timer.Stop();
                            Assert.IsTrue(success);
                            Log("parse (actions) = {0}", timer.Elapsed);
                        }
                    }
                }

                // Parse tree
                if ((flags & BenchFlags.ParseTree) == BenchFlags.ParseTree)
                {
                    for (int trial = 0; trial != trialCount; ++trial)
                    {
                        timer.Reset();
                        using (var testFile = new StreamReader(path))
                        {
                            timer.Start();
                            interp.BuildTree(testFile, path);
                            timer.Stop();
                            Log("parse (tree) = {0}", timer.Elapsed);
                        }
                    }
                }
            }
        }
        private static void Benchmarks(
            string path,
            string title,
            Type langDef,
            int trialCount   = 1,
            BenchFlags flags = BenchFlags.All)
        {
            var timer = new Stopwatch();

            timer.Start();
            var lang = Language.Get(langDef);

            using (var interp = new Interpreter(lang))
            {
                interp.Parse("a+a");
            }
            timer.Stop();

            Log("--------------- " + title + " ---------------");
            Log("heatup time  = {0}", timer.Elapsed);

            timer.Reset();
            using (var testFile = new StreamReader(path))
            {
                timer.Start();
                testFile.ReadToEnd();
                timer.Stop();
                Log("read time    = {0}", timer.Elapsed);
            }

            using (var interp = new Interpreter(lang))
            {
                for (int trial = 0; trial != trialCount; ++trial)
                {
                    timer.Reset();
                    using (var testFile = new StreamReader(path))
                    {
                        timer.Start();

                        int count = interp.Scan(testFile, path).Count();

                        timer.Stop();
                        Log("scan time    = {0} tokenCount = {1}", timer.Elapsed, count);
                    }
                }

                // Recognize
                if ((flags & BenchFlags.Recognize) == BenchFlags.Recognize)
                {
                    for (int trial = 0; trial != trialCount; ++trial)
                    {
                        timer.Reset();
                        using (var testFile = new StreamReader(path))
                        {
                            timer.Start();
                            bool success = interp.Recognize(testFile, path);
                            timer.Stop();
                            Assert.IsTrue(success);
                            Log("parse (recognize) = {0}", timer.Elapsed);
                        }
                    }
                }

                // Parse actions
                if ((flags & BenchFlags.ParseActions) == BenchFlags.ParseActions)
                {
                    for (int trial = 0; trial != trialCount; ++trial)
                    {
                        timer.Reset();
                        using (var testFile = new StreamReader(path))
                        {
                            timer.Start();
                            bool success = interp.Parse(testFile, path);
                            timer.Stop();
                            Assert.IsTrue(success);
                            Log("parse (actions) = {0}", timer.Elapsed);
                        }
                    }
                }

                // Parse tree
                if ((flags & BenchFlags.ParseTree) == BenchFlags.ParseTree)
                {
                    for (int trial = 0; trial != trialCount; ++trial)
                    {
                        timer.Reset();
                        using (var testFile = new StreamReader(path))
                        {
                            timer.Start();
                            interp.BuildTree(testFile, path);
                            timer.Stop();
                            Log("parse (tree) = {0}", timer.Elapsed);
                        }
                    }
                }
            }
        }