Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/generated lexer #77

Merged
merged 13 commits into from
Aug 3, 2024
1 change: 1 addition & 0 deletions .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
run: dotnet build --no-restore -c Release -v n
- name: Unit Tests
run: |
dotnet test -c Release ./tests/HydraScript.Infrastructure.LexerRegexGenerator.Tests/HydraScript.Infrastructure.LexerRegexGenerator.Tests.csproj --no-build -v n
dotnet test -c Release /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura --no-build -v n --filter="Category=Unit"
mkdir coverage-report
- name: Code Coverage Summary Report For Merge Request
Expand Down
14 changes: 14 additions & 0 deletions ExtendedJavaScriptSubset.sln
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HydraScript.Infrastructure"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HydraScript.IntegrationTests", "tests\HydraScript.IntegrationTests\HydraScript.IntegrationTests.csproj", "{1CE98127-3027-4BD4-AAA3-63A589B09E73}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HydraScript.Infrastructure.LexerRegexGenerator", "src\Infrastructure\HydraScript.Infrastructure.LexerRegexGenerator\HydraScript.Infrastructure.LexerRegexGenerator.csproj", "{74D1495B-12A4-4E1A-ABE0-93029ECDC5FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HydraScript.Infrastructure.LexerRegexGenerator.Tests", "tests\HydraScript.Infrastructure.LexerRegexGenerator.Tests\HydraScript.Infrastructure.LexerRegexGenerator.Tests.csproj", "{829111AD-4A5C-4B3D-AC28-208309CE10D6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -130,6 +134,14 @@ Global
{1CE98127-3027-4BD4-AAA3-63A589B09E73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1CE98127-3027-4BD4-AAA3-63A589B09E73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1CE98127-3027-4BD4-AAA3-63A589B09E73}.Release|Any CPU.Build.0 = Release|Any CPU
{74D1495B-12A4-4E1A-ABE0-93029ECDC5FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74D1495B-12A4-4E1A-ABE0-93029ECDC5FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74D1495B-12A4-4E1A-ABE0-93029ECDC5FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74D1495B-12A4-4E1A-ABE0-93029ECDC5FE}.Release|Any CPU.Build.0 = Release|Any CPU
{829111AD-4A5C-4B3D-AC28-208309CE10D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{829111AD-4A5C-4B3D-AC28-208309CE10D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{829111AD-4A5C-4B3D-AC28-208309CE10D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{829111AD-4A5C-4B3D-AC28-208309CE10D6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{54CBE5A7-3C3E-44ED-B877-7B08A818083B} = {86CF2A2F-4DFE-48E7-B062-EF824730916A}
Expand All @@ -147,5 +159,7 @@ Global
{07DEA726-9772-4B61-AA66-1B82823F6BF0} = {A280C99E-0112-4F3C-A5E9-B793F2D9898E}
{160B77ED-BA30-40A2-81EF-F5D1E4D22039} = {B7DDF6C9-B67C-430A-948A-A380EF68DEF1}
{1CE98127-3027-4BD4-AAA3-63A589B09E73} = {3F131901-A9EC-451A-B7E9-726887CFE5FB}
{74D1495B-12A4-4E1A-ABE0-93029ECDC5FE} = {B7DDF6C9-B67C-430A-948A-A380EF68DEF1}
{829111AD-4A5C-4B3D-AC28-208309CE10D6} = {3F131901-A9EC-451A-B7E9-726887CFE5FB}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Text.RegularExpressions;

namespace HydraScript.Domain.FrontEnd.Lexer;

public interface IGeneratedRegexContainer
{
public static abstract Regex GetRegex();
}
2 changes: 1 addition & 1 deletion src/Domain/HydraScript.Domain.FrontEnd/Lexer/ILexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace HydraScript.Domain.FrontEnd.Lexer;

public interface ILexer
{
public Structure Structure { get; }
public IStructure Structure { get; }

public List<Token> GetTokens(string text);
}
11 changes: 11 additions & 0 deletions src/Domain/HydraScript.Domain.FrontEnd/Lexer/IStructure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Text.RegularExpressions;
using HydraScript.Domain.FrontEnd.Lexer.TokenTypes;

namespace HydraScript.Domain.FrontEnd.Lexer;

public interface IStructure : IEnumerable<TokenType>
{
public Regex Regex { get; }

public TokenType FindByTag(string tag);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using HydraScript.Domain.FrontEnd.Lexer.TokenTypes;

namespace HydraScript.Domain.FrontEnd.Lexer;

public interface ITokenTypesProvider
{
IEnumerable<TokenType> GetTokenTypes();
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

namespace HydraScript.Domain.FrontEnd.Lexer.Impl;

public class RegexLexer(Structure structure, ITextCoordinateSystemComputer computer) : ILexer, IEnumerable<Token>
public class RegexLexer(IStructure structure, ITextCoordinateSystemComputer computer) : ILexer, IEnumerable<Token>
{
private IReadOnlyList<int> _lines = [];
private string _text = "";

public Structure Structure { get; } = structure;
public IStructure Structure { get; } = structure;

public List<Token> GetTokens(string text)
{
Expand Down
31 changes: 31 additions & 0 deletions src/Domain/HydraScript.Domain.FrontEnd/Lexer/Impl/Structure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Text.RegularExpressions;
using HydraScript.Domain.FrontEnd.Lexer.TokenTypes;

namespace HydraScript.Domain.FrontEnd.Lexer.Impl;

public class Structure<TContainer>(ITokenTypesProvider provider) : IStructure
where TContainer : IGeneratedRegexContainer
{
private Dictionary<string, TokenType> Types { get; } = provider.GetTokenTypes()
.Concat([new EndOfProgramType(), new ErrorType()])
.ToDictionary(x => x.Tag);

public Regex Regex { get; } = TContainer.GetRegex();

public TokenType FindByTag(string tag) =>
Types[tag];

public override string ToString() =>
new StringBuilder()
.AppendJoin('\n', this)
.ToString();

public IEnumerator<TokenType> GetEnumerator() =>
Types.Values.GetEnumerator();

[ExcludeFromCodeCoverage]
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
54 changes: 0 additions & 54 deletions src/Domain/HydraScript.Domain.FrontEnd/Lexer/Structure.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace HydraScript.Domain.FrontEnd.Lexer.TokenTypes;

internal record EndOfProgramType() : TokenType("EOP", "", int.MaxValue - 1)
internal record EndOfProgramType() : TokenType(EopTag)
{
public override bool EndOfProgram() => true;
public const string EopTag = "EOP";
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace HydraScript.Domain.FrontEnd.Lexer.TokenTypes;

internal record ErrorType() : TokenType("ERROR", @"\S+", int.MaxValue)
internal record ErrorType() : TokenType("ERROR")
{
public override bool Error() => true;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace HydraScript.Domain.FrontEnd.Lexer.TokenTypes;

public record IgnorableType(string Tag, string Pattern, int Priority)
: TokenType(Tag, Pattern, Priority)
public record IgnorableType(string Tag) : TokenType(Tag)
{
public override bool CanIgnore() => true;
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
namespace HydraScript.Domain.FrontEnd.Lexer.TokenTypes;

public record TokenType(string Tag, string Pattern, int Priority)
public record TokenType(string Tag)
{
public virtual bool CanIgnore() => false;

public virtual bool EndOfProgram() => false;

public virtual bool Error() => false;

public string GetNamedRegex() => $"(?<{Tag}>{Pattern})";

public override string ToString() => Tag;
public sealed override string ToString() => Tag;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System.Diagnostics.CodeAnalysis;

namespace HydraScript.Domain.FrontEnd.Lexer;

public static class TokenTypesJson
{
[StringSyntax(StringSyntaxAttribute.Json)]
public const string String =
"""
[
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Globalization;
using System.Text.RegularExpressions;
using HydraScript.Domain.FrontEnd.Lexer;
using HydraScript.Domain.FrontEnd.Lexer.TokenTypes;
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast;
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes;
using HydraScript.Domain.FrontEnd.Parser.Impl.Ast.Nodes.Declarations;
Expand All @@ -26,7 +27,7 @@ public IAbstractSyntaxTree Parse(string text)
_tokens = _lexer.GetTokens(text);

var root = Script();
Expect("EOP");
Expect(EndOfProgramType.EopTag);
return new AbstractSyntaxTree(root);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

</Project>
2 changes: 1 addition & 1 deletion src/HydraScript/HydraScript.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Version>1.2.6</Version>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>

<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.10.0"/>
<PackageReference Include="System.Text.Json" Version="8.0.4">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace HydraScript.Infrastructure.LexerRegexGenerator;

public partial class PatternGenerator
{
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
{
Converters = { new TokenTypesReadConverter() }
};

private record TokenType(
string Tag,
string Pattern,
int Priority)
{
public string GetNamedRegex() => $"(?<{Tag}>{Pattern})";
}

[ExcludeFromCodeCoverage]
private class TokenTypesReadConverter : JsonConverter<IEnumerable<TokenType>>
{
public override IEnumerable<TokenType> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
var root = JsonElement.ParseValue(ref reader);
var tokenTypes = root.EnumerateArray()
.Select(element =>
{
var tag = element.GetProperty("tag").GetString()!;
var pattern = element.GetProperty("pattern").GetString()!;
var priority = element.GetProperty("priority").GetInt32();

return new TokenType(tag, pattern, priority);
})
.OrderBy(x => x.Priority);
return tokenTypes;
}

public override void Write(
Utf8JsonWriter writer,
IEnumerable<TokenType> value,
JsonSerializerOptions options) => throw new NotSupportedException();
}
}
Loading
Loading