コード例 #1
0
        public void Execute()
        {
            AbstractMachineState state = new AbstractMachineState(new AMFactory());
            ArrayList            prog  = new ArrayList();

            prog.Add(new PutConstantInstruction());
            prog.Add(new HaltInstruction());


            state.Initialize(prog);

            AMProgram program = (AMProgram)state.Program;

            ProgramClause clause = new ProgramClause("male", 2);

            program.AddLabel("male/2", clause);

            ExecuteInstruction i = new ExecuteInstruction();

            object[] args = { "male", "2" };

            i.Process(args);

            i.Execute(state);

            Assert.AreEqual("execute", i.Name());
            Assert.AreEqual(2, i.NumberOfArguments());
            Assert.AreSame(clause, program.P);
        }
コード例 #2
0
        /// <summary>
        /// Loads the file name specified, with a relative path from the
        /// <see cref="NameSpace.Directory"/> property. Use a forward slash
        /// to represent files in sub folders.
        /// </summary>
        /// <param name="fileName">
        /// The fileName to load in this <see cref="NameSpace.Directory"/>, or sub
        /// folder path and filename from this NameSpace directory.
        /// </param>
        /// <param name="overwrite">
        /// If the file is already loaded in this NameSpace, do we overwrite the existing
        /// loaded file and its objects? If false, and Exception will be thrown if this file
        /// is already loaded.
        /// </param>
        /// <returns>Returns true if the file exists and loaded successfully, false otherwise</returns>
        public async Task <bool> LoadFile(
            string fileName,
            bool overwrite = false,
            Scope scope    = null,
            ExecuteInstruction instruction = ExecuteInstruction.Skip)
        {
            // Make sure this isnt loaded already...
            if (!overwrite && Files.ContainsKey(fileName))
            {
                throw new Exception($"{fileName} has already been loaded into this namespace!");
            }

            // Get full file path
            string corrected = fileName.Replace('/', Path.DirectorySeparatorChar);
            string filePath  = Path.Combine(Directory, corrected);

            // Skip not found files
            if (!File.Exists(filePath))
            {
                return(false);
            }

            // Create variables
            Scope   fileScope = scope ?? CreateScope();
            ConFile cFile;

            // Try-Catch this beast
            try
            {
                // Create sub scope for this file, and load it
                cFile = await ScriptEngine.LoadFileAsync(filePath, fileScope, instruction);

                // For dev purposes, will be removed later
                Interlocked.Increment(ref TotalFilesLoaded);
                Interlocked.Add(ref TotalObjectsLoaded, cFile.Scope.GetObjects().Count());

                // Add item
                Files[fileName] = cFile;
                return(true);
            }
            catch
            {
                // Pass the exception up
                throw;
            }
        }
コード例 #3
0
ファイル: Namespace.cs プロジェクト: wilson212/BF2Editor
        /// <summary>
        /// Loads the file name specified, with a relative path from the 
        /// <see cref="NameSpace.Directory"/> property. Use a forward slash 
        /// to represent files in sub folders.
        /// </summary> 
        /// <param name="fileName">
        /// The fileName to load in this <see cref="NameSpace.Directory"/>, or sub
        /// folder path and filename from this NameSpace directory.
        /// </param>
        /// <param name="overwrite">
        /// If the file is already loaded in this NameSpace, do we overwrite the existing
        /// loaded file and its objects? If false, and Exception will be thrown if this file 
        /// is already loaded.
        /// </param>
        /// <returns>Returns true if the file exists and loaded successfully, false otherwise</returns>
        public async Task<bool> LoadFile(
            string fileName, 
            bool overwrite = false, 
            Scope scope = null,
            ExecuteInstruction instruction = ExecuteInstruction.Skip)
        {
            // Make sure this isnt loaded already...
            if (!overwrite && Files.ContainsKey(fileName))
                throw new Exception($"{fileName} has already been loaded into this namespace!");

            // Get full file path
            string corrected = fileName.Replace('/', Path.DirectorySeparatorChar);
            string filePath = Path.Combine(Directory, corrected);

            // Skip not found files
            if (!File.Exists(filePath))
                return false;

            // Create variables
            Scope fileScope = scope ?? CreateScope();
            ConFile cFile;

            // Try-Catch this beast
            try
            {
                // Create sub scope for this file, and load it
                cFile = await ScriptEngine.LoadFileAsync(filePath, fileScope, instruction);

                // For dev purposes, will be removed later
                Interlocked.Increment(ref TotalFilesLoaded);
                Interlocked.Add(ref TotalObjectsLoaded, cFile.Scope.GetObjects().Count());

                // Add item
                Files[fileName] = cFile;
                return true;
            }
            catch
            {
                // Pass the exception up
                throw;
            }
        }
コード例 #4
0
 public AMInstructionSet()
 {
     _instructions["allocate"]          = new AllocateInstruction();
     _instructions["bcall"]             = new BCallInstruction();
     _instructions["call"]              = new CallInstruction();
     _instructions["cut"]               = new CutInstruction();
     _instructions["deallocate"]        = new DeallocateInstruction();
     _instructions["execute"]           = new ExecuteInstruction();
     _instructions["fcall"]             = new FCallInstruction();
     _instructions["fail"]              = new FailInstruction();
     _instructions["get_constant"]      = new GetConstantInstruction();
     _instructions["get_list"]          = new GetListInstruction();
     _instructions["get_structure"]     = new GetStructureInstruction();
     _instructions["get_value"]         = new GetValueInstruction();
     _instructions["get_variable"]      = new GetVariableInstruction();
     _instructions["halt"]              = new HaltInstruction();
     _instructions["nop"]               = new NopInstruction();
     _instructions["proceed"]           = new ProceedInstruction();
     _instructions["put_constant"]      = new PutConstantInstruction();
     _instructions["put_list"]          = new PutListInstruction();
     _instructions["put_structure"]     = new PutStructureInstruction();
     _instructions["put_unsafe_value"]  = new PutUnsafeValueInstruction();
     _instructions["put_variable"]      = new PutVariableInstruction();
     _instructions["put_value"]         = new PutValueInstruction();
     _instructions["retry_me_else"]     = new RetryMeElseInstruction();
     _instructions["set_constant"]      = new SetConstantInstruction();
     _instructions["set_local_value"]   = new SetLocalValueInstruction();
     _instructions["set_value"]         = new SetValueInstruction();
     _instructions["set_variable"]      = new SetVariableInstruction();
     _instructions["set_void"]          = new SetVoidInstruction();
     _instructions["trust_me"]          = new TrustMeInstruction();
     _instructions["try_me_else"]       = new TryMeElseInstruction();
     _instructions["unify_constant"]    = new UnifyConstantInstruction();
     _instructions["unify_local_value"] = new UnifyLocalValueInstruction();
     _instructions["unify_variable"]    = new UnifyVariableInstruction();
     _instructions["unify_value"]       = new UnifyValueInstruction();
     _instructions["unify_void"]        = new UnifyVoidInstruction();
     _instructions["procedure"]         = new ProcedureInstruction();
 }
コード例 #5
0
        /// <summary>
        /// Loads a .con or .ai file, and converts the script objects into C# objects
        /// </summary>
        /// <param name="filePath">The path to the .con / .ai file</param>
        /// <param name="scope">
        /// Sets the scope in which the objects from this <see cref="ConFile"/>
        /// will be loaded into.
        /// </param>
        /// <param name="runInstruction">
        /// Defines how the script engine should handle nested file includes
        /// </param>
        /// <exception cref="Exception">
        /// Thrown if there is a problem loading the script file in any way.
        /// </exception>
        /// <returns>Returns the parsed bf2 script file.</returns>
        public static async Task <ConFile> LoadFileAsync(string filePath, Scope scope      = null,
                                                         ExecuteInstruction runInstruction = ExecuteInstruction.Skip)
        {
            // Create new ConFile contents
            ConFile cFile = new ConFile(filePath, scope);
            Dictionary <int, string> fileContents = new Dictionary <int, string>();
            int lineNum = 1;

            // Create Log
            Logger.Info("Loading file: " + filePath);

            // Open the confile, and read its contents
            using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                using (StreamReader reader = new StreamReader(fStream))
                {
                    // While we can keep reading
                    while (!reader.EndOfStream)
                    {
                        string line = await reader.ReadLineAsync();

                        fileContents.Add(lineNum++, line);
                    }
                }

            // Parse the contents of the Con / Ai file
            try
            {
                await ParseFileLines(fileContents, cFile, runInstruction);
            }
            catch
            {
                // Pass the exception up
                throw;
            }

            // Return the file
            return(cFile);
        }
コード例 #6
0
ファイル: ScriptEngine.cs プロジェクト: wilson212/BF2Editor
        /// <summary>
        /// Loads a .con or .ai file, and converts the script objects into C# objects
        /// </summary>
        /// <param name="filePath">The path to the .con / .ai file</param>
        /// <param name="scope">
        /// Sets the scope in which the objects from this <see cref="ConFile"/> 
        /// will be loaded into.
        /// </param>
        /// <param name="runInstruction">
        /// Defines how the script engine should handle nested file includes
        /// </param>
        /// <exception cref="Exception">
        /// Thrown if there is a problem loading the script file in any way.
        /// </exception>
        /// <returns>Returns the parsed bf2 script file.</returns>
        public static async Task<ConFile> LoadFileAsync(string filePath, Scope scope = null, 
            ExecuteInstruction runInstruction = ExecuteInstruction.Skip)
        {
            // Create new ConFile contents
            ConFile cFile = new ConFile(filePath, scope);
            Dictionary<int, string> fileContents = new Dictionary<int, string>();
            int lineNum = 1;

            // Create Log
            Logger.Info("Loading file: " + filePath);

            // Open the confile, and read its contents
            using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            using (StreamReader reader = new StreamReader(fStream))
            {
                // While we can keep reading
                while (!reader.EndOfStream)
                {
                    string line = await reader.ReadLineAsync();
                    fileContents.Add(lineNum++, line);
                }
            }

            // Parse the contents of the Con / Ai file
            try
            {
                await ParseFileLines(fileContents, cFile, runInstruction);
            }
            catch
            {
                // Pass the exception up
                throw;
            }

            // Return the file
            return cFile;
        }
コード例 #7
0
        // Reset CPU control section and instruction decoder internal state
        private void ResetCPUControlState()
        {
            // Z80CPU.cs internal state
            tStateCounter = 0;
            machineCycleCounter = 0;
            instructionCounter = 0;
            instructionOrigin = null;
            currentInstruction = null;
            executeInstruction = null;
            halfTStateIndex = 0;
            machineCycleIndex = 0;
            machineCycleCountAfterInstruction = 0;
            currentMachineCycle = null;
            executeMachineCycle = null;

            // Z80CPU_Instruction_Decoder.cs internal state
            opcodeTableIndex = 0;

            // Z80CPU_ExternalControl.cs internal state
            busRequestPending = false;
            maskableInterruptPending = false;
            nonMaskableInterruptPending = false;
        }
コード例 #8
0
 private void EndInstruction()
 {
     instructionOrigin = null;
     currentInstruction = null;
     executeInstruction = null;
 }
コード例 #9
0
 private void EndInstruction()
 {
     instructionOrigin  = null;
     currentInstruction = null;
     executeInstruction = null;
 }
コード例 #10
0
ファイル: ScriptEngine.cs プロジェクト: wilson212/BF2Editor
        /// <summary>
        /// Parses the contents of a .con or .ai file, and converts the contents into C# objects
        /// </summary>
        /// <param name="fileContents">A dictionary of file contents [LineNumber => LineContents]</param>
        /// <param name="workingFile">A reference to the ConFile that contains the contents</param>
        internal static async Task ParseFileLines(
            Dictionary<int, string> fileContents, 
            ConFile workingFile, 
            ExecuteInstruction run)
        {
            // ============
            // First we convert our confile lines into parsed tokens
            // ============
            Token[] fileTokens = Tokenizer.Tokenize(workingFile, ref fileContents);
            TokenArgs tokenArgs;
            Scope currentScope = workingFile.Scope;

            // ============
            // Now we create an object reference of all objects in the Confile
            // before parsing the object properties, which **can** reference an object
            // in the same file before its defined
            // NOTE: Do not create object references for .Active and .safeActive
            // ============
            foreach (Token token in fileTokens.Where(x => x.Kind == TokenType.ObjectStart).OrderBy(x => x.Position))
            {
                // Create the object
                var Method = token.TokenArgs.ReferenceType.GetMethod(token.TokenArgs.PropertyName);
                ConFileObject template = Method.Invoke(token);

                // Finally, register the object with the ObjectManager
                currentScope.AddObject(template, token);
                Logger.Info($"Created {token.TokenArgs.ReferenceType} \"{template.Name}\"", workingFile, token.Position);
            }

            // ============
            // Finally, we load all of the object properties, and assign them to their 
            // respective objects
            // ============

            // Create our needed objects
            RemComment comment = null;
            ConFileObject currentObj = null;
            ReferenceType type;
            var builder = new StringBuilder();

            // We use a for loop here so we can skip rem blocks and statements
            for (int i = 0; i < fileTokens.Length; i++)
            {
                // Grab token value
                Token token = fileTokens[i];
                try
                {
                    switch (token.Kind)
                    {
                        case TokenType.ObjectStart:
                        case TokenType.ActiveSwitch:
                            // NOTE: the object was created before this loop!
                            currentObj = currentScope.GetObject(token);
                            currentScope.SetActiveObject(currentObj);

                            // === Objects are already added to the working file before hand === //
                            // Add object reference to file
                            workingFile.AddEntry(currentObj, token);

                            // Reset comment
                            comment = null;

                            // Log
                            Logger.Info($"Loading object properties for \"{currentObj.Name}\"",
                                workingFile, token.Position
                            );
                            break;
                        case TokenType.ObjectProperty:
                            // Convert args to an object
                            tokenArgs = token.TokenArgs;

                            // Get the last used object
                            type = tokenArgs.ReferenceType;
                            currentObj = currentScope.GetActiveObject(type);

                            // Make sure we have an object to work with and the object
                            // reference matches our current working object
                            if (currentObj == null)
                            {
                                // If we are here, we have an issue...
                                string error = $"Failed to set property \"{token.TokenArgs.ReferenceType.Name}.\""
                                    + $"{token.TokenArgs.PropertyName}. No object reference set!";
                                throw new ParseException(error, token);
                            }

                            // Let the object parse its own lines...
                            try
                            {
                                currentObj.Parse(token);

                                // Ensure comment is null
                                comment = null;
                            }
                            catch (Exception e)
                            {
                                Logger.Error(e.Message, workingFile, token.Position, e);
                                throw;
                            }
                            break;
                        case TokenType.RemComment:
                            // Create a new comment if we need to
                            if (comment == null)
                            {
                                comment = new RemComment(token);
                            }

                            // Add comment to the current string
                            comment.AppendLine(token.Value);
                            break;
                        case TokenType.BeginRem:
                            RemComment rem = new RemComment(token);
                            rem.IsRemBlock = true;

                            // Skip every line until we get to the endRem
                            builder.AppendLine(token.Value);
                            i = ScopeUntil(TokenType.EndRem, fileTokens, i, builder);

                            // Set rem value
                            rem.Value = builder.ToString().TrimEnd();
                            workingFile.AddEntry(rem, rem.Token);

                            // Clear the string builder
                            builder.Clear();
                            break;
                        case TokenType.IfStart:
                            Statement statement = new Statement(token);
                            if (token.Kind == TokenType.IfStart)
                            {
                                // Skip every line until we get to the endIf
                                builder.AppendLine(token.Value);
                                i = ScopeUntil(TokenType.EndIf, fileTokens, i, builder);

                                // Clear the string builder
                                statement.Token.Value = builder.ToString().TrimEnd();
                                builder.Clear();
                            }

                            // Add entry
                            workingFile.AddEntry(statement, statement.Token);
                            break;
                        case TokenType.Run:
                        case TokenType.Include:
                            // Just add to as a string
                            RunStatement stmt = new RunStatement(token);
                            workingFile.AddEntry(stmt, stmt.Token);

                            // Do we execute the statement?
                            if (run == ExecuteInstruction.Skip)
                                continue;

                            // Create new scope for execution
                            Scope runScope = currentScope;

                            // Are we executing in a new scope?
                            if (run == ExecuteInstruction.ExecuteInNewScope)
                            {
                                // For now, we just inherit the parent scope type
                                runScope = new Scope(currentScope, currentScope.ScopeType);
                                runScope.MissingObjectHandling = MissingObjectHandling.CheckParent;
                            }

                            // Get the filepath
                            string filePath = Path.GetDirectoryName(workingFile.FilePath);
                            string fileName = Path.Combine(filePath, stmt.FileName);

                            // Define file arguments
                            runScope.SetArguments(stmt.Arguments);

                            // Load the file
                            try
                            {
                                ConFile include = await LoadFileAsync(fileName, runScope, run);
                                workingFile.ExecutedIncludes.Add(include);
                            }
                            catch (FileNotFoundException) // Only acceptable exception
                            {
                                fileName = Path.GetFileName(fileName);
                                Logger.Warning($"Failed to run file \"{fileName}\". File Not Found", 
                                    workingFile, token.Position);
                            }
                            break;
                        case TokenType.Constant:
                        case TokenType.Variable:
                            // Set the new expression reference in Scope
                            Expression exp = new Expression(token);
                            currentScope.Expressions[exp.Name] = exp;

                            // Add expression to the confile as well
                            workingFile.AddEntry(exp, exp.Token);
                            break;
                        case TokenType.None:
                            // Dont attach comment to a property if we have an empty line here
                            if (comment != null)
                            {
                                workingFile.AddEntry(comment, comment.Token);
                                comment = null;
                            }

                            // Throw error if the line is not empty
                            if (!String.IsNullOrWhiteSpace(token.Value))
                            {
                                string message = $"Unable to parse file entry \"{token.Value}\" on line {token.Position}";
                                throw new ParseException(message, token);
                            }
                            break;
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e.Message, token.File, token.Position, e);
                    throw;
                }
            }

            // Finalize this confile
            workingFile.Finish();
        }
コード例 #11
0
        /// <summary>
        /// Parses the contents of a .con or .ai file, and converts the contents into C# objects
        /// </summary>
        /// <param name="fileContents">A dictionary of file contents [LineNumber => LineContents]</param>
        /// <param name="workingFile">A reference to the ConFile that contains the contents</param>
        internal static async Task ParseFileLines(
            Dictionary <int, string> fileContents,
            ConFile workingFile,
            ExecuteInstruction run)
        {
            // ============
            // First we convert our confile lines into parsed tokens
            // ============
            Token[]   fileTokens = Tokenizer.Tokenize(workingFile, ref fileContents);
            TokenArgs tokenArgs;
            Scope     currentScope = workingFile.Scope;

            // ============
            // Now we create an object reference of all objects in the Confile
            // before parsing the object properties, which **can** reference an object
            // in the same file before its defined
            // NOTE: Do not create object references for .Active and .safeActive
            // ============
            foreach (Token token in fileTokens.Where(x => x.Kind == TokenType.ObjectStart).OrderBy(x => x.Position))
            {
                // Create the object
                var           Method   = token.TokenArgs.ReferenceType.GetMethod(token.TokenArgs.PropertyName);
                ConFileObject template = Method.Invoke(token);

                // Finally, register the object with the ObjectManager
                currentScope.AddObject(template, token);
                Logger.Info($"Created {token.TokenArgs.ReferenceType} \"{template.Name}\"", workingFile, token.Position);
            }

            // ============
            // Finally, we load all of the object properties, and assign them to their
            // respective objects
            // ============

            // Create our needed objects
            RemComment    comment    = null;
            ConFileObject currentObj = null;
            ReferenceType type;
            var           builder = new StringBuilder();

            // We use a for loop here so we can skip rem blocks and statements
            for (int i = 0; i < fileTokens.Length; i++)
            {
                // Grab token value
                Token token = fileTokens[i];
                try
                {
                    switch (token.Kind)
                    {
                    case TokenType.ObjectStart:
                    case TokenType.ActiveSwitch:
                        // NOTE: the object was created before this loop!
                        currentObj = currentScope.GetObject(token);
                        currentScope.SetActiveObject(currentObj);

                        // === Objects are already added to the working file before hand === //
                        // Add object reference to file
                        workingFile.AddEntry(currentObj, token);

                        // Reset comment
                        comment = null;

                        // Log
                        Logger.Info($"Loading object properties for \"{currentObj.Name}\"",
                                    workingFile, token.Position
                                    );
                        break;

                    case TokenType.ObjectProperty:
                        // Convert args to an object
                        tokenArgs = token.TokenArgs;

                        // Get the last used object
                        type       = tokenArgs.ReferenceType;
                        currentObj = currentScope.GetActiveObject(type);

                        // Make sure we have an object to work with and the object
                        // reference matches our current working object
                        if (currentObj == null)
                        {
                            // If we are here, we have an issue...
                            string error = $"Failed to set property \"{token.TokenArgs.ReferenceType.Name}.\""
                                           + $"{token.TokenArgs.PropertyName}. No object reference set!";
                            throw new ParseException(error, token);
                        }

                        // Let the object parse its own lines...
                        try
                        {
                            currentObj.Parse(token);

                            // Ensure comment is null
                            comment = null;
                        }
                        catch (Exception e)
                        {
                            Logger.Error(e.Message, workingFile, token.Position, e);
                            throw;
                        }
                        break;

                    case TokenType.RemComment:
                        // Create a new comment if we need to
                        if (comment == null)
                        {
                            comment = new RemComment(token);
                        }

                        // Add comment to the current string
                        comment.AppendLine(token.Value);
                        break;

                    case TokenType.BeginRem:
                        RemComment rem = new RemComment(token);
                        rem.IsRemBlock = true;

                        // Skip every line until we get to the endRem
                        builder.AppendLine(token.Value);
                        i = ScopeUntil(TokenType.EndRem, fileTokens, i, builder);

                        // Set rem value
                        rem.Value = builder.ToString().TrimEnd();
                        workingFile.AddEntry(rem, rem.Token);

                        // Clear the string builder
                        builder.Clear();
                        break;

                    case TokenType.IfStart:
                        Statement statement = new Statement(token);
                        if (token.Kind == TokenType.IfStart)
                        {
                            // Skip every line until we get to the endIf
                            builder.AppendLine(token.Value);
                            i = ScopeUntil(TokenType.EndIf, fileTokens, i, builder);

                            // Clear the string builder
                            statement.Token.Value = builder.ToString().TrimEnd();
                            builder.Clear();
                        }

                        // Add entry
                        workingFile.AddEntry(statement, statement.Token);
                        break;

                    case TokenType.Run:
                    case TokenType.Include:
                        // Just add to as a string
                        RunStatement stmt = new RunStatement(token);
                        workingFile.AddEntry(stmt, stmt.Token);

                        // Do we execute the statement?
                        if (run == ExecuteInstruction.Skip)
                        {
                            continue;
                        }

                        // Create new scope for execution
                        Scope runScope = currentScope;

                        // Are we executing in a new scope?
                        if (run == ExecuteInstruction.ExecuteInNewScope)
                        {
                            // For now, we just inherit the parent scope type
                            runScope = new Scope(currentScope, currentScope.ScopeType);
                            runScope.MissingObjectHandling = MissingObjectHandling.CheckParent;
                        }

                        // Get the filepath
                        string filePath = Path.GetDirectoryName(workingFile.FilePath);
                        string fileName = Path.Combine(filePath, stmt.FileName);

                        // Define file arguments
                        runScope.SetArguments(stmt.Arguments);

                        // Load the file
                        try
                        {
                            ConFile include = await LoadFileAsync(fileName, runScope, run);

                            workingFile.ExecutedIncludes.Add(include);
                        }
                        catch (FileNotFoundException)     // Only acceptable exception
                        {
                            fileName = Path.GetFileName(fileName);
                            Logger.Warning($"Failed to run file \"{fileName}\". File Not Found",
                                           workingFile, token.Position);
                        }
                        break;

                    case TokenType.Constant:
                    case TokenType.Variable:
                        // Set the new expression reference in Scope
                        Expression exp = new Expression(token);
                        currentScope.Expressions[exp.Name] = exp;

                        // Add expression to the confile as well
                        workingFile.AddEntry(exp, exp.Token);
                        break;

                    case TokenType.None:
                        // Dont attach comment to a property if we have an empty line here
                        if (comment != null)
                        {
                            workingFile.AddEntry(comment, comment.Token);
                            comment = null;
                        }

                        // Throw error if the line is not empty
                        if (!String.IsNullOrWhiteSpace(token.Value))
                        {
                            string message = $"Unable to parse file entry \"{token.Value}\" on line {token.Position}";
                            throw new ParseException(message, token);
                        }
                        break;
                    }
                }
                catch (Exception e)
                {
                    Logger.Error(e.Message, token.File, token.Position, e);
                    throw;
                }
            }

            // Finalize this confile
            workingFile.Finish();
        }