Add diagnostics
This commit is contained in:
parent
d928c262fa
commit
cdbb0ffb72
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Parser;
|
||||
using ProjectConsole;
|
||||
using Semantics;
|
||||
@ -40,9 +41,9 @@ namespace ConsoleDemo
|
||||
}
|
||||
}
|
||||
|
||||
public static void Render(SyntaxNode node)
|
||||
public static void RenderTree(SyntaxTree tree)
|
||||
{
|
||||
RenderNode(node, "", true);
|
||||
RenderNode(tree.Root, "", true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,15 +80,24 @@ namespace ConsoleDemo
|
||||
function [a, b c] = functionName(d, e, f)
|
||||
a = d + e;
|
||||
end
|
||||
%{
|
||||
comment
|
||||
";
|
||||
var window = new TextWindowWithNull(text, "noname");
|
||||
var parser = CreateParser(window);
|
||||
var tree = parser.Parse();
|
||||
TreeRenderer.Render(tree);
|
||||
TreeRenderer.RenderTree(tree);
|
||||
if (tree.Diagnostics.Any())
|
||||
{
|
||||
foreach (var diagnostic in tree.Diagnostics)
|
||||
{
|
||||
Console.WriteLine($"ERROR: {diagnostic.Message} at position {diagnostic.Span.Start}");
|
||||
}
|
||||
}
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
private static FileSyntaxNode GetTree(string fileName)
|
||||
private static SyntaxTree GetTree(string fileName)
|
||||
{
|
||||
var text = File.ReadAllText(fileName);
|
||||
var window = new TextWindowWithNull(text, fileName);
|
||||
@ -104,10 +114,11 @@ namespace ConsoleDemo
|
||||
"@table",
|
||||
"table.m");
|
||||
var tree = GetTree(fileName);
|
||||
var childNodesAndTokens = tree.GetChildNodesAndTokens();
|
||||
var root = tree.Root;
|
||||
var childNodesAndTokens = root.GetChildNodesAndTokens();
|
||||
var node = childNodesAndTokens[0].AsNode();
|
||||
var classChildNodesAndTokens = node.GetChildNodesAndTokens();
|
||||
var c = GetClass.FromTree(tree, fileName);
|
||||
var c = GetClass.FromTree(root, fileName);
|
||||
Console.WriteLine(c.Name);
|
||||
foreach (var m in c.Methods)
|
||||
{
|
||||
@ -135,7 +146,7 @@ namespace ConsoleDemo
|
||||
"heatmap.m");
|
||||
var tree = GetTree(fileName);
|
||||
var printer = new DumbWalker(context);
|
||||
printer.Visit(tree);
|
||||
printer.Visit(tree.Root);
|
||||
}
|
||||
|
||||
public static void UsageDemo()
|
||||
@ -148,16 +159,16 @@ namespace ConsoleDemo
|
||||
"heatmap.m");
|
||||
var tree = GetTree(fileName);
|
||||
var printer = new UsageGathering(context);
|
||||
printer.Visit(tree);
|
||||
printer.Visit(tree.Root);
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
//ParserDemo();
|
||||
ParserDemo();
|
||||
//SemanticsDemo();
|
||||
//ContextDemo();
|
||||
//DumbPrinterDemo();
|
||||
UsageDemo();
|
||||
//UsageDemo();
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
16
Parser/Internal/Diagnostic.cs
Normal file
16
Parser/Internal/Diagnostic.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Parser.Internal
|
||||
{
|
||||
public class Diagnostic
|
||||
{
|
||||
public TextSpan Span { get; }
|
||||
public string Message { get; }
|
||||
|
||||
public Diagnostic(TextSpan span, string message)
|
||||
{
|
||||
Span = span;
|
||||
Message = message ?? throw new ArgumentNullException(nameof(message));
|
||||
}
|
||||
}
|
||||
}
|
38
Parser/Internal/DiagnosticsBag.cs
Normal file
38
Parser/Internal/DiagnosticsBag.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Parser.Internal
|
||||
{
|
||||
public class DiagnosticsBag : IEnumerable<Diagnostic>
|
||||
{
|
||||
internal DiagnosticsBag()
|
||||
{
|
||||
_diagnostics = new List<Diagnostic>();
|
||||
}
|
||||
|
||||
private readonly List<Diagnostic> _diagnostics;
|
||||
|
||||
public IReadOnlyCollection<Diagnostic> Diagnostics => _diagnostics.AsReadOnly();
|
||||
|
||||
private void Report(TextSpan span, string message)
|
||||
{
|
||||
var diagnostic = new Diagnostic(span, message);
|
||||
_diagnostics.Add(diagnostic);
|
||||
}
|
||||
|
||||
internal void ReportUnexpectedEndOfFile(TextSpan span)
|
||||
{
|
||||
Report(span, "Unexpected end of file.");
|
||||
}
|
||||
|
||||
public IEnumerator<Diagnostic> GetEnumerator()
|
||||
{
|
||||
return _diagnostics.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@ namespace Parser.Internal
|
||||
private int TokensSinceNewLine { get; set; }
|
||||
private Stack<TokenKind> TokenStack { get; }
|
||||
|
||||
public DiagnosticsBag Diagnostics { get; } = new DiagnosticsBag();
|
||||
|
||||
public MLexerGreen(ITextWindow window)
|
||||
{
|
||||
Window = window;
|
||||
@ -50,10 +52,11 @@ namespace Parser.Internal
|
||||
var c = Window.PeekChar(n);
|
||||
if (c == '\0')
|
||||
{
|
||||
throw new ParsingException("Unexpected end of file while parsing multi-line comment.");
|
||||
Diagnostics.ReportUnexpectedEndOfFile(new TextSpan(Window.Position.Offset, 0));
|
||||
return TokenFactory.CreateTrivia(TokenKind.Comment, Window.GetAndConsumeChars(n));
|
||||
}
|
||||
|
||||
if (c == '\n')
|
||||
if (c == '\n' || (c == '\r' && Window.PeekChar(n + 1) == '\n'))
|
||||
{
|
||||
atFirstLine = false;
|
||||
}
|
||||
|
15
Parser/Internal/TextSpan.cs
Normal file
15
Parser/Internal/TextSpan.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Parser.Internal
|
||||
{
|
||||
public class TextSpan
|
||||
{
|
||||
public TextSpan(int start, int length)
|
||||
{
|
||||
Start = start;
|
||||
Length = length;
|
||||
}
|
||||
|
||||
public int Start { get; }
|
||||
public int Length { get; }
|
||||
public int End => Start + Length;
|
||||
}
|
||||
}
|
@ -1,21 +1,39 @@
|
||||
namespace Parser
|
||||
using System;
|
||||
using Parser.Internal;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
public class MParser
|
||||
{
|
||||
private readonly ITextWindow _window;
|
||||
|
||||
|
||||
public MParser(ITextWindow window)
|
||||
{
|
||||
_window = window;
|
||||
}
|
||||
|
||||
public FileSyntaxNode Parse()
|
||||
public SyntaxTree Parse()
|
||||
{
|
||||
var lexer = new Internal.MLexerGreen(_window);
|
||||
var diagnostics = lexer.Diagnostics;
|
||||
var tokens = lexer.ParseAll();
|
||||
var parser = new Internal.MParserGreen(tokens, new Internal.SyntaxFactory());
|
||||
var green = parser.ParseFile();
|
||||
return new FileSyntaxNode(null, green);
|
||||
var root = new FileSyntaxNode(null, green);
|
||||
return new SyntaxTree(root, diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
public class SyntaxTree
|
||||
{
|
||||
public SyntaxTree(FileSyntaxNode root, DiagnosticsBag diagnostics)
|
||||
{
|
||||
Root = root ?? throw new ArgumentNullException(nameof(root));
|
||||
Diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics));
|
||||
}
|
||||
|
||||
public FileSyntaxNode Root { get; }
|
||||
public DiagnosticsBag Diagnostics { get; }
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
public string FileName { get; set; }
|
||||
public int Line { get; set; }
|
||||
public int Column { get; set; }
|
||||
public int Offset { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
@ -3,42 +3,39 @@
|
||||
public class TextWindow : ITextWindow
|
||||
{
|
||||
protected readonly string Text;
|
||||
protected int Offset { get; set; }
|
||||
private Position _position;
|
||||
public Position Position => _position;
|
||||
|
||||
public TextWindow(string text, string fileName = null)
|
||||
{
|
||||
Text = text;
|
||||
Offset = 0;
|
||||
_position = new Position
|
||||
{
|
||||
FileName = fileName,
|
||||
Line = 0,
|
||||
Column = 0
|
||||
Column = 0,
|
||||
Offset = 0
|
||||
};
|
||||
}
|
||||
|
||||
public bool IsEof()
|
||||
{
|
||||
return Offset >= Text.Length;
|
||||
return _position.Offset >= Text.Length;
|
||||
}
|
||||
|
||||
public virtual char PeekChar()
|
||||
{
|
||||
return Text[Offset];
|
||||
return Text[_position.Offset];
|
||||
}
|
||||
|
||||
|
||||
public virtual char PeekChar(int n)
|
||||
{
|
||||
return Text[Offset + n];
|
||||
return Text[_position.Offset + n];
|
||||
}
|
||||
|
||||
|
||||
public void ConsumeChar()
|
||||
{
|
||||
if (Text[Offset] == '\n' || Text[Offset] == '\r')
|
||||
if (Text[_position.Offset] == '\n' || Text[_position.Offset] == '\r')
|
||||
{
|
||||
_position.Line++;
|
||||
_position.Column = 0;
|
||||
@ -47,7 +44,7 @@
|
||||
{
|
||||
_position.Column++;
|
||||
}
|
||||
Offset++;
|
||||
_position.Offset++;
|
||||
}
|
||||
|
||||
public void ConsumeChars(int n)
|
||||
@ -64,26 +61,26 @@
|
||||
_position.Column++;
|
||||
}
|
||||
}
|
||||
Offset += n;
|
||||
_position.Offset += n;
|
||||
}
|
||||
|
||||
public char GetAndConsumeChar()
|
||||
{
|
||||
var c = Text[Offset];
|
||||
var c = Text[_position.Offset];
|
||||
ConsumeChar();
|
||||
return c;
|
||||
}
|
||||
|
||||
public string GetAndConsumeChars(int n)
|
||||
{
|
||||
var s = Text.Substring(Offset, n);
|
||||
var s = Text.Substring(_position.Offset, n);
|
||||
ConsumeChars(n);
|
||||
return s;
|
||||
}
|
||||
|
||||
public int CharactersLeft()
|
||||
{
|
||||
return Text.Length - Offset;
|
||||
return Text.Length - _position.Offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
public override char PeekChar(int n)
|
||||
{
|
||||
return Offset + n >= Text.Length ? '\0' : base.PeekChar(n);
|
||||
return Position.Offset + n >= Text.Length ? '\0' : base.PeekChar(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user