Skip to content

Commit

Permalink
Merge branch 'anytext'
Browse files Browse the repository at this point in the history
  • Loading branch information
georghinkel committed Nov 20, 2024
2 parents 9e536fe + b89a07d commit d82e9f8
Show file tree
Hide file tree
Showing 368 changed files with 49,413 additions and 29,652 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,4 @@ FakesAssemblies/
/Expressions/Tests/Expressions.Test/MethodCallTestsDynamic.cs
/UserInterfaces/NMetaGlspEditor/nmetaglspeditor.client/test.json
/Services/PropertyService/Properties/launchSettings.json
/AnyText/Tests/AnyTextExtension/out
24 changes: 24 additions & 0 deletions AnyText/AnyText.AspNetCore/AnyText.AspNetCore.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputType>Library</OutputType>
<AssemblyName>NMF.AnyText.AspNetCore</AssemblyName>
<RootNamespace>NMF.AnyText</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<OutputPath>..\..\Build</OutputPath>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\..\CommonAssemblyInfo.cs" Link="Properties\CommonAssemblyInfo.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Services\ModelServices\ModelServices.csproj" />
<ProjectReference Include="..\AnyText.Core\AnyText.Core.csproj" />
<ProjectReference Include="..\AnyText.Lsp\AnyText.Lsp.csproj" />
<ProjectReference Include="..\AnyText\AnyText.csproj" />
</ItemGroup>

</Project>
66 changes: 66 additions & 0 deletions AnyText/AnyText.AspNetCore/AnyTextWebSocketServerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NMF.AnyText;
using NMF.AnyText.Grammars;
using NMF.Models.Services;

namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Denotes extension methods to add GLSP server implementations to an ASP.NET Core dependency injection container
/// </summary>
public static class AnyTextWebSocketServerExtensions
{
/// <summary>
/// Registers the GLSP server itself
/// </summary>
/// <param name="services">The service container the GLSP server should be added to</param>
public static void AddGlspServer(this IServiceCollection services)
{
services.AddSingleton<ILspServer, LspServer>();
}

/// <summary>
/// Adds a graphical language
/// </summary>
/// <typeparam name="TLanguage">The type of graphical language</typeparam>
/// <param name="services">The service container the graphical language should be added to</param>
public static void AddLanguage<TLanguage>(this IServiceCollection services)
where TLanguage : Grammar
{
services.AddSingleton<Grammar, TLanguage>();
}

/// <summary>
/// Maps the GLSP server
/// </summary>
/// <param name="app">The endpoint route builder</param>
/// <param name="path">The path under which the GLSP server is called</param>
public static void MapLspWebSocketServer(this IEndpointRouteBuilder app, string path)
{
app.Map(path, async (HttpContext context, ILspServer server) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
var socket = await context.WebSockets.AcceptWebSocketAsync();
using (var rpc = AnyTextJsonRpcServerUtil.CreateServer(socket, server))
{
rpc.StartListening();
await rpc.Completion;
}
#if NET8_0_OR_GREATER
return Results.Empty;
#else
return Results.Ok();
#endif
}
else
{
return Results.BadRequest();
}
});
}
}
}
12 changes: 12 additions & 0 deletions AnyText/AnyText.AspNetCore/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"profiles": {
"AnyText.AspNetCore": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:59641;http://localhost:59642"
}
}
}
13 changes: 13 additions & 0 deletions AnyText/AnyText.Core/AnyText.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputType>Library</OutputType>
<AssemblyName>NMF.AnyText.Core</AssemblyName>
<RootNamespace>NMF.AnyText</RootNamespace>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<OutputPath>..\..\Build</OutputPath>
</PropertyGroup>

</Project>
55 changes: 55 additions & 0 deletions AnyText/AnyText.Core/Grammars/AdHocGrammar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using NMF.AnyText.Rules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NMF.AnyText.Grammars
{
/// <summary>
/// Wraps a rule (with pre-initialized dependencies) into a grammar
/// </summary>
public class AdHocGrammar : Grammar
{
private readonly Rule _root;
private readonly List<Rule> _furtherRules;

/// <summary>
/// Creates a new instance
/// </summary>
/// <param name="root">the rule that should be wrapped</param>
/// <param name="furtherRules">other rules</param>
public AdHocGrammar(Rule root, IEnumerable<Rule> furtherRules)
{
_root = root;
_furtherRules = new List<Rule>(furtherRules);
}

/// <inheritdoc/>
public override string LanguageId => null;

/// <inheritdoc/>
protected override IEnumerable<Rule> CreateCustomRules()
{
return _furtherRules;
}

/// <inheritdoc/>
protected override IDictionary<Type, Rule> CreateTypedRules()
{
return new Dictionary<Type, Rule>() { [typeof(Rule)] = _root };
}

/// <inheritdoc/>
protected override Rule GetRootRule(GrammarContext context)
{
return _root;
}

/// <summary>
/// Gets a collection of all rules
/// </summary>
public IEnumerable<Rule> Rules => Enumerable.Repeat(_root, 1).Concat(_furtherRules);
}
}
156 changes: 156 additions & 0 deletions AnyText/AnyText.Core/Grammars/Grammar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NMF.AnyText.Rules;

namespace NMF.AnyText.Grammars
{
/// <summary>
/// Denotes an abstract grammar
/// </summary>
public abstract class Grammar
{
private GrammarContext _context;

/// <summary>
/// Gets the rule with the given rule type
/// </summary>
/// <typeparam name="T">the type of the rule</typeparam>
/// <returns>the rule with the provided type, if it exists and registered for this type</returns>
public T GetRule<T>() where T : Rule
{
Initialize();
return _context?.ResolveRule<T>();
}

/// <summary>
/// Initializes the current grammar
/// </summary>
public void Initialize()
{
if (_context == null)
{
var rules = CreateTypedRules();
_context = new GrammarContext(rules, this);
var tokenTypes = new List<string>();
var tokenModifiers = new List<string>();
IEnumerable<Rule> allRules = rules.Values;
var others = CreateCustomRules();
if (others != null)
{
allRules = allRules.Concat(others);
}
foreach (var rule in allRules)
{
rule.Initialize(_context);
if (rule.TokenType != null)
{
CalculateTokenIndices(tokenTypes, tokenModifiers, rule, out int tokenTypeIndex, out int tokenModifierIndex);
rule.TokenTypeIndex = (uint)tokenTypeIndex;
rule.TokenModifierIndex = (uint)tokenModifierIndex;
}
}
foreach (var rule in allRules)
{
rule.IsLeftRecursive = rule.CanStartWith(rule);
}
TokenModifiers = tokenModifiers.ToArray();
TokenTypes = tokenTypes.ToArray();
}
}

/// <summary>
/// Creates the keyword rule for the given keyword
/// </summary>
/// <param name="keyword">the keyword</param>
/// <returns>A literal rule that represents matching the provided keyword</returns>
protected internal virtual LiteralRule CreateKeywordRule(string keyword)
{
return new LiteralRule(keyword);
}

private static void CalculateTokenIndices(List<string> tokenTypes, List<string> tokenModifiers, Rule rule, out int tokenTypeIndex, out int tokenModifierIndex)
{
tokenTypeIndex = tokenTypes.IndexOf(rule.TokenType);
if (tokenTypeIndex == -1)
{
tokenTypeIndex = tokenTypes.Count;
tokenTypes.Add(rule.TokenType);
}
tokenModifierIndex = 0;
foreach (var modifier in rule.TokenModifiers)
{
var modifierIndex = tokenModifiers.IndexOf(modifier);
if (modifierIndex == -1)
{
modifierIndex = tokenModifiers.Count;
tokenModifiers.Add(modifier);
}
tokenModifierIndex |= 1 << modifierIndex;
}
}

/// <summary>
/// Create the typed rules as a dictionary
/// </summary>
/// <returns>a dictionary of rules by type</returns>
protected abstract IDictionary<Type, Rule> CreateTypedRules();

/// <summary>
/// Create custom rules that are not resolvable by type
/// </summary>
/// <returns>a collection of custom rules</returns>
protected abstract IEnumerable<Rule> CreateCustomRules();

/// <summary>
/// Create a parser for this grammar
/// </summary>
/// <returns>a parser configured for this grammar</returns>
public Parser CreateParser()
{
return new Parser(CreateParseContext());
}

/// <summary>
/// Gets the language id for this grammar
/// </summary>
public abstract string LanguageId { get; }

/// <summary>
/// Creates a parsing context for this grammar
/// </summary>
/// <returns>a parsing context for the current grammar</returns>
protected internal virtual ParseContext CreateParseContext() => new ParseContext(this, new Matcher());

/// <summary>
/// Gets the root rule
/// </summary>
public Rule Root
{
get
{
Initialize();
return GetRootRule(_context);
}
}

/// <summary>
/// Gets an array of token types used by this grammar
/// </summary>
public string[] TokenTypes { get; private set; }

/// <summary>
/// Gets an array of token modifiers used by this grammar
/// </summary>
public string[] TokenModifiers { get; private set; }

/// <summary>
/// Gets the root rule
/// </summary>
/// <param name="context">a context to resolve the root rule</param>
/// <returns>the root rule for this grammar</returns>
protected abstract Rule GetRootRule(GrammarContext context);
}
}
Loading

0 comments on commit d82e9f8

Please sign in to comment.