private void HandleCompilerErrors(CompilerException ex, ScriptCompilerLogger logger) { logger.Error(ex); StringBuilder sb = new StringBuilder(); sb.AppendLine(ex.Message); sb.AppendLine(); sb.AppendLine($"Text: \"{ex.Text}\""); sb.AppendLine("Line: " + ex.Line); sb.AppendLine("Column: " + ex.Column); var _ = MetroMessageBox.Show("Compilation Failed", sb.ToString(), MetroMessageBox.MessageBoxButtons.Ok); if (txtScript.TextArea.Focus()) { txtScript.TextArea.Caret.Offset = txtScript.Document.GetOffset(ex.Line, ex.Column); txtScript.ScrollToLine(ex.Line); } }
private ScriptData CompileScripts(string code, IProgress <int> progress, ScriptCompilerLogger logger, ParsingExceptionCollector collector) { using (IReader reader = _streamManager.OpenRead()) { // Set up the lexer. logger.Information("Running the lexer..."); ICharStream stream = CharStreams.fromstring(code); HS_Gen1Lexer lexer = new HS_Gen1Lexer(stream); lexer.AddErrorListener(collector); ITokenStream tokens = new CommonTokenStream(lexer); // Set up the parser. logger.Information("Running the parser..."); HS_Gen1Parser parser = new HS_Gen1Parser(tokens); parser.AddErrorListener(collector); // Parse the scripts. parser.BuildParseTree = true; IParseTree tree = parser.hsc(); // Throw an exception if ANTLR reports parsing or lexing errors. if (collector.ContainsExceptions) { logger.Information("The collector contained errors. Cancelling the process..."); throw new OperationCanceledException($"Parsing Failed! {collector.ExceptionCount} Exceptions occured during the parsing process."); } // Load the context. var context = _scriptFile.LoadContext(reader, _cashefile); // Run the compiler. logger.Information("Running the compiler..."); bool outputDebugData = App.AssemblyStorage.AssemblySettings.OutputCompilerDebugData; ScriptCompiler compiler = new ScriptCompiler(_cashefile, _buildInfo, _opcodes, context, progress, logger, outputDebugData); ParseTreeWalker.Default.Walk(compiler, tree); return(compiler.Result()); } }
private void HandleParsingErrors(OperationCanceledException ex, ParsingExceptionCollector collector, ScriptCompilerLogger logger) { StringBuilder sb = new StringBuilder(); ParsingExceptionInformation[] errors = collector.GetExceptions().ToArray(); int counter = errors.Length <= 10 ? errors.Length : 10; for (int i = 0; i < counter; i++) { string errorMessage = $"{i + 1}: {errors[i].Message}, Line: {errors[i].Line}, Column: {errors[i].Column}"; sb.AppendLine(errorMessage); logger.Error("Parsing Error " + errorMessage); } var _ = MetroMessageBox.Show("Parsing Failed", sb.ToString(), MetroMessageBox.MessageBoxButtons.Ok); if (txtScript.TextArea.Focus()) { // Go to the first error. var firstError = errors[0]; if (firstError.Exception != null && firstError.Exception.OffendingToken != null) { txtScript.Select(firstError.Exception.OffendingToken.StartIndex, firstError.Exception.OffendingToken.StopIndex + 1 - firstError.Exception.OffendingToken.StartIndex); } else { txtScript.TextArea.Caret.Offset = txtScript.Document.GetOffset(firstError.Line, firstError.Column); } txtScript.ScrollToLine(firstError.Line); } }
private async void CompileClick(object sender, RoutedEventArgs e) { // Logger Setup string folder = "Compiler"; if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } string logPath = Path.Combine(folder, "ScriptCompiler.log"); using (var logStream = File.Create(logPath)) { // Create the logger and the exception collector. They are used for debugging. var traceListener = new TextWriterTraceListener(logStream); var logger = new ScriptCompilerLogger(traceListener); var exceptionCollector = new ParsingExceptionCollector(); logger.Information($"Attempting to compile: {_scriptFile.Name}, Time: {DateTime.Now}"); try { // Get the script file. string hsc = txtScript.Text; // Measure the time it took to compile the scripts. var stopWatch = Stopwatch.StartNew(); // Compile the scripts. ScriptData compileData = await Task.Run(() => CompileScripts(hsc, _progress, logger, exceptionCollector)); stopWatch.Stop(); var timeSpan = stopWatch.Elapsed; string compilationMessage = $"The scripts were successfully compiled in {Math.Round(timeSpan.TotalSeconds, 3)} seconds."; logger.Information(compilationMessage); // Show the message box. var saveResult = MetroMessageBox.Show("Scripts Compiled", compilationMessage + "\nWARNING: This compiler is not 100% accurate and could corrupt the map in rare cases. Making a backup before proceeding is advisable." + "\n\nDo you want to save the changes to the file?", MetroMessageBox.MessageBoxButtons.YesNo); if (saveResult == MetroMessageBox.MessageBoxResult.Yes) { //TODO: Move this to its own function. await Task.Run(() => { using (IStream stream = _streamManager.OpenReadWrite()) { _scriptFile.SaveScripts(compileData, stream, _progress); _cashefile.SaveChanges(stream); } }); RefreshMeta(); StatusUpdater.Update("Scripts saved"); } } // Handle Parsing Errors. catch (OperationCanceledException opEx) { if (exceptionCollector.ContainsExceptions) { HandleParsingErrors(opEx, exceptionCollector, logger); } else { MetroMessageBox.Show("Operation Canceled", opEx.Message); } } // Handle Compiler Errors. catch (CompilerException compEx) { HandleCompilerErrors(compEx, logger); } finally { logger.Flush(); ResetProgressBar(); } } }