Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions src/Parlot/Compilation/CompilationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@ public class CompilationContext
{
private int _number;

public CompilationContext()
{
}

/// <summary>
/// Gets the expression containing the the <see cref="ParseContext"/> instance for the parser.
/// Gets the expression containing the <see cref="ParseContext"/> instance for the parser.
/// </summary>
public ParameterExpression ParseContext { get; } = Expression.Parameter(typeof(ParseContext));

Expand All @@ -27,12 +23,12 @@ public CompilationContext()
public int NextNumber => _number++;

/// <summary>
/// Gets the list of global variables to add the the final list of statements.
/// Gets the list of global variables to add the final list of statements.
/// </summary>
public List<ParameterExpression> GlobalVariables { get; } = new();

/// <summary>
/// Gets the list of global expressions to add the the final list of statements.
/// Gets the list of global expressions to add the final list of statements.
/// </summary>
public List<Expression> GlobalExpressions { get; } = new();

Expand Down
4 changes: 2 additions & 2 deletions src/Parlot/Compilation/CompilationResult.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

Expand All @@ -9,7 +9,7 @@ namespace Parlot.Compilation;
/// to parse the expected input.
/// The convention is that these statements are returned in the <see cref="Body"/> property, and any variable that needs to be declared in the block
/// that the <see cref="Body"/> is used in are set in the <see cref="Variables"/> list.
/// The <see cref="Success"/> property represents the variable that contains the success of the statements once executed, and if <code>true</code> then
/// The <see cref="Success"/> property represents the variable that contains the success of the statements once executed, and if <code>true</code> then
/// the <see cref="Value"/> property contains the result.
/// </summary>
public class CompilationResult
Expand Down
7 changes: 2 additions & 5 deletions src/Parlot/Compilation/CompiledParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ namespace Parlot.Compilation;
/// <summary>
/// Marker interface to detect a Parser has already been compiled.
/// </summary>
public interface ICompiledParser
{

}
public interface ICompiledParser;

/// <summary>
/// An instance of this class encapsulates the result of a compiled parser
/// in order to expose is as as standard parser contract.
/// in order to expose is as standard parser contract.
/// </summary>
/// <remarks>
/// This class is used in <see cref="Parser{T}.Compile"/>.
Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Cursor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void Advance(int count)
{
Current = NullChar;
Offset = _textLength;
_column += 1;
_column++;
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/Parlot/Fluent/Deferred.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace Parlot.Fluent;

public sealed class Deferred<T> : Parser<T>, ICompilable, ISeekable
{

private readonly object _lockObject = new();
private Parser<T>? _parser;

public Parser<T>? Parser
Expand Down Expand Up @@ -175,7 +177,7 @@ public override string ToString()
{
// Handle recursion

lock (this)
lock (_lockObject)
{
if (!_toString)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/Identifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public override bool Parse(ParseContext context, ref ParseResult<TextSpan> resul

var first = context.Scanner.Cursor.Current;

if (Character.IsIdentifierStart(first) || _extraStart != null && _extraStart(first))
if (Character.IsIdentifierStart(first) || (_extraStart != null && _extraStart(first)))
{
var start = context.Scanner.Cursor.Offset;

Expand Down
10 changes: 2 additions & 8 deletions src/Parlot/Fluent/LeftAssociative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,7 @@ public CompilationResult Compile(CompilationContext context)
var (op, factory) = _operators[i];
var opCompileResult = op.Build(context);

foreach (var variable in opCompileResult.Variables)
{
allOperatorVariables.Add(variable);
}
allOperatorVariables.AddRange(opCompileResult.Variables);

var factoryConst = Expression.Constant(factory);

Expand Down Expand Up @@ -291,10 +288,7 @@ public CompilationResult Compile(CompilationContext context)
var (op, factory) = _operators[i];
var opCompileResult = op.Build(context);

foreach (var variable in opCompileResult.Variables)
{
allOperatorVariables.Add(variable);
}
allOperatorVariables.AddRange(opCompileResult.Variables);

var factoryConst = Expression.Constant(factory);

Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/NumberLiteralBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public abstract class NumberLiteralBase<T> : Parser<T>, ICompilable, ISeekable

public abstract bool TryParseNumber(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider provider, out T value);

public NumberLiteralBase(NumberOptions numberOptions = NumberOptions.Number, char decimalSeparator = NumberLiterals.DefaultDecimalSeparator, char groupSeparator = NumberLiterals.DefaultGroupSeparator, MethodInfo? tryParseMethodInfo = null)
protected NumberLiteralBase(NumberOptions numberOptions = NumberOptions.Number, char decimalSeparator = NumberLiterals.DefaultDecimalSeparator, char groupSeparator = NumberLiterals.DefaultGroupSeparator, MethodInfo? tryParseMethodInfo = null)
{
_decimalSeparator = decimalSeparator;
_groupSeparator = groupSeparator;
Expand Down
28 changes: 14 additions & 14 deletions src/Parlot/Fluent/NumberOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;

namespace Parlot.Fluent;

Expand All @@ -8,7 +8,7 @@ public enum NumberOptions
/// <summary>
/// Indicates that no style elements, such as leading sign, thousands
/// separators, decimal separator or exponent, can be present in the parsed string.
/// The string to be parsed must consist of integral decimal digits only.
/// The string to be parsed must consist of integral decimal digits only.
/// </summary>
None = 0,

Expand All @@ -18,6 +18,12 @@ public enum NumberOptions
/// </summary>
AllowLeadingSign = 1,

/// <summary>
/// Indicates that the <see cref="AllowLeadingSign"/>
/// style is used. This is a composite number style.
/// </summary>
Integer = AllowLeadingSign,

/// <summary>
/// Indicates that the numeric string can have a decimal separator. By default it uses dot (.) as the separator.
/// </summary>
Expand All @@ -29,6 +35,12 @@ public enum NumberOptions
/// </summary>
AllowGroupSeparators = 4,

/// <summary>
/// Indicates that the <see cref="AllowLeadingSign"/>, <see cref="AllowDecimalSeparator"/>, <see cref="AllowGroupSeparators"/>
/// styles are used. This is a composite number style.
/// </summary>
Number = AllowLeadingSign | AllowDecimalSeparator | AllowGroupSeparators,

/// <summary>
/// Indicates that the numeric string can be in exponential notation. It
/// allows the parsed string to contain an exponent that begins with the "E"
Expand All @@ -37,18 +49,6 @@ public enum NumberOptions
/// </summary>
AllowExponent = 8,

/// <summary>
/// Indicates that the <see cref="AllowLeadingSign"/>
/// style is used. This is a composite number style.
/// </summary>
Integer = AllowLeadingSign,

/// <summary>
/// Indicates that the <see cref="AllowLeadingSign"/>, <see cref="AllowDecimalSeparator"/>, <see cref="AllowGroupSeparators"/>
/// styles are used. This is a composite number style.
/// </summary>
Number = AllowLeadingSign | AllowDecimalSeparator | AllowGroupSeparators,

/// <summary>
/// Indicates that the <see cref="AllowLeadingSign"/>, <see cref="AllowDecimalSeparator"/>, <see cref="AllowExponent"/>
/// styles are used. This is a composite number style.
Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/OneOf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static void AddUniqueSingle(List<Parser<T>> target, Parser<T> item)
lookupTable?.Remove(OtherSeekableChar);
var expectedChars = string.Join(",", lookupTable?.Keys.ToArray() ?? []);

if (lookupTable != null && lookupTable.Count > 0)
if (lookupTable?.Count > 0)
{
_map = new CharMap<List<Parser<T>>>(lookupTable);

Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/Optional.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Parlot.Fluent;
public sealed class Optional<T> : Parser<Option<T>>, ICompilable
{
private static readonly ConstructorInfo _optionConstructor = typeof(Option<T>).GetConstructor([typeof(T)])!;

private readonly Parser<T> _parser;
public Optional(Parser<T> parser)
{
Expand Down
5 changes: 2 additions & 3 deletions src/Parlot/Fluent/ParseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public ParseContext(Scanner scanner, bool useNewLines = false, bool disableLoopD
UseNewLines = useNewLines;
CancellationToken = cancellationToken;
DisableLoopDetection = disableLoopDetection;

_activeParserPositions = !disableLoopDetection ? new HashSet<ParserPosition>(ParserPositionComparer.Instance) : null!;
}

Expand Down Expand Up @@ -192,8 +192,7 @@ public int GetHashCode(ParserPosition obj)
unchecked
{
var hash = RuntimeHelpers.GetHashCode(obj.Parser);
hash = (hash * 397) ^ obj.Position;
return hash;
return (hash * 397) ^ obj.Position;
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/Parlot/Fluent/Parser.Compile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ namespace Parlot.Fluent;
public abstract partial class Parser<T>
{
private static readonly ConstructorInfo _valueTupleConstructor = typeof(ValueTuple<bool, T>).GetConstructor([typeof(bool), typeof(T)])!;
private readonly object _lockObject = new();

/// <summary>
/// Compiles the current parser.
/// </summary>
/// <returns>A compiled parser.</returns>
public Parser<T> Compile()
{
lock (this)
lock (_lockObject)
{
if (this is ICompiledParser)
{
Expand Down Expand Up @@ -79,7 +80,7 @@ public Parser<T> Compile()
}

/// <summary>
/// Invokes the <see cref="ICompilable.Compile(CompilationContext)"/> method of the <see cref="Parser{T}"/> if it's available or
/// Invokes the <see cref="ICompilable.Compile(CompilationContext)"/> method of the <see cref="Parser{T}"/> if it's available or
/// creates a generic one.
/// </summary>
/// <param name="context">The <see cref="CompilationContext"/> instance.</param>
Expand Down
8 changes: 4 additions & 4 deletions src/Parlot/Fluent/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ bool IParser<T>.Parse(ParseContext context, out int start, out int end, out obje
{
// Check if U implements IConvertible at construction time for performance
var targetImplementsIConvertible = typeof(IConvertible).IsAssignableFrom(typeof(U));

if (targetImplementsIConvertible)
{
return new Then<T, U?>(this, x =>
Expand All @@ -66,12 +66,12 @@ bool IParser<T>.Parse(ParseContext context, out int start, out int end, out obje
catch
{
// Fall back to default if conversion fails
return default(U);
return default;
}
}

// For non-convertible types, return default
return default(U);
return default;
});
}
else
Expand Down
2 changes: 0 additions & 2 deletions src/Parlot/Fluent/ParserExtensions.Cardinality.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Collections.Generic;

using Parlot;

namespace Parlot.Fluent;

public static partial class ParserExtensions
Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/ParserExtensions.WhiteSpace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public CommentsBuilder WithMultiLine(string multiLineStart, string multiLineEnd)
return this;
}

public Parser<TextSpan> Build()
public Parser<TextSpan> Build()
{
return Capture(ZeroOrMany(OneOf(_parsers.ToArray())));
}
Expand Down
4 changes: 2 additions & 2 deletions src/Parlot/Fluent/Parsers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public class LiteralBuilder
/// <summary>
/// Builds a parser that matches a keyword by ensuring the following character is not a letter.
/// </summary>
public Parser<string> Keyword(string text, bool caseInsensitive = false) => Text(text, caseInsensitive).When((context, value) => context.Scanner.Cursor.Eof || !Character.IsInRange(context.Scanner.Cursor.Current, 'a', 'z') && !Character.IsInRange(context.Scanner.Cursor.Current, 'A', 'Z'));
public Parser<string> Keyword(string text, bool caseInsensitive = false) => Text(text, caseInsensitive).When((context, value) => context.Scanner.Cursor.Eof || (!Character.IsInRange(context.Scanner.Cursor.Current, 'a', 'z') && !Character.IsInRange(context.Scanner.Cursor.Current, 'A', 'Z')));

/// <summary>
/// Builds a parser that matches the specified char.
Expand Down Expand Up @@ -333,7 +333,7 @@ public class TermBuilder
/// <summary>
/// Builds a parser that matches a keyword by ensuring the following character is not a letter.
/// </summary>
public Parser<string> Keyword(string text, bool caseInsensitive = false) => Text(text, caseInsensitive).When((context, value) => context.Scanner.Cursor.Eof || !Character.IsInRange(context.Scanner.Cursor.Current, 'a', 'z') && !Character.IsInRange(context.Scanner.Cursor.Current, 'A', 'Z'));
public Parser<string> Keyword(string text, bool caseInsensitive = false) => Text(text, caseInsensitive).When((context, value) => context.Scanner.Cursor.Eof || (!Character.IsInRange(context.Scanner.Cursor.Current, 'a', 'z') && !Character.IsInRange(context.Scanner.Cursor.Current, 'A', 'Z')));

/// <summary>
/// Builds a parser that matches the specified char.
Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/TextBefore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ private static void JumpToNextExpectedChar(ParseContext context, char[] expected
{
var indexOfAny = int.MaxValue;
var span = context.Scanner.Cursor.Span;

foreach (var c in expectedChars)
{
var index = span.IndexOf(c);
Expand Down
6 changes: 3 additions & 3 deletions src/Parlot/Fluent/TextLiteral.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public override bool Parse(ParseContext context, ref ParseResult<string> result)
var parsedText = context.Scanner.Buffer.AsSpan(start, end - start);

// Prevent an allocation if the text matches exactly
result.Set(start, end, parsedText.Equals(Text, StringComparison.Ordinal)
? Text
result.Set(start, end, parsedText.Equals(Text, StringComparison.Ordinal)
? Text
: parsedText.ToString());

context.ExitParser(this);
Expand All @@ -99,7 +99,7 @@ public CompilationResult Compile(CompilationContext context)
var resultSpan = Expression.Variable(typeof(ReadOnlySpan<char>), $"result{context.NextNumber}");
result.Variables.Add(resultSpan);

var readTextMethod = typeof(Scanner).GetMethod(nameof(Scanner.ReadText),
var readTextMethod = typeof(Scanner).GetMethod(nameof(Scanner.ReadText),
[typeof(ReadOnlySpan<char>), typeof(StringComparison), typeof(ReadOnlySpan<char>).MakeByRefType()])!;

var ifReadText = Expression.IfThen(
Expand Down
2 changes: 1 addition & 1 deletion src/Parlot/Fluent/Then.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace Parlot.Fluent;

/// <summary>
/// Returns a new <see cref="Parser{U}" /> converting the input value of
/// Returns a new <see cref="Parser{U}" /> converting the input value of
/// type T to the output value of type U using a custom function.
/// </summary>
/// <typeparam name="T">The input parser type.</typeparam>
Expand Down
10 changes: 2 additions & 8 deletions src/Parlot/Fluent/Unary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,7 @@ public CompilationResult Compile(CompilationContext context)
var (op, factory) = _operators[i];
var opCompileResult = op.Build(innerContext);

foreach (var variable in opCompileResult.Variables)
{
allOperatorVariables.Add(variable);
}
allOperatorVariables.AddRange(opCompileResult.Variables);

var factoryConst = Expression.Constant(factory);

Expand Down Expand Up @@ -318,10 +315,7 @@ public CompilationResult Compile(CompilationContext context)
var (op, factory) = _operators[i];
var opCompileResult = op.Build(innerContext);

foreach (var variable in opCompileResult.Variables)
{
allOperatorVariables.Add(variable);
}
allOperatorVariables.AddRange(opCompileResult.Variables);

var factoryConst = Expression.Constant(factory);

Expand Down
11 changes: 3 additions & 8 deletions src/Parlot/Fluent/WhenFollowedBy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,16 @@ public override bool Parse(ParseContext context, ref ParseResult<T> result)

public CompilationResult Compile(CompilationContext context)
{
var result = context.CreateCompilationResult<T>();

var mainParserCompileResult = _parser.Build(context, requireResult: true);

// For now, don't attempt to compile the lookahead check. Just compile the main parser.
// Compilation support for lookahead can be added later if needed.
// This ensures the parser still benefits from compilation of the main parser.

var parserResult = context.CreateCompilationResult<T>();

// Just add the compiled main parser
foreach (var variable in mainParserCompileResult.Variables)
{
parserResult.Variables.Add(variable);
}
parserResult.Variables.AddRange(mainParserCompileResult.Variables);

parserResult.Body.AddRange(mainParserCompileResult.Body);

Expand Down
Loading