/Pegasus.Workbench/Pipeline/PegParser.cs

https://gitlab.com/mirhagk/Pegasus · C# · 97 lines · 73 code · 17 blank · 7 comment · 2 complexity · 317c5fab98582b18c594847e73b6c4d9 MD5 · raw file

  1. // -----------------------------------------------------------------------
  2. // <copyright file="PegParser.cs" company="(none)">
  3. // Copyright © 2014 John Gietzen. All Rights Reserved.
  4. // This source is subject to the MIT license.
  5. // Please see license.md for more information.
  6. // </copyright>
  7. // -----------------------------------------------------------------------
  8. namespace Pegasus.Workbench.Pipeline
  9. {
  10. using System;
  11. using System.CodeDom.Compiler;
  12. using System.Collections.Generic;
  13. using System.Diagnostics.CodeAnalysis;
  14. using System.Reactive.Concurrency;
  15. using System.Reactive.Linq;
  16. using System.Text.RegularExpressions;
  17. using Pegasus.Common;
  18. using Pegasus.Expressions;
  19. internal sealed class PegParser : IDisposable
  20. {
  21. private readonly IDisposable disposable;
  22. public PegParser(IObservable<string> subjects, IObservable<string> fileNames)
  23. {
  24. var internalParseResults = subjects.CombineLatest(fileNames, (subject, filename) => new { subject, filename })
  25. .Throttle(TimeSpan.FromMilliseconds(10), Scheduler.Default)
  26. .Select(p => Parse(p.subject, p.filename))
  27. .Publish();
  28. this.Grammars = internalParseResults.Select(g => g.Grammar);
  29. this.Errors = internalParseResults.Select(g => g.Errors.AsReadOnly());
  30. this.LexicalElements = internalParseResults.Select(g => g.LexicalElements);
  31. this.disposable = internalParseResults.Connect();
  32. }
  33. public IObservable<IList<CompilerError>> Errors { get; private set; }
  34. public IObservable<Grammar> Grammars { get; private set; }
  35. [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "TODO: Use this for syntax highlighting.")]
  36. public IObservable<IList<LexicalElement>> LexicalElements { get; private set; }
  37. public void Dispose()
  38. {
  39. this.disposable.Dispose();
  40. }
  41. [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Any exception that happens during parsing should be reported through the UI.")]
  42. private static ParseResult Parse(string subject, string fileName)
  43. {
  44. subject = subject ?? "";
  45. try
  46. {
  47. IList<LexicalElement> lexicalElements;
  48. var grammar = new Pegasus.Parser.PegParser().Parse(subject, fileName, out lexicalElements);
  49. return new ParseResult
  50. {
  51. Grammar = grammar,
  52. LexicalElements = lexicalElements,
  53. Errors = new List<CompilerError>(),
  54. };
  55. }
  56. catch (Exception ex)
  57. {
  58. var cursor = ex.Data["cursor"] as Cursor ?? new Cursor(subject, 0, fileName);
  59. var parts = Regex.Split(ex.Message, @"(?<=^\w+):");
  60. if (parts.Length == 1)
  61. {
  62. parts = new[] { "", parts[0] };
  63. }
  64. return new ParseResult
  65. {
  66. Errors = new List<CompilerError>
  67. {
  68. new CompilerError(fileName, cursor.Line, cursor.Column, errorNumber: parts[0], errorText: parts[1]),
  69. },
  70. };
  71. }
  72. }
  73. private class ParseResult
  74. {
  75. public List<CompilerError> Errors { get; set; }
  76. public Grammar Grammar { get; set; }
  77. public IList<LexicalElement> LexicalElements { get; set; }
  78. }
  79. }
  80. }