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
70 changes: 53 additions & 17 deletions src/LLTSharp/LLTParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ private static void DeclareExpressions(ParserBuilder builder)
return target;
});

builder.CreateRule("nop_expression")
builder.CreateRule("simple_expression")
.Rule("prefix_operator");

// Operators //
Expand Down Expand Up @@ -372,12 +372,11 @@ private static void DeclareMessagesTemplates(ParserBuilder builder)
builder.CreateRule("message_statements")
.ZeroOrMore(b => b
.Literal('@')
.ConfigureLast(c => c.SkippingStrategy(ParserSkippingStrategy.SkipBeforeParsingGreedy))
.Choice(
c => c.Rule("message_block"),
c => c.Rule("messages_if"),
c => c.Rule("messages_foreach"),
// c => c.Rule("messages_while"),
c => c.Rule("messages_while"),
c => c.Rule("messages_render"),
c => c.Rule("messages_var_assignment"))
.Transform(v => v.GetValue(1)))
Expand Down Expand Up @@ -409,7 +408,7 @@ private static void DeclareMessagesTemplates(ParserBuilder builder)
builder.CreateRule("message_block_variable_role")
.Keyword("message")
.Literal('{')
.Literal('@').Keyword("role").Rule("nop_expression") // 4
.Literal('@').Keyword("role").Rule("simple_expression") // 4
.Rule("text_statements") // 5
.Literal('}')
.Transform(v =>
Expand Down Expand Up @@ -451,18 +450,23 @@ private static void DeclareMessagesTemplates(ParserBuilder builder)
return new MessagesTemplateForeachNode(collection, block, variable);
});

// TEMPORARY EXCLUDED: messages while loop
builder.CreateRule("messages_while")
.Keyword("while")
.Rule("expression")
.Rule("messages_template_block");
.Rule("messages_template_block")
.Transform(v =>
{
var expression = v.GetValue<TemplateExpressionNode>(1);
var block = v.GetValue<MessagesTemplateNode>(2);
return new MessagesTemplateWhileNode(expression, block);
});

builder.CreateRule("messages_render")
.Keyword("render")
.Rule("nop_expression") // 1
.Rule("simple_expression") // 1
.Optional(b => b
.Keyword("with")
.Rule("nop_expression")
.Rule("simple_expression")
.Transform(v => v.GetValue(1)))
.Transform(v =>
{
Expand Down Expand Up @@ -557,14 +561,14 @@ private static void DeclareTextTemplates(ParserBuilder builder)
b => b.Rule("text_if"),
b => b.Rule("text_foreach"),
b => b.Rule("text_render"),
// b => b.Rule("text_while"),
b => b.Rule("text_while"),
b => b.Rule("text_var_assignment"),
b => b.Rule("text_expression")
)
.Transform(v => v.GetValue(1));

builder.CreateRule("text_expression")
.Rule("nop_expression") // We don't want to use binary expressions in text statements
builder.CreateRule("text_expression_inner")
.Rule("simple_expression") // We don't want to use binary expressions in text statements
.Optional(b => b
.Literal(':')
.Token("raw_string"))
Expand All @@ -573,6 +577,21 @@ private static void DeclareTextTemplates(ParserBuilder builder)
var format = v.Children[1].Children.Count > 0 ? v.Children[1].Children[0].GetValue<string>(1) : null;
return new TextTemplateExpressionNode(v.GetValue<TemplateExpressionNode>(0), format);
});

builder.CreateRule("text_expression")
.Custom(
(self, ctx, sett, childSett, children, childrenIds) =>
{
var result = self.ParseRule(childrenIds[0], ctx, childSett);
if (!result.success)
return result;
var modifierChild = result.children[1];
if (modifierChild.length == 0)
result.length = result.children[0].length;
return result;
},
b => b.Rule("text_expression_inner")
);

builder.CreateRule("text_if")
.Keyword("if")
Expand Down Expand Up @@ -607,11 +626,16 @@ private static void DeclareTextTemplates(ParserBuilder builder)
return new TextTemplateForeachNode(collection, block, variable);
});

// TEMPORARY EXCLUDED: text while loop
builder.CreateRule("text_while")
.Keyword("while")
.Rule("expression")
.Rule("text_template_block");
.Rule("text_template_block")
.Transform(v =>
{
var expression = v.GetValue<TemplateExpressionNode>(1);
var block = v.GetValue<TextTemplateNode>(2);
return new TextTemplateWhileNode(expression, block);
});

builder.CreateRule("text_render")
.Keyword("render")
Expand All @@ -632,7 +656,7 @@ private static void DeclareTextTemplates(ParserBuilder builder)
.Keyword("let")
.Token("identifier")
.Literal("=")
.Rule("nop_expression")
.Rule("simple_expression")
.Transform(v =>
{
var name = v.GetValue<string>(1);
Expand All @@ -641,7 +665,7 @@ private static void DeclareTextTemplates(ParserBuilder builder)
}), b => b
.Token("identifier")
.Literal("=")
.Rule("nop_expression")
.Rule("simple_expression")
.Transform(v =>
{
var name = v.GetValue<string>(0);
Expand Down Expand Up @@ -683,6 +707,12 @@ private static void DeclareMainRules(ParserBuilder builder)
case "model_family":
metadata.Add(new TargetModelFamilyMetadata(pair.Value.ToString()));
break;
case "version":
metadata.Add(new VersionMetadata((int)((double)pair.Value.GetValue())));
break;
default:
metadata.Add(new AdditionalMetadata(pair.Key, pair.Value.GetValue()));
break;
}
}

Expand All @@ -703,11 +733,11 @@ static LLTParser()
builder.Settings
.Skip(s => s.Choice(
c => c.Whitespaces(),
c => c.Literal("@//").TextUntil('\n', '\r'), // @// C#-like comments
c => c.Literal("@/").TextUntil('\n', '\r'), // @/ C#-like comments
c => c.Literal("@*").TextUntil("*@").Literal("*@")) // @*...*@ comments
.ConfigureForSkip(), // Ignore all errors when parsing comments and unnecessary whitespace
ParserSkippingStrategy.TryParseThenSkipLazy) // Allows rules to capture skip-rules contents if can, such as whitespaces
.UseCaching(); // If caching is disabled, prepare to wait for a long time (seconds) when encountering an error :P (you will also get a million of errors, seriously)
.UseCaching().RecordWalkTrace(); // If caching is disabled, prepare to wait for a long time (seconds) when encountering an error :P (you will also get a million of errors, seriously)

// ---- Values ---- //
DeclareValues(builder);
Expand All @@ -728,6 +758,12 @@ static LLTParser()
}

public ParsedRuleResultBase ParseAST(string templateString)
{
var ctx = new LLTParsingContext { LocalLibrary = new TemplateLibrary() };
return _parser.Parse(templateString, ctx);
}

public ParsedRuleResultBase ParseOptimizedAST(string templateString)
{
var ctx = new LLTParsingContext { LocalLibrary = new TemplateLibrary() };
return _parser.Parse(templateString, ctx).Optimized(ParseTreeOptimization.Default);
Expand Down
4 changes: 2 additions & 2 deletions src/LLTSharp/LLTSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<PropertyGroup>
<PackageId>LLTSharp</PackageId>
<Version>1.0.0</Version>
<Version>1.1.0</Version>
<Authors>Roman K.</Authors>
<Company>RomeCore</Company>
<Product>LLTSharp</Product>
Expand All @@ -26,7 +26,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.10.0" />
<PackageReference Include="RCParsing" Version="4.6.1" />
<PackageReference Include="RCParsing" Version="4.7.1" />
</ItemGroup>

</Project>
14 changes: 14 additions & 0 deletions src/LLTSharp/Metadata/AdditionalMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
using LLTSharp.Utils;

namespace LLTSharp.Metadata
{
Expand Down Expand Up @@ -199,5 +200,18 @@ public override IEnumerable<string> GetDynamicMemberNames()
{
return _metadata.Keys;
}

public override bool Equals(object? obj)
{
return obj is AdditionalMetadata other &&
DictionaryUtils.DictionariesEqual(_metadata, other._metadata);
}

public override int GetHashCode()
{
int hash = 17;
hash = hash * 397 + DictionaryUtils.GetDictionaryHashCode(_metadata);
return hash;
}
}
}
14 changes: 14 additions & 0 deletions src/LLTSharp/Metadata/ImmutableAdditionalMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Dynamic;
using System.Linq;
using System.Text;
using LLTSharp.Utils;

namespace LLTSharp.Metadata
{
Expand Down Expand Up @@ -118,5 +119,18 @@ public override IEnumerable<string> GetDynamicMemberNames()
{
return _metadata.Keys;
}

public override bool Equals(object? obj)
{
return obj is ImmutableAdditionalMetadata other &&
DictionaryUtils.DictionariesEqual(_metadata, other._metadata);
}

public override int GetHashCode()
{
int hash = 17;
hash = hash * 397 + DictionaryUtils.GetDictionaryHashCode(_metadata);
return hash;
}
}
}
43 changes: 43 additions & 0 deletions src/LLTSharp/Metadata/VersionMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace LLTSharp.Metadata
{
/// <summary>
/// Represents the version metadata.
/// </summary>
public class VersionMetadata : IMetadata
{
/// <summary>
/// Gets the version code associated with this metadata.
/// </summary>
public int Version { get; }

/// <summary>
/// Initializes a new instance of the <see cref="VersionMetadata"/> class with the specified version code.
/// </summary>
/// <param name="version">The version code associated with this metadata.</param>
public VersionMetadata(int version)
{
Version = version;
}

public override string ToString()
{
return $"Version: {Version}";
}

public override bool Equals(object? obj)
{
return obj is VersionMetadata other && Version == other.Version;
}

public override int GetHashCode()
{
int hash = 17;
hash *= 397 + Version.GetHashCode();
return hash;
}
}
}
69 changes: 69 additions & 0 deletions src/LLTSharp/TemplateNodes/MessagesTemplateWhileNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.AI;

namespace LLTSharp.TemplateNodes
{
/// <summary>
/// Represents a node in the messages template that executes a child node while a condition is true.
/// </summary>
public class MessagesTemplateWhileNode : MessagesTemplateNode
{
/// <summary>
/// Gets the condition expression controlling the loop execution.
/// </summary>
public TemplateExpressionNode Condition { get; }

/// <summary>
/// Gets the child node that will be executed each iteration.
/// </summary>
public MessagesTemplateNode Child { get; }

/// <summary>
/// Creates a new instance of the <see cref="MessagesTemplateWhileNode"/> class.
/// </summary>
public MessagesTemplateWhileNode(TemplateExpressionNode condition, MessagesTemplateNode child)
{
Condition = condition ?? throw new ArgumentNullException(nameof(condition));
Child = child ?? throw new ArgumentNullException(nameof(child));
}

public override IEnumerable<ChatMessage> Render(TemplateContextAccessor context)
{
List<ChatMessage> messages = new List<ChatMessage>();

context.PushFrame();
try
{
while (EvaluateCondition(context))
{
var childResult = Child.Render(context);
messages.AddRange(childResult);
}
}
finally
{
context.PopFrame();
}

return messages;
}

private bool EvaluateCondition(TemplateContextAccessor context)
{
var value = Condition.Evaluate(context);
return value.AsBoolean();
}

public override void Refine(int depth)
{
Child.Refine(depth + 1);
}

public override string ToString()
{
return $"@messages while {Condition} {{\n{Child}\n}}";
}
}

}
1 change: 1 addition & 0 deletions src/LLTSharp/TemplateNodes/TextTemplateForeachNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using LLTSharp.DataAccessors;
using Microsoft.Extensions.AI;

namespace LLTSharp.TemplateNodes
{
Expand Down
Loading