specific file for special regex rule
This commit is contained in:
@@ -1,16 +1,18 @@
|
|||||||
# StgSharp
|
# Nitload
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
StgSharp is an experimental .NET framework for graphics, numerical computing, language analysis, and other performance-sensitive applications. It began as the foundation of a next-generation STG (shoot 'em up) engine, but the current repository focuses on reusable low-level infrastructure rather than a complete, ready-to-use game engine.
|
Nitload (formerly StgSharp) is an experimental .NET framework for graphics, numerical computing, language analysis, and other performance-sensitive applications. It began as the foundation of a next-generation STG (shoot 'em up) engine, but the current repository focuses on reusable low-level infrastructure rather than a complete, ready-to-use game engine.
|
||||||
|
|
||||||
|
The managed libraries now use the `Nitload.*` namespace and project prefix. Repository URLs, the logo filename, and some legacy test artifacts still retain the StgSharp name.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The framework combines managed C# APIs with a C native library. Its current work includes OpenGL bindings and rendering infrastructure, generic matrix and vector types, SIMD-accelerated native kernels, custom allocators and collections, regular-language analysis, and state-oriented UI infrastructure. StgSharp targets .NET 8; platform and architecture coverage varies by module, with Windows and Linux as the principal native targets.
|
The framework combines managed C# APIs with a C native library. Its current work includes OpenGL bindings and rendering infrastructure, generic matrix and vector types, SIMD-accelerated native kernels, custom allocators and collections, regular-language analysis, and state-oriented UI infrastructure. Nitload targets .NET 8; platform and architecture coverage varies by module, with Windows and Linux as the principal native targets.
|
||||||
|
|
||||||
## Core Modules
|
## Core Modules
|
||||||
|
|
||||||
### StgSharp.Common
|
### Nitload.Common
|
||||||
|
|
||||||
The foundational library containing shared functionality:
|
The foundational library containing shared functionality:
|
||||||
|
|
||||||
@@ -20,7 +22,7 @@ The foundational library containing shared functionality:
|
|||||||
- **Pipeline and State**: Processing pipelines and reusable state-machine primitives
|
- **Pipeline and State**: Processing pipelines and reusable state-machine primitives
|
||||||
- **Environment**: Platform abstraction and system integration
|
- **Environment**: Platform abstraction and system integration
|
||||||
|
|
||||||
### StgSharp.Mathematics (Numeric)
|
### Nitload.Mathematics (Numeric)
|
||||||
|
|
||||||
Numerics and linear algebra built on top of the core library:
|
Numerics and linear algebra built on top of the core library:
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@ Numerics and linear algebra built on top of the core library:
|
|||||||
- **Numeric Utilities**: Core numeric helpers and algorithms
|
- **Numeric Utilities**: Core numeric helpers and algorithms
|
||||||
- **SIMD-Friendly Kernels**: Data layouts optimized for hardware acceleration
|
- **SIMD-Friendly Kernels**: Data layouts optimized for hardware acceleration
|
||||||
|
|
||||||
### StgSharp.RegularAnalysis
|
### Nitload.RegularAnalysis
|
||||||
|
|
||||||
Nitload General Regular Analysis (NGRA) infrastructure for recognizing and processing regular languages:
|
Nitload General Regular Analysis (NGRA) infrastructure for recognizing and processing regular languages:
|
||||||
|
|
||||||
@@ -36,9 +38,9 @@ Nitload General Regular Analysis (NGRA) infrastructure for recognizing and proce
|
|||||||
- **Parsing Primitives**: Reusable tokenizer and grammar building blocks
|
- **Parsing Primitives**: Reusable tokenizer and grammar building blocks
|
||||||
- **Analysis Pipeline**: Structured processing for language-like inputs
|
- **Analysis Pipeline**: Structured processing for language-like inputs
|
||||||
|
|
||||||
NGRA is a foundation for higher-level language tooling. It does not replace `StgSharp.Script`; the planned Script implementation depends on NGRA and has not started yet. The source currently under `StgSharp.Script` is retained from the earlier EXPRESS implementation and is not part of the active core solution.
|
NGRA is a foundation for higher-level language tooling. It does not replace `Nitload.Script`; the planned Script implementation depends on NGRA and has not started yet. The source currently under `Nitload.Script` is retained from the earlier EXPRESS implementation and is not part of the active core solution.
|
||||||
|
|
||||||
### StgSharp.Graphics
|
### Nitload.Graphics
|
||||||
|
|
||||||
Managed graphics infrastructure built on Common and Mathematics:
|
Managed graphics infrastructure built on Common and Mathematics:
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ Managed graphics infrastructure built on Common and Mathematics:
|
|||||||
- **Shader Support**: Shader compilation, program management, and shader-generation utilities
|
- **Shader Support**: Shader compilation, program management, and shader-generation utilities
|
||||||
- **Window Integration**: GLFW-based window and input access
|
- **Window Integration**: GLFW-based window and input access
|
||||||
|
|
||||||
### StgSharp.Native
|
### Nitload.Native
|
||||||
|
|
||||||
Native library integration:
|
Native library integration:
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ Native library integration:
|
|||||||
- **Matrix Kernels**: Optimized matrix computation routines
|
- **Matrix Kernels**: Optimized matrix computation routines
|
||||||
- **Platform Runtime**: Native thread and platform support for Windows and Linux
|
- **Platform Runtime**: Native thread and platform support for Windows and Linux
|
||||||
|
|
||||||
### StgSharp.TerminalDialogue
|
### Nitload.TerminalDialogue
|
||||||
|
|
||||||
Terminal-based user interface application and components:
|
Terminal-based user interface application and components:
|
||||||
|
|
||||||
@@ -64,7 +66,7 @@ Terminal-based user interface application and components:
|
|||||||
- **Dialogue System**: User interaction and input handling
|
- **Dialogue System**: User interaction and input handling
|
||||||
- **Terminal Graphics**: Text-based UI rendering
|
- **Terminal Graphics**: Text-based UI rendering
|
||||||
|
|
||||||
> Note: `StgSharp.Script` is planned as a consumer of NGRA and has not started yet. Its existing EXPRESS sources belong to the earlier implementation. `StgSharp.Model` is currently an empty placeholder while its design is being reconsidered.
|
> Note: `Nitload.Script` is planned as a consumer of NGRA and has not started yet. Its existing EXPRESS sources belong to the earlier implementation. `Nitload.Model` is currently an empty placeholder while its design is being reconsidered.
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
@@ -113,7 +115,7 @@ The benchmark reports normalized time per allocation/free operation. Each iterat
|
|||||||
### Data Processing
|
### Data Processing
|
||||||
|
|
||||||
- **NGRA**: Regex analysis, intermediate representation, optimization, and source generation
|
- **NGRA**: Regex analysis, intermediate representation, optimization, and source generation
|
||||||
- **EXPRESS (legacy/inactive)**: The repository retains an earlier experimental EXPRESS parser/compiler under `StgSharp.Script`
|
- **EXPRESS (legacy/inactive)**: The repository retains an earlier experimental EXPRESS parser/compiler under `Nitload.Script`
|
||||||
- **Script (planned)**: A future language layer intended to build on NGRA; development has not started
|
- **Script (planned)**: A future language layer intended to build on NGRA; development has not started
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
@@ -125,7 +127,7 @@ The benchmark reports normalized time per allocation/free operation. Each iterat
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
StgSharp is currently in development and requires compilation from source. **NuGet packages are not yet available** - you must build the project from source code.
|
Nitload is currently in development and requires compilation from source. **NuGet packages are not yet available** - you must build the project from source code.
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
@@ -159,7 +161,7 @@ StgSharp is currently in development and requires compilation from source. **NuG
|
|||||||
dotnet build Nitload.sln
|
dotnet build Nitload.sln
|
||||||
```
|
```
|
||||||
|
|
||||||
Managed builds copy an existing native binary into their output directory. They do not invoke CMake automatically, so build `StgSharp.Native` first when native functionality is required.
|
Managed builds copy an existing native binary into their output directory. They do not invoke CMake automatically, so build `Nitload.Native` first when native functionality is required.
|
||||||
|
|
||||||
### Build Configuration
|
### Build Configuration
|
||||||
|
|
||||||
@@ -168,7 +170,7 @@ StgSharp is currently in development and requires compilation from source. **NuG
|
|||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
|
|
||||||
- CMake is the maintained build path for `StgSharp.Native`; the checked-in presets primarily target Clang
|
- CMake is the maintained build path for `Nitload.Native`; the checked-in presets primarily target Clang
|
||||||
- The Visual Studio C project may be opened with MSVC tooling, but MSVC IntelliSense behavior and MSVC-produced binaries are not maintained or guaranteed
|
- The Visual Studio C project may be opened with MSVC tooling, but MSVC IntelliSense behavior and MSVC-produced binaries are not maintained or guaranteed
|
||||||
- Windows and Linux platform implementations exist; actual feature and architecture coverage may differ
|
- Windows and Linux platform implementations exist; actual feature and architecture coverage may differ
|
||||||
- x86-64 currently has the most complete optimized kernel coverage
|
- x86-64 currently has the most complete optimized kernel coverage
|
||||||
@@ -187,8 +189,8 @@ StgSharp is currently in development and requires compilation from source. **NuG
|
|||||||
### Matrix Operations
|
### Matrix Operations
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
using StgSharp.HighPerformance.Memory;
|
using Nitload.Common.HighPerformance.Memory;
|
||||||
using StgSharp.Mathematics.Numeric;
|
using Nitload.Mathematics.Numeric;
|
||||||
|
|
||||||
// Matrix storage is allocated explicitly from a native-memory arena.
|
// Matrix storage is allocated explicitly from a native-memory arena.
|
||||||
using var allocator = new TwoLayerSegregatedFitAllocator(64 * 1024 * 1024);
|
using var allocator = new TwoLayerSegregatedFitAllocator(64 * 1024 * 1024);
|
||||||
@@ -207,7 +209,7 @@ General matrix arithmetic does not currently provide operator overloads. Because
|
|||||||
### Memory Management
|
### Memory Management
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
using StgSharp.HighPerformance.Memory;
|
using Nitload.Common.HighPerformance.Memory;
|
||||||
|
|
||||||
// Create a 64 MiB TLSF arena
|
// Create a 64 MiB TLSF arena
|
||||||
using var allocator = new TwoLayerSegregatedFitAllocator(64 * 1024 * 1024);
|
using var allocator = new TwoLayerSegregatedFitAllocator(64 * 1024 * 1024);
|
||||||
@@ -231,7 +233,7 @@ allocator.Free(handle);
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
StgSharp is developed by Nitload Space. Contributions are welcome, particularly in:
|
Nitload is developed by Nitload Space. Contributions are welcome, particularly in:
|
||||||
|
|
||||||
- Performance optimizations
|
- Performance optimizations
|
||||||
- Cross-platform compatibility
|
- Cross-platform compatibility
|
||||||
@@ -240,7 +242,7 @@ StgSharp is developed by Nitload Space. Contributions are welcome, particularly
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
StgSharp is licensed under the MIT License. See [LICENSE](LICENSE) for details.
|
Nitload is licensed under the MIT License. See [LICENSE](LICENSE) for details.
|
||||||
|
|
||||||
## Future Plans
|
## Future Plans
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# StgSharp.Native
|
# Nitload.Native
|
||||||
|
|
||||||
## COMPILE
|
## COMPILE
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,27 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
{
|
{
|
||||||
return node is null || ReferenceEquals(node, Empty);
|
return node is null || ReferenceEquals(node, Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recognizes zero-or-more repetitions of one non-negated Any atom, including lazy
|
||||||
|
/// repetition. Callers inspect the COUNT payload's IsGreedy flag separately.
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsDotStar(RegexAstNode? node)
|
||||||
|
{
|
||||||
|
if (node?.Payload is not RegexCountPayload { IsStar: true }) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool left_empty = IsNullOrEmpty(node.Left);
|
||||||
|
bool right_empty = IsNullOrEmpty(node.Right);
|
||||||
|
if (left_empty == right_empty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegexAstNode operand = left_empty ? node.Right : node.Left;
|
||||||
|
return operand.Payload is RegexCharSetPayload { IsAny: true, Accept: true } set &&
|
||||||
|
set.Set[0].Accept;
|
||||||
|
}
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
public void PrependNode(RegexAstNode previousNode)
|
public void PrependNode(RegexAstNode previousNode)
|
||||||
|
|||||||
@@ -7,15 +7,7 @@
|
|||||||
|
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Nitload.RegularAnalysis.Abstraction;
|
using Nitload.RegularAnalysis.Abstraction;
|
||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
|
||||||
using System.Reflection.Metadata.Ecma335;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Nitload.RegularAnalysis.Text
|
namespace Nitload.RegularAnalysis.Text
|
||||||
{
|
{
|
||||||
@@ -27,21 +19,24 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
in SequenceEmitter<string> sc,
|
in SequenceEmitter<string> sc,
|
||||||
in List<SequenceEmitter<string>> func_list,
|
in List<SequenceEmitter<string>> func_list,
|
||||||
in SourceGenContext context,
|
in SourceGenContext context,
|
||||||
|
in ExitLabel exit_label = default,
|
||||||
bool is_find = false
|
bool is_find = false
|
||||||
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegexAstNode root = ast;
|
RegexAstNode root = ast;
|
||||||
if (root.Label == RegexElementLabel.EPSILON) {
|
if (root.Label == RegexElementLabel.EPSILON) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (TryGenerateSpecialSource(root, sc, func_list, context, exit_label)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
RegexElementLabel op = root.Label & (RegexElementLabel.VAST_OPERATOR);
|
RegexElementLabel op = root.Label & (RegexElementLabel.VAST_OPERATOR);
|
||||||
if (op != 0)
|
if (op != 0)
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case RegexElementLabel.CONCAT:
|
case RegexElementLabel.CONCAT:
|
||||||
GenerateConcat(root, sc, func_list, context);
|
GenerateConcat(root, sc, func_list, context, exit_label);
|
||||||
break;
|
break;
|
||||||
case RegexElementLabel.COUNT:
|
case RegexElementLabel.COUNT:
|
||||||
GenerateCount(root, sc, func_list, context);
|
GenerateCount(root, sc, func_list, context);
|
||||||
@@ -64,25 +59,20 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case RegexElementLabel.UNIT:
|
case RegexElementLabel.UNIT:
|
||||||
|
GenerateUnit(root, sc, context, exit_label);
|
||||||
// TODO(NGRA): Emit the remaining-span length guard, literal comparison,
|
|
||||||
// cursor advance, and failure transfer for one character.
|
|
||||||
break;
|
break;
|
||||||
case RegexElementLabel.UNIT_SET:
|
case RegexElementLabel.UNIT_SET:
|
||||||
|
GenerateUnitSet(root, sc, context, exit_label);
|
||||||
// TODO(NGRA): Emit the remaining-span length guard, charset predicate,
|
|
||||||
// cursor advance, and failure transfer.
|
|
||||||
break;
|
break;
|
||||||
case RegexElementLabel.UNIT_SPAN:
|
case RegexElementLabel.UNIT_SPAN:
|
||||||
|
GenerateUnitSpan(root, sc, context, exit_label);
|
||||||
// TODO(NGRA): Emit StartsWith for the complete literal span and advance by
|
|
||||||
// the literal length; integrate is_find candidate retry semantics.
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
// TODO(NGRA): Diagnose malformed leaf nodes instead of generating no code.
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(NGRA): Integrate is_find candidate search and continuation retries.
|
||||||
|
// Leaf emission currently matches only at the active cursor.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,228 +110,105 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
case RegexCharSetType.Single:
|
case RegexCharSetType.Single:
|
||||||
return $"{accept}({FormatStringLiteral(set.Value)}.{nameof(MemoryExtensions.Contains)}({remain_span}[0]))";
|
return $"{accept}({FormatStringLiteral(set.Value)}.{nameof(MemoryExtensions.Contains)}({remain_span}[0]))";
|
||||||
case RegexCharSetType.Range:
|
case RegexCharSetType.Range:
|
||||||
|
if (set.Value.Length != 2) {
|
||||||
|
throw new InvalidOperationException("A charset range requires two endpoints.");
|
||||||
|
}
|
||||||
return $"{accept}({remain_span}[0] >= {FormatCharLiteral(set.Value[0])} && {remain_span}[0] <= {FormatCharLiteral(set.Value[1])})";
|
return $"{accept}({remain_span}[0] >= {FormatCharLiteral(set.Value[0])} && {remain_span}[0] <= {FormatCharLiteral(set.Value[1])})";
|
||||||
case RegexCharSetType.Set:
|
case RegexCharSetType.Set:
|
||||||
switch (set.Value[0])
|
switch (set.Value)
|
||||||
{
|
{
|
||||||
case 's':
|
case "s":
|
||||||
return $"{accept}char.IsWhiteSpace({remain_span}[0])";
|
return $"{accept}char.IsWhiteSpace({remain_span}[0])";
|
||||||
case 'w':
|
case "w":
|
||||||
return $"{accept}{nameof(TextRegex.IsCharWord)}({remain_span}[0])";
|
return $"{accept}{Text_Regex}.{nameof(TextRegex.IsCharWord)}({remain_span}[0])";
|
||||||
case 'd':
|
case "d":
|
||||||
return $"{accept}char.IsDigit({remain_span}[0])";
|
return $"{accept}char.IsDigit({remain_span}[0])";
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
goto default;
|
goto default;
|
||||||
|
case RegexCharSetType.Any:
|
||||||
|
return set.Accept ? "true" : "false";
|
||||||
default:
|
default:
|
||||||
|
throw new NotSupportedException($"Unsupported charset rule: {set.Type} ({set.Value}).");
|
||||||
// TODO(NGRA): Unsupported/empty charset rules must become an analyzer
|
|
||||||
// diagnostic; returning an empty expression produces invalid generated C#.
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsNamedFind(
|
|
||||||
RegexAstNode node
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// (?<name>.*)abc
|
|
||||||
|
|
||||||
if (node is null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((node.Label & RegexElementLabel.CONCAT) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
RegexAstNode group = node.Left;
|
|
||||||
|
|
||||||
// TODO(NGRA): Validate the normalized CONCAT/GROUP/COUNT shape with Empty sentinels
|
|
||||||
// before dereferencing children; this helper currently assumes every edge exists.
|
|
||||||
if ((group.Label & RegexElementLabel.GROUP_BEGIN) == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
RegexAstNode count = group.Right;
|
|
||||||
|
|
||||||
// .*
|
|
||||||
return (count.Label & RegexElementLabel.COUNT) != 0 &&
|
|
||||||
(count.Right.Label & RegexElementLabel.UNIT_SINGLE) != 0 &&
|
|
||||||
count.Right.Source.Source == ".";
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region basic verb generate
|
#region UNIT direct matching
|
||||||
|
|
||||||
private static void GenerateAlt(
|
private static void GenerateUnit(
|
||||||
RegexAstNode node,
|
RegexAstNode value,
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in List<SequenceEmitter<string>> func_list,
|
in SourceGenContext context,
|
||||||
in SourceGenContext context
|
in ExitLabel exit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegexAstNode current = node.Right;
|
string literal = value.Value;
|
||||||
|
if (literal.Length != 1) {
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"UNIT requires one decoded character, but received {literal.Length}.");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(NGRA-NAMING): Reserve exclusive names for future ALT cursor/capture snapshots;
|
string remain_span = context.RemainSpan;
|
||||||
// their lifetime extends through retry labels, not just the candidate's emitted block.
|
_ = sc.AppendLine($"if ({remain_span}.IsEmpty || {remain_span}[0] != {FormatCharLiteral(literal[0])})")
|
||||||
ExitLabel exit_label = context.RequestExitLabel(ExitMode.Goto);
|
|
||||||
|
|
||||||
// TODO(NGRA): Walk every normalized ALT candidate exactly once. The final traversal
|
|
||||||
// shape and failure continuation are not wired yet.
|
|
||||||
while (RegexAstNode.IsNullOrEmpty(current))
|
|
||||||
{
|
|
||||||
RegexElementLabel op = current.Label & RegexElementLabel.SEQUENCE;
|
|
||||||
if (op != 0)
|
|
||||||
{
|
|
||||||
string code = current.SourceCode;
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case RegexElementLabel.UNIT:
|
|
||||||
|
|
||||||
// TODO(NGRA): Guard against an empty remaining span before indexing it.
|
|
||||||
_ = sc.AppendLine(@$"if({context.RemainSpan}[0] == {FormatCharLiteral(code[0])})")
|
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice(1);")
|
.AppendLine($"goto {exit.GetLabelName()};")
|
||||||
.AppendLine($@"goto {exit_label};")
|
.AppendLine("}")
|
||||||
.AppendLine("}");
|
.AppendLine($"{remain_span} = {remain_span}.Slice(1);");
|
||||||
break;
|
|
||||||
case RegexElementLabel.UNIT_SET:
|
|
||||||
|
|
||||||
// TODO(NGRA): Guard the remaining span, handle empty/Any sets, and
|
|
||||||
// validate negated-set composition before emitting this predicate.
|
|
||||||
RegexCharSetPayload payload = current.PayloadAs<RegexCharSetPayload>();
|
|
||||||
IReadOnlyList<RegexCharSet> split = payload.Set;
|
|
||||||
bool accept = payload.Accept;
|
|
||||||
RegexCharSet _set = split[0];
|
|
||||||
_ = sc.AppendLine($"if({(accept ? string.Empty : "!(")} {GenerateCharSetExpression(_set)} ||");
|
|
||||||
for (int i = 1; i < split.Count - 1; i++)
|
|
||||||
{
|
|
||||||
_set = split[i];
|
|
||||||
_ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ||");
|
|
||||||
}
|
|
||||||
_set = split[^1];
|
|
||||||
_ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ){(accept ? string.Empty : ')')}")
|
|
||||||
.AppendLine("{")
|
|
||||||
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice(1);")
|
|
||||||
.AppendLine($@"goto {exit_label};")
|
|
||||||
.AppendLine("}");
|
|
||||||
break;
|
|
||||||
case RegexElementLabel.UNIT_SPAN:
|
|
||||||
|
|
||||||
// TODO(NGRA): Advance by code.Length rather than one character and
|
|
||||||
// preserve the ALT rollback cursor on failure.
|
|
||||||
string liteal = FormatStringLiteral(code);
|
|
||||||
_ = sc.AppendLine(@$"if({context.RemainSpan}.{MemoryExtensions.StartsWith}({liteal}))")
|
|
||||||
.AppendLine("{")
|
|
||||||
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice({code.Length});")
|
|
||||||
.AppendLine($@"goto {exit_label};")
|
|
||||||
.AppendLine("}");
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
|
|
||||||
// TODO(NGRA): Route unsupported ALT candidates through the recursive
|
|
||||||
// matcher or report a source-generation diagnostic.
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(NGRA): Advance to the next ALT candidate after a scalar candidate
|
private static void GenerateUnitSet(
|
||||||
// misses; the current sequence branch does not update current.
|
RegexAstNode value,
|
||||||
} else
|
|
||||||
{
|
|
||||||
GenerateMethodSource(current, sc, func_list, context);
|
|
||||||
current = current.Next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(NGRA): Emit the all-alternatives-failed continuation before the shared success
|
|
||||||
// label, including restoration of the entry cursor and capture state.
|
|
||||||
_ = sc.AppendLine($@"{exit_label}: {{ }}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void GenerateGroup(
|
|
||||||
RegexAstNode node,
|
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in List<SequenceEmitter<string>> func_list,
|
in SourceGenContext context,
|
||||||
in SourceGenContext context
|
in ExitLabel exit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegexAstNode left = node.Left;
|
RegexCharSetPayload payload = value.PayloadAs<RegexCharSetPayload>();
|
||||||
RegexAstNode right = node.Right;
|
string[] rules = new string[payload.Set.Count];
|
||||||
|
for (int i = 0; i < rules.Length; i++) {
|
||||||
RegexGroupPayload config = node.PayloadAs<RegexGroupPayload>();
|
rules[i] = GenerateCharSetExpression(payload.Set[i]);
|
||||||
|
|
||||||
// TODO(NGRA-NAMING): Reserve exclusive names for generated group snapshots and capture
|
|
||||||
// temporaries. A capture's user-provided name is not a unique generated local name.
|
|
||||||
|
|
||||||
// TODO(NGRA): Select the owned group body using Empty-sentinel checks, snapshot its
|
|
||||||
// start cursor, and restore it when the child matcher fails.
|
|
||||||
if (left is not null)
|
|
||||||
{
|
|
||||||
GenerateMethodSource(left, sc, func_list, context);
|
|
||||||
} else
|
|
||||||
if (right is not null) {
|
|
||||||
GenerateMethodSource(right, sc, func_list, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string group_name = config.Name;
|
// Combine rule-level complements before applying the enclosing charset complement.
|
||||||
|
// An empty union accepts nothing; its complement accepts any available character.
|
||||||
// TODO(NGRA): Allocate numeric/named capture slots and emit the successful capture
|
string predicate = rules.Length == 0 ? "false" : string.Join(" || ", rules);
|
||||||
// span. Non-capturing groups still need a rollback scope but no stored capture.
|
string mismatch = payload.Accept ? $"!({predicate})" : $"({predicate})";
|
||||||
throw new NotImplementedException();
|
string remain_span = context.RemainSpan;
|
||||||
|
_ = sc.AppendLine($"if ({remain_span}.IsEmpty || {mismatch})")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine($"goto {exit.GetLabelName()};")
|
||||||
|
.AppendLine("}")
|
||||||
|
.AppendLine($"{remain_span} = {remain_span}.Slice(1);");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateConcat(
|
private static void GenerateUnitSpan(
|
||||||
RegexAstNode node,
|
RegexAstNode value,
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in List<SequenceEmitter<string>> func_list,
|
in SourceGenContext context,
|
||||||
in SourceGenContext context
|
in ExitLabel exit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegexAstNode left = node.Left;
|
string literal = value.Value;
|
||||||
RegexAstNode right = node.Right;
|
if (literal.Length == 0) {
|
||||||
|
throw new InvalidOperationException("UNIT_SPAN requires a non-empty literal.");
|
||||||
if (left is not null)
|
|
||||||
{
|
|
||||||
// find
|
|
||||||
if ((left.Label & RegexElementLabel.COUNT) == RegexElementLabel.COUNT &&
|
|
||||||
(left.Right.Label & RegexElementLabel.UNIT_SINGLE) == RegexElementLabel.UNIT_SINGLE &&
|
|
||||||
left.Right.Source.Source == "." &&
|
|
||||||
right is not null)
|
|
||||||
{
|
|
||||||
// TODO(NGRA): Emit the unnamed FIND candidate loop and retry the right subtree
|
|
||||||
// until it succeeds or no anchor candidate remains.
|
|
||||||
GenerateMethodSource(right, sc, func_list, context, true);
|
|
||||||
} else if (IsNamedFind(node))
|
|
||||||
{
|
|
||||||
if (right is not null)
|
|
||||||
{
|
|
||||||
// TODO(NGRA): Emit named FIND retry and capture the text preceding the
|
|
||||||
// successful anchor candidate.
|
|
||||||
GenerateMethodSource(right, sc, func_list, context, true);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// TODO(NGRA): Capture the remaining input for a terminal named dot-star.
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
GenerateMethodSource(left, sc, func_list, context);
|
|
||||||
if (right is not null) {
|
|
||||||
GenerateMethodSource(right, sc, func_list, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(NGRA): Normalize ownership so the right subtree is emitted exactly once. It is
|
// StartsWith also rejects input shorter than the decoded literal.
|
||||||
// currently reachable both inside the ordinary CONCAT branch and here.
|
string remain_span = context.RemainSpan;
|
||||||
if (right is not null)
|
_ = sc.AppendLine($"if (!{remain_span}.{nameof(MemoryExtensions.StartsWith)}({FormatStringLiteral(literal)}))")
|
||||||
{
|
.AppendLine("{")
|
||||||
GenerateMethodSource(right, sc, func_list, context);
|
.AppendLine($"goto {exit.GetLabelName()};")
|
||||||
}
|
.AppendLine("}")
|
||||||
|
.AppendLine($"{remain_span} = {remain_span}.Slice({literal.Length});");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UNIT count matching
|
||||||
|
|
||||||
private const int flattened_unit_count_threshold = 32;
|
private const int flattened_unit_count_threshold = 32;
|
||||||
|
|
||||||
private static void GenerateUnitCount(
|
private static void GenerateUnitCount(
|
||||||
@@ -435,19 +302,15 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
int additional_limit = max < 0 ? -1 : max - min;
|
int additional_limit = max < 0 ? -1 : max - min;
|
||||||
if (is_greedy && additional_limit != 0)
|
if (is_greedy && additional_limit != 0)
|
||||||
{
|
{
|
||||||
if (additional_limit < 0)
|
_ = additional_limit < 0 ?
|
||||||
{
|
sc.AppendLine($"while (!{remain_span}.IsEmpty && {remain_span}[0] == {expected_literal})")
|
||||||
_ = sc.AppendLine($"while (!{remain_span}.IsEmpty && {remain_span}[0] == {expected_literal})")
|
.AppendLine("{")
|
||||||
|
.AppendLine($"{remain_span} = {remain_span}.Slice(1);")
|
||||||
|
.AppendLine("}") :
|
||||||
|
sc.AppendLine($"for (int {additional_count} = 0; {additional_count} < {additional_limit} && !{remain_span}.IsEmpty && {remain_span}[0] == {expected_literal}; {additional_count}++)")
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($"{remain_span} = {remain_span}.Slice(1);")
|
.AppendLine($"{remain_span} = {remain_span}.Slice(1);")
|
||||||
.AppendLine("}");
|
.AppendLine("}");
|
||||||
} else
|
|
||||||
{
|
|
||||||
_ = sc.AppendLine($"for (int {additional_count} = 0; {additional_count} < {additional_limit} && !{remain_span}.IsEmpty && {remain_span}[0] == {expected_literal}; {additional_count}++)")
|
|
||||||
.AppendLine("{")
|
|
||||||
.AppendLine($"{remain_span} = {remain_span}.Slice(1);")
|
|
||||||
.AppendLine("}");
|
|
||||||
}
|
|
||||||
} else if (!is_greedy && additional_limit != 0)
|
} else if (!is_greedy && additional_limit != 0)
|
||||||
{
|
{
|
||||||
// Lazy COUNT deliberately stops at Min. Its optional tail is consumed only when
|
// Lazy COUNT deliberately stops at Min. Its optional tail is consumed only when
|
||||||
@@ -673,12 +536,156 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateCount(
|
#endregion
|
||||||
|
|
||||||
|
#region UNIT find matching
|
||||||
|
|
||||||
|
// TODO(NGRA): Add UNIT, UNIT_SET, and UNIT_SPAN candidate search emitters here.
|
||||||
|
// Wire is_find dispatch and continuation retries when FIND matching is implemented.
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Operator generation
|
||||||
|
|
||||||
|
private static void GenerateAlt(
|
||||||
|
RegexAstNode node,
|
||||||
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
|
in List<SequenceEmitter<string>> func_list,
|
||||||
|
in SourceGenContext context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
RegexAstNode current = node.Right;
|
||||||
|
|
||||||
|
// TODO(NGRA-NAMING): Reserve exclusive names for future ALT cursor/capture snapshots;
|
||||||
|
// their lifetime extends through retry labels, not just the candidate's emitted block.
|
||||||
|
ExitLabel exit_label = context.RequestExitLabel(ExitMode.Goto);
|
||||||
|
|
||||||
|
// TODO(NGRA): Walk every normalized ALT candidate exactly once. The final traversal
|
||||||
|
// shape and failure continuation are not wired yet.
|
||||||
|
while (RegexAstNode.IsNullOrEmpty(current))
|
||||||
|
{
|
||||||
|
RegexElementLabel op = current.Label & RegexElementLabel.SEQUENCE;
|
||||||
|
if (op != 0)
|
||||||
|
{
|
||||||
|
string code = current.SourceCode;
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case RegexElementLabel.UNIT:
|
||||||
|
|
||||||
|
// TODO(NGRA): Guard against an empty remaining span before indexing it.
|
||||||
|
_ = sc.AppendLine(@$"if({context.RemainSpan}[0] == {FormatCharLiteral(code[0])})")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice(1);")
|
||||||
|
.AppendLine($@"goto {exit_label};")
|
||||||
|
.AppendLine("}");
|
||||||
|
break;
|
||||||
|
case RegexElementLabel.UNIT_SET:
|
||||||
|
|
||||||
|
// TODO(NGRA): Guard the remaining span, handle empty/Any sets, and
|
||||||
|
// validate negated-set composition before emitting this predicate.
|
||||||
|
RegexCharSetPayload payload = current.PayloadAs<RegexCharSetPayload>();
|
||||||
|
IReadOnlyList<RegexCharSet> split = payload.Set;
|
||||||
|
bool accept = payload.Accept;
|
||||||
|
RegexCharSet _set = split[0];
|
||||||
|
_ = sc.AppendLine($"if({(accept ? string.Empty : "!(")} {GenerateCharSetExpression(_set)} ||");
|
||||||
|
for (int i = 1; i < split.Count - 1; i++)
|
||||||
|
{
|
||||||
|
_set = split[i];
|
||||||
|
_ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ||");
|
||||||
|
}
|
||||||
|
_set = split[^1];
|
||||||
|
_ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ){(accept ? string.Empty : ')')}")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice(1);")
|
||||||
|
.AppendLine($@"goto {exit_label};")
|
||||||
|
.AppendLine("}");
|
||||||
|
break;
|
||||||
|
case RegexElementLabel.UNIT_SPAN:
|
||||||
|
|
||||||
|
// TODO(NGRA): Advance by code.Length rather than one character and
|
||||||
|
// preserve the ALT rollback cursor on failure.
|
||||||
|
string literal = FormatStringLiteral(code);
|
||||||
|
_ = sc.AppendLine(@$"if({context.RemainSpan}.{MemoryExtensions.StartsWith}({literal}))")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice({code.Length});")
|
||||||
|
.AppendLine($@"goto {exit_label};")
|
||||||
|
.AppendLine("}");
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
// TODO(NGRA): Route unsupported ALT candidates through the recursive
|
||||||
|
// matcher or report a source-generation diagnostic.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(NGRA): Advance to the next ALT candidate after a scalar candidate
|
||||||
|
// misses; the current sequence branch does not update current.
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
GenerateMethodSource(current, sc, func_list, context);
|
||||||
|
current = current.Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(NGRA): Emit the all-alternatives-failed continuation before the shared success
|
||||||
|
// label, including restoration of the entry cursor and capture state.
|
||||||
|
_ = sc.AppendLine($@"{exit_label}: {{ }}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateGroup(
|
||||||
|
RegexAstNode node,
|
||||||
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
|
in List<SequenceEmitter<string>> func_list,
|
||||||
|
in SourceGenContext context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
RegexAstNode left = node.Left;
|
||||||
|
RegexAstNode right = node.Right;
|
||||||
|
|
||||||
|
RegexGroupPayload config = node.PayloadAs<RegexGroupPayload>();
|
||||||
|
|
||||||
|
// TODO(NGRA-NAMING): Reserve exclusive names for generated group snapshots and capture
|
||||||
|
// temporaries. A capture's user-provided name is not a unique generated local name.
|
||||||
|
|
||||||
|
// TODO(NGRA): Select the owned group body using Empty-sentinel checks, snapshot its
|
||||||
|
// start cursor, and restore it when the child matcher fails.
|
||||||
|
if (left is not null)
|
||||||
|
{
|
||||||
|
GenerateMethodSource(left, sc, func_list, context);
|
||||||
|
} else
|
||||||
|
if (right is not null) {
|
||||||
|
GenerateMethodSource(right, sc, func_list, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
string group_name = config.Name;
|
||||||
|
|
||||||
|
// TODO(NGRA): Allocate numeric/named capture slots and emit the successful capture
|
||||||
|
// span. Non-capturing groups still need a rollback scope but no stored capture.
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateConcat(
|
||||||
RegexAstNode node,
|
RegexAstNode node,
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in List<SequenceEmitter<string>> func_list,
|
in List<SequenceEmitter<string>> func_list,
|
||||||
in SourceGenContext context,
|
in SourceGenContext context,
|
||||||
in ExitLabel exit
|
in ExitLabel exit_label = default
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!RegexAstNode.IsNullOrEmpty(node.Left)) {
|
||||||
|
GenerateMethodSource(node.Left, sc, func_list, context, exit_label);
|
||||||
|
}
|
||||||
|
if (!RegexAstNode.IsNullOrEmpty(node.Right)) {
|
||||||
|
GenerateMethodSource(node.Right, sc, func_list, context, exit_label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateCount(
|
||||||
|
RegexAstNode node,
|
||||||
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
|
in List<SequenceEmitter<string>> func_list,
|
||||||
|
in SourceGenContext context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegexAstNode value = RegexAstNode.IsNullOrEmpty(node.Left) ? node.Right : node.Left;
|
RegexAstNode value = RegexAstNode.IsNullOrEmpty(node.Left) ? node.Right : node.Left;
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// file="TextRegexSourceGen.GenSpecial"
|
||||||
|
// Project: Nitload
|
||||||
|
// Copyright (c) Nitload.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
using Nitload.RegularAnalysis.Abstraction;
|
||||||
|
|
||||||
|
namespace Nitload.RegularAnalysis.Text
|
||||||
|
{
|
||||||
|
internal partial class TextRegexSourceGen
|
||||||
|
{
|
||||||
|
|
||||||
|
private static bool TryGenerateSpecialSource(
|
||||||
|
RegexAstNode node,
|
||||||
|
in SequenceEmitter<string> sc,
|
||||||
|
in List<SequenceEmitter<string>> func_list,
|
||||||
|
in SourceGenContext context,
|
||||||
|
in ExitLabel exit_label
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// A special rule owns the entire matched subtree. Returning false leaves emission
|
||||||
|
// to the general path; returning true prevents that subtree from being emitted twice.
|
||||||
|
return node.Label switch
|
||||||
|
{
|
||||||
|
RegexElementLabel.CONCAT => TryGenerateFindConcat(node, sc, func_list, context, exit_label),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#region FIND concatenation
|
||||||
|
|
||||||
|
private static bool TryGenerateFindConcat(
|
||||||
|
RegexAstNode node,
|
||||||
|
in SequenceEmitter<string> sc,
|
||||||
|
in List<SequenceEmitter<string>> func_list,
|
||||||
|
in SourceGenContext context,
|
||||||
|
in ExitLabel exit_label
|
||||||
|
)
|
||||||
|
{
|
||||||
|
RegexAstNode left = node.Left;
|
||||||
|
RegexAstNode right = node.Right;
|
||||||
|
if (RegexAstNode.IsNullOrEmpty(left)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Existing FIND dispatch scaffold; candidate search and retries are not implemented.
|
||||||
|
// TODO(NGRA): Use the COUNT payload's IsGreedy flag to order FIND candidates.
|
||||||
|
if (RegexAstNode.IsDotStar(left) && !RegexAstNode.IsNullOrEmpty(right))
|
||||||
|
{
|
||||||
|
// TODO(NGRA): Emit the unnamed FIND candidate loop and retry the right subtree
|
||||||
|
// until it succeeds or no anchor candidate remains.
|
||||||
|
GenerateMethodSource(right, sc, func_list, context, exit_label, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsNamedFind(node))
|
||||||
|
{
|
||||||
|
if (!RegexAstNode.IsNullOrEmpty(right))
|
||||||
|
{
|
||||||
|
// TODO(NGRA): Emit named FIND retry and capture the text preceding the
|
||||||
|
// successful anchor candidate.
|
||||||
|
GenerateMethodSource(right, sc, func_list, context, exit_label, true);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// TODO(NGRA): Capture the remaining input for a terminal named dot-star.
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsNamedFind(
|
||||||
|
RegexAstNode node
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// (?<name>.*)abc
|
||||||
|
|
||||||
|
if (RegexAstNode.IsNullOrEmpty(node) || node.Label != RegexElementLabel.CONCAT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RegexAstNode group = node.Left;
|
||||||
|
if (RegexAstNode.IsNullOrEmpty(group) ||
|
||||||
|
group.Payload is not RegexGroupPayload { IsCapturing: true } config ||
|
||||||
|
string.IsNullOrEmpty(config.Name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool left_empty = RegexAstNode.IsNullOrEmpty(group.Left);
|
||||||
|
bool right_empty = RegexAstNode.IsNullOrEmpty(group.Right);
|
||||||
|
return left_empty != right_empty &&
|
||||||
|
RegexAstNode.IsDotStar(left_empty ? group.Right : group.Left);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Repeated capture rules
|
||||||
|
|
||||||
|
// TODO(NGRA): Recognize and implement repeated captures such as (?<name>.*){m,n}
|
||||||
|
// and (?<name>.*a){m,n}. Keep these distinct from (?<name>.*)a FIND concatenation.
|
||||||
|
// A later repetition may need to reopen an earlier repetition's inner search, restoring
|
||||||
|
// its cursor, candidate position, and capture state. Do not claim these subtrees in
|
||||||
|
// TryGenerateSpecialSource until the complete retry/rollback strategy is implemented.
|
||||||
|
// An escaped star is a literal and must not be classified as dot-star repetition.
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-12
@@ -1,22 +1,22 @@
|
|||||||
# Source Projects
|
# Source Projects
|
||||||
|
|
||||||
This directory contains the production source code, native runtime, supporting applications, and benchmarks for StgSharp. Most managed projects target .NET 8. The native project is built separately with CMake and provides platform and SIMD functionality consumed by managed projects.
|
This directory contains the production source code, native runtime, supporting applications, and benchmarks for Nitload. Most managed projects target .NET 8. The native project is built separately with CMake and provides platform and SIMD functionality consumed by managed projects.
|
||||||
|
|
||||||
## Directory map
|
## Directory map
|
||||||
|
|
||||||
| Directory | Purpose |
|
| Directory | Purpose |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `StgSharp.Common` | Shared collections, memory management, threading, pipelines, platform abstractions, and other foundational APIs. |
|
| `Nitload.Common` | Shared collections, memory management, threading, pipelines, platform abstractions, and other foundational APIs. |
|
||||||
| `StgSharp.Mathematics` | Numeric types, vectors, matrices, geometry, and managed access to accelerated math operations. |
|
| `Nitload.Mathematics` | Numeric types, vectors, matrices, geometry, and managed access to accelerated math operations. |
|
||||||
| `StgSharp.Graphics` | OpenGL bindings, rendering infrastructure, shaders, textures, windows, and input integration. |
|
| `Nitload.Graphics` | OpenGL bindings, rendering infrastructure, shaders, textures, windows, and input integration. |
|
||||||
| `StgSharp.Native` | C native runtime, GLFW/STBI integration, allocators, platform code, and optimized SIMD/matrix kernels. See its own `README.md` for native build details. |
|
| `Nitload.Native` | C native runtime, GLFW/STBI integration, allocators, platform code, and optimized SIMD/matrix kernels. See its own `README.md` for native build details. |
|
||||||
| `StgSharp.RegularAnalysis` | NGRA regular-language analysis, regex processing, intermediate representations, and source-generation infrastructure. |
|
| `Nitload.RegularAnalysis` | NGRA regular-language analysis, regex processing, intermediate representations, and source-generation infrastructure. |
|
||||||
| `StgSharp.UserInterface` | State-oriented user-interface framework and its incremental source generator. |
|
| `Nitload.UserInterface` | State-oriented user-interface framework and its incremental source generator. |
|
||||||
| `StgSharp.TerminalDialogue` | Terminal user-interface components and an interactive terminal application. |
|
| `Nitload.TerminalDialogue` | Terminal user-interface components and an interactive terminal application. |
|
||||||
| `StgSharp.Benchmark` | BenchmarkDotNet workloads for measuring selected runtime and allocation behavior. |
|
| `Nitload.Benchmark` | BenchmarkDotNet workloads for measuring selected runtime and allocation behavior. |
|
||||||
| `StgSharp.Script` | Retained sources from the earlier EXPRESS implementation. The planned Script layer has not started and is expected to build on NGRA. |
|
| `Nitload.Script` | Retained sources from the earlier EXPRESS implementation. The planned Script layer has not started and is expected to build on NGRA. |
|
||||||
| `StgSharp.Model` | Placeholder project whose design is being reconsidered. |
|
| `Nitload.Model` | Placeholder project whose design is being reconsidered. |
|
||||||
| `StgSharp.Tools` | Small retained comparison and inspection artifacts; it is not currently a buildable project. |
|
| `Nitload.Tools` | Small retained comparison and inspection artifacts; it is not currently a buildable project. |
|
||||||
|
|
||||||
## Build notes
|
## Build notes
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
# StgSharp.GenerateGL
|
# Nitload.GenerateGL
|
||||||
|
|
||||||
`StgSharp.GenerateGL` generates the StgSharp desktop OpenGL C# bindings from the Khronos `gl.xml` registry.
|
`Nitload.GenerateGL` generates the Nitload desktop OpenGL C# bindings from the Khronos `gl.xml` registry.
|
||||||
|
|
||||||
The current target is OpenGL 4.6 Core. The generator does not emit OpenGL ES or mix extension entry points into the core API. `gl.xml` is the authoritative generation input; the retained `gl.h` is reference material only.
|
The current target is OpenGL 4.6 Core. The generator does not emit OpenGL ES or mix extension entry points into the core API. `gl.xml` is the authoritative generation input; the retained `gl.h` is reference material only.
|
||||||
|
|
||||||
|
## Namespace migration
|
||||||
|
|
||||||
|
The project and directory are named `Nitload.GenerateGL`, but the implementation namespace and generated-source templates still contain `StgSharp.*`. Update the templates in `Generation/OpenGlGenerator.cs` to emit `Nitload.Graphics.OpenGL` and import `Nitload.Mathematics.Numeric.Graphics` before regenerating the renamed graphics library. The CLI commands below use the current project paths; they do not automatically migrate generated namespaces.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Start the interactive CLI:
|
Start the interactive CLI:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Khronos OpenGL Registry input
|
# Khronos OpenGL Registry input
|
||||||
|
|
||||||
This directory intentionally does not track the third-party Khronos registry files. Before building or running `StgSharp.GenerateGL`, supply a registry snapshot from the canonical [KhronosGroup/OpenGL-Registry](https://github.com/KhronosGroup/OpenGL-Registry) repository.
|
This directory intentionally does not track the third-party Khronos registry files. Before building or running `Nitload.GenerateGL`, supply a registry snapshot from the canonical [KhronosGroup/OpenGL-Registry](https://github.com/KhronosGroup/OpenGL-Registry) repository.
|
||||||
|
|
||||||
1. Clone or download one coherent revision of `KhronosGroup/OpenGL-Registry`.
|
1. Clone or download one coherent revision of `KhronosGroup/OpenGL-Registry`.
|
||||||
2. Copy the contents of its `xml/` directory directly into this directory.
|
2. Copy the contents of its `xml/` directory directly into this directory.
|
||||||
|
|||||||
+3
-3
@@ -1,14 +1,14 @@
|
|||||||
# Development Tools
|
# Development Tools
|
||||||
|
|
||||||
This directory contains repository-maintenance and source-generation programs. Tools are kept outside `src` because they help build or maintain StgSharp but are not shipped as part of the runtime libraries.
|
This directory contains repository-maintenance and source-generation programs. Tools are kept outside `src` because they help build or maintain Nitload but are not shipped as part of the runtime libraries.
|
||||||
|
|
||||||
## Directory map
|
## Directory map
|
||||||
|
|
||||||
| Directory | Purpose |
|
| Directory | Purpose |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `StgSharp.GenerateGL` | Reads the Khronos `gl.xml` registry, projects the OpenGL 4.6 Core API, analyzes function families, and generates the managed OpenGL bindings used by `StgSharp.Graphics`. |
|
| `Nitload.GenerateGL` | Reads the Khronos `gl.xml` registry, projects the OpenGL 4.6 Core API, analyzes function families, and generates the managed OpenGL bindings used by `Nitload.Graphics`. |
|
||||||
|
|
||||||
`StgSharp.GenerateGL` has its own `README.md` with its pipeline, naming rules, and interactive commands. The common direct-generation command is:
|
`Nitload.GenerateGL` has its own `README.md` with its pipeline, naming rules, and interactive commands. The common direct-generation command is:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
dotnet run --project tools/Nitload.GenerateGL/Nitload.GenerateGL.csproj -- generate all src/Nitload.Graphics/OpenGL/Generated
|
dotnet run --project tools/Nitload.GenerateGL/Nitload.GenerateGL.csproj -- generate all src/Nitload.Graphics/OpenGL/Generated
|
||||||
|
|||||||
Reference in New Issue
Block a user