Skip to content
Merged
Changes from 1 commit
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
Prev Previous commit
Make IParserAdapter implement ICompilable to support compilation
Co-authored-by: sebastienros <1165805+sebastienros@users.noreply.github.com>
  • Loading branch information
Copilot and sebastienros committed Nov 10, 2025
commit b3237549d0aa0db04739c1e984183124483c6d09
46 changes: 45 additions & 1 deletion src/Parlot/Fluent/IParserAdapter.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using Parlot.Compilation;
using Parlot.Rewriting;
using System.Linq.Expressions;

namespace Parlot.Fluent;

/// <summary>
/// Adapts an IParser&lt;T&gt; to a Parser&lt;T&gt; for use in contexts that require Parser.
/// This is used internally to support covariance.
/// </summary>
internal sealed class IParserAdapter<T> : Parser<T>, ISeekable
internal sealed class IParserAdapter<T> : Parser<T>, ISeekable, ICompilable
{
private readonly IParser<T> _parser;

Expand Down Expand Up @@ -39,5 +41,47 @@ public override bool Parse(ParseContext context, ref ParseResult<T> result)
return success;
}

public CompilationResult Compile(CompilationContext context)
{
// If the wrapped parser is actually a Parser<T>, delegate compilation to it
if (_parser is Parser<T> parser)
{
return parser.Build(context);
}

// Otherwise, fall back to the default non-compilable behavior
// This uses the Parse method which will work with any IParser<T>
var result = context.CreateCompilationResult<T>(false);

// ParseResult<T> parseResult;
var parseResult = Expression.Variable(typeof(ParseResult<T>), $"value{context.NextNumber}");
result.Variables.Add(parseResult);

// success = this.Parse(context.ParseContext, ref parseResult)
result.Body.Add(
Expression.Assign(result.Success,
Expression.Call(
Expression.Constant(this),
GetType().GetMethod("Parse", [typeof(ParseContext), typeof(ParseResult<T>).MakeByRefType()])!,
context.ParseContext,
parseResult))
);

if (!context.DiscardResult)
{
var value = result.Value = Expression.Variable(typeof(T), $"value{context.NextNumber}");
result.Variables.Add(value);

result.Body.Add(
Expression.IfThen(
result.Success,
Expression.Assign(value, Expression.Field(parseResult, "Value"))
)
);
}

return result;
}

public override string ToString() => _parser.ToString() ?? "IParserAdapter";
}