-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from moorestech/feature/エラーのyaml上での位置をjsonnode…
…に含めるようにする Feature/エラーのyaml上での位置をjsonnodeに含めるようにする
- Loading branch information
Showing
10 changed files
with
208 additions
and
160 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,172 +1,93 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using YamlDotNet.Core; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace mooresmaster.Generator.Json; | ||
|
||
public struct Location | ||
{ | ||
public string FilePath; | ||
public long StartLine; | ||
public long StartColumn; | ||
public long EndLine; | ||
public long EndColumn; | ||
|
||
private static Location Create(string filePath, Mark start, Mark end) | ||
{ | ||
return new Location | ||
{ | ||
StartLine = start.Line, | ||
StartColumn = start.Column, | ||
EndLine = end.Line, | ||
EndColumn = end.Column, | ||
FilePath = filePath | ||
}; | ||
} | ||
|
||
public static Location Create(string filePath, YamlNode yamlNode) | ||
{ | ||
return Create(filePath, yamlNode.Start, yamlNode.End); | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return $"({StartLine}:{StartColumn} - {EndLine}:{EndColumn}) in {FilePath}"; | ||
} | ||
} | ||
|
||
public interface IJsonNode | ||
{ | ||
IJsonNode? Parent { get; } | ||
string? PropertyName { get; } | ||
Location Location { get; } | ||
} | ||
|
||
public record JsonObject(Dictionary<string, IJsonNode> Nodes, IJsonNode? Parent, string? PropertyName) : IJsonNode | ||
public record JsonObject(Dictionary<string, IJsonNode> Nodes, IJsonNode? Parent, string? PropertyName, Location Location) : IJsonNode | ||
{ | ||
public readonly Dictionary<string, IJsonNode> Nodes = Nodes; | ||
public IJsonNode? this[string key] => Nodes.ContainsKey(key) ? Nodes[key] : null; | ||
public IJsonNode? Parent { get; } = Parent; | ||
public string? PropertyName { get; } = PropertyName; | ||
public Location Location { get; } = Location; | ||
} | ||
|
||
public record JsonArray(IJsonNode[] Nodes, IJsonNode? Parent, string? PropertyName) : IJsonNode | ||
public record JsonArray(IJsonNode[] Nodes, IJsonNode? Parent, string? PropertyName, Location Location) : IJsonNode | ||
{ | ||
public IJsonNode[] Nodes = Nodes; | ||
public IJsonNode? this[int index] => Nodes.Length > index ? Nodes[index] : null; | ||
public IJsonNode? Parent { get; } = Parent; | ||
public string? PropertyName { get; } = PropertyName; | ||
public Location Location { get; } = Location; | ||
} | ||
|
||
public record JsonString(string Literal, IJsonNode? Parent, string? PropertyName) : IJsonNode | ||
public record JsonString(string Literal, IJsonNode? Parent, string? PropertyName, Location Location) : IJsonNode | ||
{ | ||
public readonly string Literal = Literal; | ||
public string? PropertyName { get; } = PropertyName; | ||
public Location Location { get; } = Location; | ||
public IJsonNode? Parent { get; } = Parent; | ||
public readonly string Literal = Literal; | ||
} | ||
|
||
public record JsonBoolean(bool Literal, IJsonNode? Parent, string? PropertyName) : IJsonNode | ||
public record JsonBoolean(bool Literal, IJsonNode? Parent, string? PropertyName, Location Location) : IJsonNode | ||
{ | ||
public readonly bool Literal = Literal; | ||
public IJsonNode? Parent { get; } = Parent; | ||
public string? PropertyName { get; } = PropertyName; | ||
public Location Location { get; } = Location; | ||
} | ||
|
||
public record JsonNumber(double Literal, IJsonNode? Parent, string? PropertyName) : IJsonNode | ||
public record JsonNumber(double Literal, IJsonNode? Parent, string? PropertyName, Location Location) : IJsonNode | ||
{ | ||
public readonly double Literal = Literal; | ||
public IJsonNode? Parent { get; } = Parent; | ||
public string? PropertyName { get; } = PropertyName; | ||
public Location Location { get; } = Location; | ||
} | ||
|
||
public record JsonInt(long Literal, IJsonNode? Parent, string? PropertyName) : IJsonNode | ||
public record JsonInt(long Literal, IJsonNode? Parent, string? PropertyName, Location Location) : IJsonNode | ||
{ | ||
public readonly long Literal = Literal; | ||
public IJsonNode? Parent { get; } = Parent; | ||
public string? PropertyName { get; } = PropertyName; | ||
} | ||
|
||
public static class JsonParser | ||
{ | ||
public static IJsonNode Parse(Token[] tokens) | ||
{ | ||
var iterator = new Iterator(tokens); | ||
return Parse(ref iterator, null, null); | ||
} | ||
|
||
private static IJsonNode Parse(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
return iterator.CurrentToken.Type switch | ||
{ | ||
TokenType.String => ParseString(ref iterator, parent, name), | ||
TokenType.LBrace => ParseObject(ref iterator, parent, name), | ||
TokenType.LSquare => ParseArray(ref iterator, parent, name), | ||
TokenType.True or TokenType.False => ParseBoolean(ref iterator, parent, name), | ||
TokenType.Number => ParseNumber(ref iterator, parent, name), | ||
TokenType.Int => ParseInt(ref iterator, parent, name), | ||
_ => throw new Exception($"""Unexpected token: {iterator.CurrentToken.Type} "{iterator.CurrentToken.Literal}" """) | ||
}; | ||
} | ||
|
||
private static IJsonNode ParseMinus(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
iterator.CurrentIndex++; // skip '-' | ||
switch (iterator.CurrentToken.Type) | ||
{ | ||
case TokenType.Int: | ||
var intValue = ParseInt(ref iterator, parent, name); | ||
return new JsonInt(-intValue.Literal, parent, name); | ||
case TokenType.Number: | ||
var numberValue = ParseNumber(ref iterator, parent, name); | ||
return new JsonNumber(-numberValue.Literal, parent, name); | ||
default: | ||
throw new ArgumentOutOfRangeException(); | ||
} | ||
} | ||
|
||
private static JsonInt ParseInt(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
var value = iterator.CurrentToken.Literal; | ||
iterator.CurrentIndex++; // skip int | ||
return new JsonInt(long.Parse(value), parent, name); | ||
} | ||
|
||
private static JsonNumber ParseNumber(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
var value = iterator.CurrentToken.Literal; | ||
iterator.CurrentIndex++; // skip number | ||
return new JsonNumber(double.Parse(value), parent, name); | ||
} | ||
|
||
private static JsonBoolean ParseBoolean(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
var value = iterator.CurrentToken.Literal; | ||
iterator.CurrentIndex++; // skip boolean | ||
return new JsonBoolean(value == "true", parent, name); | ||
} | ||
|
||
private static JsonString ParseString(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
var value = iterator.CurrentToken.Literal; | ||
iterator.CurrentIndex++; // skip string | ||
return new JsonString(value, parent, name); | ||
} | ||
|
||
private static JsonArray ParseArray(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
var nodes = new List<IJsonNode>(); | ||
iterator.CurrentIndex++; // skip '[' | ||
|
||
var jsonNode = new JsonArray([], parent, name); | ||
|
||
while (iterator.CurrentToken.Type != TokenType.RSquare) | ||
{ | ||
nodes.Add(Parse(ref iterator, jsonNode, null)); | ||
if (iterator.CurrentToken.Type == TokenType.RSquare) break; | ||
iterator.CurrentIndex++; // skip ',' | ||
} | ||
|
||
iterator.CurrentIndex++; // skip ']' | ||
|
||
jsonNode.Nodes = nodes.ToArray(); | ||
|
||
return jsonNode; | ||
} | ||
|
||
private static JsonObject ParseObject(ref Iterator iterator, IJsonNode? parent, string? name) | ||
{ | ||
var nodes = new Dictionary<string, IJsonNode>(); | ||
iterator.CurrentIndex++; // skip '{' | ||
|
||
var jsonNode = new JsonObject(nodes, parent, name); | ||
|
||
while (iterator.CurrentToken.Type != TokenType.RBrace) | ||
{ | ||
var key = iterator.CurrentToken.Literal; | ||
iterator.CurrentIndex++; // skip string | ||
iterator.CurrentIndex++; // skip ':' | ||
var value = Parse(ref iterator, jsonNode, key); | ||
nodes.Add(key, value); | ||
if (iterator.CurrentToken.Type == TokenType.RBrace) break; | ||
iterator.CurrentIndex++; // skip ',' | ||
} | ||
|
||
iterator.CurrentIndex++; // skip '}' | ||
|
||
return jsonNode; | ||
} | ||
|
||
public struct Iterator(Token[] tokens) | ||
{ | ||
public int CurrentIndex; | ||
public Token CurrentToken => tokens.Length > CurrentIndex ? tokens[CurrentIndex] : new Token(TokenType.Illegal, ""); | ||
public Token NextToken => tokens.Length > CurrentIndex + 1 ? tokens[CurrentIndex + 1] : new Token(TokenType.Illegal, ""); | ||
} | ||
public Location Location { get; } = Location; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.