Add diagnostics
This commit is contained in:
parent
d928c262fa
commit
cdbb0ffb72
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using Parser;
|
using Parser;
|
||||||
using ProjectConsole;
|
using ProjectConsole;
|
||||||
using Semantics;
|
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)
|
function [a, b c] = functionName(d, e, f)
|
||||||
a = d + e;
|
a = d + e;
|
||||||
end
|
end
|
||||||
|
%{
|
||||||
|
comment
|
||||||
";
|
";
|
||||||
var window = new TextWindowWithNull(text, "noname");
|
var window = new TextWindowWithNull(text, "noname");
|
||||||
var parser = CreateParser(window);
|
var parser = CreateParser(window);
|
||||||
var tree = parser.Parse();
|
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();
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FileSyntaxNode GetTree(string fileName)
|
private static SyntaxTree GetTree(string fileName)
|
||||||
{
|
{
|
||||||
var text = File.ReadAllText(fileName);
|
var text = File.ReadAllText(fileName);
|
||||||
var window = new TextWindowWithNull(text, fileName);
|
var window = new TextWindowWithNull(text, fileName);
|
||||||
@ -104,10 +114,11 @@ namespace ConsoleDemo
|
|||||||
"@table",
|
"@table",
|
||||||
"table.m");
|
"table.m");
|
||||||
var tree = GetTree(fileName);
|
var tree = GetTree(fileName);
|
||||||
var childNodesAndTokens = tree.GetChildNodesAndTokens();
|
var root = tree.Root;
|
||||||
|
var childNodesAndTokens = root.GetChildNodesAndTokens();
|
||||||
var node = childNodesAndTokens[0].AsNode();
|
var node = childNodesAndTokens[0].AsNode();
|
||||||
var classChildNodesAndTokens = node.GetChildNodesAndTokens();
|
var classChildNodesAndTokens = node.GetChildNodesAndTokens();
|
||||||
var c = GetClass.FromTree(tree, fileName);
|
var c = GetClass.FromTree(root, fileName);
|
||||||
Console.WriteLine(c.Name);
|
Console.WriteLine(c.Name);
|
||||||
foreach (var m in c.Methods)
|
foreach (var m in c.Methods)
|
||||||
{
|
{
|
||||||
@ -135,7 +146,7 @@ namespace ConsoleDemo
|
|||||||
"heatmap.m");
|
"heatmap.m");
|
||||||
var tree = GetTree(fileName);
|
var tree = GetTree(fileName);
|
||||||
var printer = new DumbWalker(context);
|
var printer = new DumbWalker(context);
|
||||||
printer.Visit(tree);
|
printer.Visit(tree.Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UsageDemo()
|
public static void UsageDemo()
|
||||||
@ -148,16 +159,16 @@ namespace ConsoleDemo
|
|||||||
"heatmap.m");
|
"heatmap.m");
|
||||||
var tree = GetTree(fileName);
|
var tree = GetTree(fileName);
|
||||||
var printer = new UsageGathering(context);
|
var printer = new UsageGathering(context);
|
||||||
printer.Visit(tree);
|
printer.Visit(tree.Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
//ParserDemo();
|
ParserDemo();
|
||||||
//SemanticsDemo();
|
//SemanticsDemo();
|
||||||
//ContextDemo();
|
//ContextDemo();
|
||||||
//DumbPrinterDemo();
|
//DumbPrinterDemo();
|
||||||
UsageDemo();
|
//UsageDemo();
|
||||||
Console.ReadKey();
|
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 int TokensSinceNewLine { get; set; }
|
||||||
private Stack<TokenKind> TokenStack { get; }
|
private Stack<TokenKind> TokenStack { get; }
|
||||||
|
|
||||||
|
public DiagnosticsBag Diagnostics { get; } = new DiagnosticsBag();
|
||||||
|
|
||||||
public MLexerGreen(ITextWindow window)
|
public MLexerGreen(ITextWindow window)
|
||||||
{
|
{
|
||||||
Window = window;
|
Window = window;
|
||||||
@ -50,10 +52,11 @@ namespace Parser.Internal
|
|||||||
var c = Window.PeekChar(n);
|
var c = Window.PeekChar(n);
|
||||||
if (c == '\0')
|
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;
|
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
|
public class MParser
|
||||||
{
|
{
|
||||||
private readonly ITextWindow _window;
|
private readonly ITextWindow _window;
|
||||||
|
|
||||||
public MParser(ITextWindow window)
|
public MParser(ITextWindow window)
|
||||||
{
|
{
|
||||||
_window = window;
|
_window = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileSyntaxNode Parse()
|
public SyntaxTree Parse()
|
||||||
{
|
{
|
||||||
var lexer = new Internal.MLexerGreen(_window);
|
var lexer = new Internal.MLexerGreen(_window);
|
||||||
|
var diagnostics = lexer.Diagnostics;
|
||||||
var tokens = lexer.ParseAll();
|
var tokens = lexer.ParseAll();
|
||||||
var parser = new Internal.MParserGreen(tokens, new Internal.SyntaxFactory());
|
var parser = new Internal.MParserGreen(tokens, new Internal.SyntaxFactory());
|
||||||
var green = parser.ParseFile();
|
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 string FileName { get; set; }
|
||||||
public int Line { get; set; }
|
public int Line { get; set; }
|
||||||
public int Column { get; set; }
|
public int Column { get; set; }
|
||||||
|
public int Offset { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
@ -3,42 +3,39 @@
|
|||||||
public class TextWindow : ITextWindow
|
public class TextWindow : ITextWindow
|
||||||
{
|
{
|
||||||
protected readonly string Text;
|
protected readonly string Text;
|
||||||
protected int Offset { get; set; }
|
|
||||||
private Position _position;
|
private Position _position;
|
||||||
public Position Position => _position;
|
public Position Position => _position;
|
||||||
|
|
||||||
public TextWindow(string text, string fileName = null)
|
public TextWindow(string text, string fileName = null)
|
||||||
{
|
{
|
||||||
Text = text;
|
Text = text;
|
||||||
Offset = 0;
|
|
||||||
_position = new Position
|
_position = new Position
|
||||||
{
|
{
|
||||||
FileName = fileName,
|
FileName = fileName,
|
||||||
Line = 0,
|
Line = 0,
|
||||||
Column = 0
|
Column = 0,
|
||||||
|
Offset = 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEof()
|
public bool IsEof()
|
||||||
{
|
{
|
||||||
return Offset >= Text.Length;
|
return _position.Offset >= Text.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual char PeekChar()
|
public virtual char PeekChar()
|
||||||
{
|
{
|
||||||
return Text[Offset];
|
return Text[_position.Offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual char PeekChar(int n)
|
public virtual char PeekChar(int n)
|
||||||
{
|
{
|
||||||
return Text[Offset + n];
|
return Text[_position.Offset + n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void ConsumeChar()
|
public void ConsumeChar()
|
||||||
{
|
{
|
||||||
if (Text[Offset] == '\n' || Text[Offset] == '\r')
|
if (Text[_position.Offset] == '\n' || Text[_position.Offset] == '\r')
|
||||||
{
|
{
|
||||||
_position.Line++;
|
_position.Line++;
|
||||||
_position.Column = 0;
|
_position.Column = 0;
|
||||||
@ -47,7 +44,7 @@
|
|||||||
{
|
{
|
||||||
_position.Column++;
|
_position.Column++;
|
||||||
}
|
}
|
||||||
Offset++;
|
_position.Offset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConsumeChars(int n)
|
public void ConsumeChars(int n)
|
||||||
@ -64,26 +61,26 @@
|
|||||||
_position.Column++;
|
_position.Column++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Offset += n;
|
_position.Offset += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public char GetAndConsumeChar()
|
public char GetAndConsumeChar()
|
||||||
{
|
{
|
||||||
var c = Text[Offset];
|
var c = Text[_position.Offset];
|
||||||
ConsumeChar();
|
ConsumeChar();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetAndConsumeChars(int n)
|
public string GetAndConsumeChars(int n)
|
||||||
{
|
{
|
||||||
var s = Text.Substring(Offset, n);
|
var s = Text.Substring(_position.Offset, n);
|
||||||
ConsumeChars(n);
|
ConsumeChars(n);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CharactersLeft()
|
public int CharactersLeft()
|
||||||
{
|
{
|
||||||
return Text.Length - Offset;
|
return Text.Length - _position.Offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
public override char PeekChar(int n)
|
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