public ScriptContext()
        {
            Pages = new SharpPages(this);
            PageFormats.Add(new HtmlPageFormat());
            Preprocessors.Add(ScriptPreprocessors.TransformCodeBlocks);
            ScriptMethods.Add(new DefaultScripts());
            ScriptMethods.Add(new HtmlScripts());
            Plugins.Add(new DefaultScriptBlocks());
            Plugins.Add(new HtmlScriptBlocks());
            FilterTransformers[ScriptConstants.HtmlEncode] = HtmlPageFormat.HtmlEncodeTransformer;
            FilterTransformers["end"]    = stream => (TypeConstants.EmptyByteArray.InMemoryStream() as Stream).InTask();
            FilterTransformers["buffer"] = stream => stream.InTask();

            Args[nameof(ScriptConfig.MaxQuota)]                = ScriptConfig.MaxQuota;
            Args[nameof(ScriptConfig.DefaultCulture)]          = ScriptConfig.CreateCulture();
            Args[nameof(ScriptConfig.DefaultDateFormat)]       = ScriptConfig.DefaultDateFormat;
            Args[nameof(ScriptConfig.DefaultDateTimeFormat)]   = ScriptConfig.DefaultDateTimeFormat;
            Args[nameof(ScriptConfig.DefaultTimeFormat)]       = ScriptConfig.DefaultTimeFormat;
            Args[nameof(ScriptConfig.DefaultFileCacheExpiry)]  = ScriptConfig.DefaultFileCacheExpiry;
            Args[nameof(ScriptConfig.DefaultUrlCacheExpiry)]   = ScriptConfig.DefaultUrlCacheExpiry;
            Args[nameof(ScriptConfig.DefaultIndent)]           = ScriptConfig.DefaultIndent;
            Args[nameof(ScriptConfig.DefaultNewLine)]          = ScriptConfig.DefaultNewLine;
            Args[nameof(ScriptConfig.DefaultJsConfig)]         = ScriptConfig.DefaultJsConfig;
            Args[nameof(ScriptConfig.DefaultStringComparison)] = ScriptConfig.DefaultStringComparison;
            Args[nameof(ScriptConfig.DefaultTableClassName)]   = ScriptConfig.DefaultTableClassName;
            Args[nameof(ScriptConfig.DefaultErrorClassName)]   = ScriptConfig.DefaultErrorClassName;
        }
        // TODO - Determine how to handle reprocessing Preprocessors
        // 1) Do I even want to store Preprocessors here? Maybe they should be left stored in the CommentTagger and DirectiveTagger
        // 2) Unlike Statements, we DO NOT need to consider ourselves as part of the next available Preprocessor
        // SO, we only need to remove Preprocessors that overlap with our range, and we should have these Preprocessors affect our return Span
        public Span ReprocessPreprocessors(int start, int end)
        {
            var nPreprocessorsToRemove = 0;

            for (var i = 0; i < Preprocessors.Count; i++)
            {
                // Skip any Preprocessors that end before our range starts
                if (start < Preprocessors[i].Span.End)
                {
                    if (start > Preprocessors[i].Span.Start)
                    {
                        // This Preprocessor started before our range, so extend our range start backwards
                        start = Preprocessors[i].Span.Start;
                    }
                    else if (end > Preprocessors[i].Span.End)
                    {
                        // This Preprocessor ends before our range does, so it must be marked for removal
                        nPreprocessorsToRemove++;
                    }

                    if (end > Preprocessors[i].Span.Start && end < Preprocessors[i].Span.End)
                    {
                        end = Preprocessors[i].Span.End;
                        nPreprocessorsToRemove++;
                        Preprocessors.RemoveRange(i - nPreprocessorsToRemove + 1, nPreprocessorsToRemove);

                        return(Span.FromBounds(start, end));
                    }
                }
            }

            Preprocessors.RemoveRange(Preprocessors.Count - 1 - nPreprocessorsToRemove, nPreprocessorsToRemove);

            return(Span.FromBounds(start, end));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SpiceParser"/> class.
        /// </summary>
        /// <param name="settings">SPICE parser settings.</param>
        public SpiceParser(SpiceParserSettings settings)
        {
            Settings            = settings ?? throw new ArgumentNullException(nameof(settings));
            SingleNetlistParser = new SingleSpiceNetlistParser(Settings.Parsing);

            TokenProviderPool = new SpiceTokenProviderPool();
            var includesPreprocessor = new IncludesPreprocessor(
                new FileReader(),
                TokenProviderPool,
                SingleNetlistParser,
                () => Settings.WorkingDirectory,
                Settings.Lexing);

            var libPreprocessor = new LibPreprocessor(
                new FileReader(),
                TokenProviderPool,
                SingleNetlistParser,
                includesPreprocessor,
                () => Settings.WorkingDirectory,
                Settings.Reading,
                Settings.Lexing);

            var appendModelPreprocessor = new AppendModelPreprocessor();
            var sweepsPreprocessor      = new SweepsPreprocessor();
            var ifPostprocessor         = new IfPreprocessor();

            Preprocessors.AddRange(new IProcessor[] { includesPreprocessor, libPreprocessor, appendModelPreprocessor, sweepsPreprocessor, ifPostprocessor });
        }
        public void Append(TagSpan <IGLSLTag> preprocessorTagSpan)
        {
            var lastPreprocessor = Preprocessors.LastOrDefault();

            if (lastPreprocessor == null || preprocessorTagSpan.Span.Start > lastPreprocessor.Span.End.Position)
            {
                Preprocessors.Add(preprocessorTagSpan);
            }
            else
            {
                for (var i = 0; i < Preprocessors.Count; i++)
                {
                    if (preprocessorTagSpan.Span.Start < Preprocessors[i].Span.Start)
                    {
                        Preprocessors.Insert(i, preprocessorTagSpan);
                        break;
                    }
                }
            }
        }