Upload from upload_mods.ps1
This commit is contained in:
126
Scripts/Utilities/ExpressionParser/Sprache/Parse.Commented.cs
Normal file
126
Scripts/Utilities/ExpressionParser/Sprache/Parse.Commented.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniLinq;
|
||||
|
||||
namespace Sprache
|
||||
{
|
||||
partial class Parse
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a text span of the matched result.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the matched result.</typeparam>
|
||||
private class TextSpan<T> : ITextSpan<T>
|
||||
{
|
||||
public T Value { get; set; }
|
||||
|
||||
public Position Start { get; set; }
|
||||
|
||||
public Position End { get; set; }
|
||||
|
||||
public int Length { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a parser that returns the <see cref="ITextSpan{T}"/> of the parsed value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The result type of the given parser.</typeparam>
|
||||
/// <param name="parser">The parser to wrap.</param>
|
||||
/// <returns>A parser for the text span of the given parser.</returns>
|
||||
public static Parser<ITextSpan<T>> Span<T>(this Parser<T> parser)
|
||||
{
|
||||
if (parser == null) throw new ArgumentNullException(nameof(parser));
|
||||
|
||||
return i =>
|
||||
{
|
||||
var r = parser(i);
|
||||
if (r.WasSuccessful)
|
||||
{
|
||||
var span = new TextSpan<T>
|
||||
{
|
||||
Value = r.Value,
|
||||
Start = Position.FromInput(i),
|
||||
End = Position.FromInput(r.Remainder),
|
||||
Length = r.Remainder.Position - i.Position,
|
||||
};
|
||||
|
||||
return Result.Success(span, r.Remainder);
|
||||
}
|
||||
|
||||
return Result.Failure<ITextSpan<T>>(r.Remainder, r.Message, r.Expectations);
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a commented result with its leading and trailing comments.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the matched result.</typeparam>
|
||||
private class CommentedValue<T> : ICommented<T>
|
||||
{
|
||||
public CommentedValue(T value)
|
||||
{
|
||||
LeadingComments = TrailingComments = EmptyStringList;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public CommentedValue(IEnumerable<string> leading, T value, IEnumerable<string> trailing)
|
||||
{
|
||||
LeadingComments = leading ?? EmptyStringList;
|
||||
Value = value;
|
||||
TrailingComments = trailing ?? EmptyStringList;
|
||||
}
|
||||
|
||||
public T Value { get; }
|
||||
|
||||
public IEnumerable<string> LeadingComments { get; }
|
||||
|
||||
public IEnumerable<string> TrailingComments { get; }
|
||||
}
|
||||
|
||||
private static readonly string[] EmptyStringList = new string[0];
|
||||
|
||||
private static readonly IComment DefaultCommentParser = new CommentParser();
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a parser that consumes a whitespace and all comments
|
||||
/// parsed by the commentParser.AnyComment parser, but parses only one trailing
|
||||
/// comment that starts exactly on the last line of the parsed value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The result type of the given parser.</typeparam>
|
||||
/// <param name="parser">The parser to wrap.</param>
|
||||
/// <param name="commentParser">The comment parser.</param>
|
||||
/// <returns>An extended Token() version of the given parser.</returns>
|
||||
public static Parser<ICommented<T>> Commented<T>(this Parser<T> parser, IComment commentParser = null)
|
||||
{
|
||||
if (parser == null) throw new ArgumentNullException(nameof(parser));
|
||||
|
||||
// consume any comment supported by the comment parser
|
||||
var comment = (commentParser ?? DefaultCommentParser).AnyComment;
|
||||
|
||||
// parses any whitespace except for the new lines
|
||||
var whiteSpaceExceptForNewLine = WhiteSpace.Except(Chars("\r\n")).Many().Text();
|
||||
|
||||
// returns true if the second span starts on the first span's last line
|
||||
bool IsSameLine(ITextSpan<T> first, ITextSpan<string> second) =>
|
||||
first.End.Line == second.Start.Line;
|
||||
|
||||
// single comment span followed by a whitespace
|
||||
var commentSpan =
|
||||
from cs in comment.Span()
|
||||
from ws in whiteSpaceExceptForNewLine
|
||||
select cs;
|
||||
|
||||
// add leading and trailing comments to the parser
|
||||
return
|
||||
from leadingWhiteSpace in WhiteSpace.Many()
|
||||
from leadingComments in comment.Token().Many()
|
||||
from valueSpan in parser.Span()
|
||||
from trailingWhiteSpace in whiteSpaceExceptForNewLine
|
||||
from trailingPreview in commentSpan.Many().Preview()
|
||||
let trailingCount = trailingPreview.GetOrElse(Enumerable.Empty<ITextSpan<string>>())
|
||||
.Where(c => IsSameLine(valueSpan, c)).Count()
|
||||
from trailingComments in commentSpan.Repeat(trailingCount)
|
||||
select new CommentedValue<T>(leadingComments, valueSpan.Value, trailingComments.Select(c => c.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user