import ast sys for regex runtime build
This commit is contained in:
@@ -12,7 +12,7 @@ StgSharp provides both low-level and high-level bindings to OpenGL, multimedia c
|
||||
|
||||
### StgSharp.Common
|
||||
|
||||
The main library containing core functionality:
|
||||
The foundational library containing shared functionality:
|
||||
|
||||
- **Mathematics**: High-performance linear algebra, matrix operations, and mathematical utilities
|
||||
- **Graphics**: OpenGL bindings, rendering pipeline, and graphics framework
|
||||
@@ -22,25 +22,21 @@ The main library containing core functionality:
|
||||
- **Entities**: Game entity system and behavior management
|
||||
- **Environment**: Platform abstraction and system integration
|
||||
|
||||
### StgSharp.Script
|
||||
### StgSharp.Mathematics (Numeric)
|
||||
|
||||
General-purpose syntax analysis framework:
|
||||
Numerics and linear algebra built on top of the core library:
|
||||
|
||||
- **Syntax Analysis Framework**: Provides a flexible framework for parsing and analyzing various programming languages
|
||||
- **EXPRESS Language Support**: Specialized support for ISO 10303-11 EXPRESS language syntax parsing
|
||||
- **Abstract Syntax Trees**: Language parsing and analysis infrastructure
|
||||
- **Token Processing**: Lexical analysis and token management
|
||||
- **Grammar Parsing**: Extensible grammar parsing and validation system
|
||||
- **Matrix & Vector Types**: High-performance math primitives
|
||||
- **Numeric Utilities**: Core numeric helpers and algorithms
|
||||
- **SIMD-Friendly Kernels**: Data layouts optimized for hardware acceleration
|
||||
|
||||
### StgSharp.Model
|
||||
### StgSharp.RegularAnalysis
|
||||
|
||||
Geometric model loading and interpretation:
|
||||
Regular-language and parsing infrastructure (replaces the former Script module):
|
||||
|
||||
- **Geometric Model Loading**: Responsible for loading and interpreting geometric models from various formats
|
||||
- **STEP Format Support**: Limited support for ISO 10303 STEP file format processing
|
||||
- **Entity Management**: Model entity parsing and geometric data interpretation
|
||||
- **Data Pipeline**: Efficient geometric data processing and transformation
|
||||
- **Schema Validation**: Model structure validation and verification
|
||||
- **Regex/Automata Core**: Regular expression processing and automata utilities
|
||||
- **Parsing Primitives**: Reusable tokenizer and grammar building blocks
|
||||
- **Analysis Pipeline**: Structured processing for language-like inputs
|
||||
|
||||
### StgSharp.Native
|
||||
|
||||
@@ -51,14 +47,24 @@ Native library integration:
|
||||
- **Matrix Kernels**: Optimized matrix computation routines
|
||||
- **Context Management**: Graphics context and resource management
|
||||
|
||||
### StgSharp.Device
|
||||
|
||||
Low-level device and port abstractions:
|
||||
|
||||
- **Command Interfaces**: Command shapes and serialization contracts
|
||||
- **Port Control**: Stream-oriented device access
|
||||
- **Decoder/Response Models**: Protocol-level data handling
|
||||
|
||||
### StgSharp.TerminalDialogue
|
||||
|
||||
Terminal-based user interface:
|
||||
Terminal-based user interface application and components:
|
||||
|
||||
- **Interactive Terminal**: Command-line interface components
|
||||
- **Interactive Terminal**: Command-line UI components
|
||||
- **Dialogue System**: User interaction and input handling
|
||||
- **Terminal Graphics**: Text-based UI rendering
|
||||
|
||||
> Note: The legacy Script module has been superseded by RegularAnalysis. The Model module is under refactoring and is currently out of the core framework.
|
||||
|
||||
## Key Features
|
||||
|
||||
### High-Performance Computing
|
||||
@@ -129,6 +135,7 @@ StgSharp is currently in development and requires compilation from source. **NuG
|
||||
### Building from Source
|
||||
|
||||
1. **Clone the repository**:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Nitload-NSI/StgSharp.git
|
||||
cd StgSharp
|
||||
@@ -140,6 +147,7 @@ StgSharp is currently in development and requires compilation from source. **NuG
|
||||
- The native components will be automatically compiled
|
||||
|
||||
3. **Linux (Experimental)**:
|
||||
|
||||
```bash
|
||||
# Build .NET components only
|
||||
# Note: Native components are not yet supported on Linux
|
||||
@@ -200,6 +208,7 @@ allocator.Free(handle);
|
||||
## Documentation
|
||||
|
||||
### Technical Documentation
|
||||
|
||||
- [HLSF Allocator](StgSharp.Common/HighPerformance/Memory/InroductionToHLSF.md) - High-performance memory allocator documentation
|
||||
- [Native Library Naming](StgSharp.Native/naming.md) - Native library file naming conventions
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="AbstractSyntaxTree"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.Collections;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml.Schema;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.Abstraction
|
||||
{
|
||||
public sealed class AbstractSyntaxTree<TNode, TType> where TNode : ISyntaxNode<TNode, TType>
|
||||
where TType : unmanaged
|
||||
{
|
||||
|
||||
private TNode _root;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return _allToken.Count; }
|
||||
}
|
||||
|
||||
public TNode Root => _root;
|
||||
|
||||
public bool Contains(
|
||||
TNode node
|
||||
)
|
||||
{
|
||||
return _allToken<TLabel>.Contains(node);
|
||||
}
|
||||
|
||||
private List<TNode> _allToken<TLabel> =
|
||||
new();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="CompileDepthState"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.Abstraction
|
||||
{
|
||||
public interface ICompileDepthState
|
||||
{
|
||||
|
||||
string CurrentState { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class CompileDepthMark
|
||||
{
|
||||
|
||||
internal CompileDepthMark(int operatorBegin, int operandBegin, int usage)
|
||||
{
|
||||
OperatorBegin = operatorBegin;
|
||||
OperandBegin = operandBegin;
|
||||
Usage = usage;
|
||||
}
|
||||
|
||||
internal CompileDepthMark(int operatorBegin, int operandBegin, int usage, ICompileDepthState stateCache)
|
||||
{
|
||||
OperatorBegin = operatorBegin;
|
||||
OperandBegin = operandBegin;
|
||||
Usage = usage;
|
||||
StateCache = stateCache;
|
||||
}
|
||||
|
||||
public bool IsBeginOfBlock { get; internal set; }
|
||||
|
||||
public ICompileDepthState StateCache { get; internal set; }
|
||||
|
||||
public int OperandBegin { get; internal set; }
|
||||
|
||||
public int OperatorBegin { get; internal set; }
|
||||
|
||||
public int Usage { get; internal set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="CompileStack"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.Collections;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.Abstraction
|
||||
{
|
||||
public partial class CompileStack<TNode, TLabel> where TNode : ISyntaxNode<TNode, TLabel>
|
||||
where TLabel : unmanaged
|
||||
{
|
||||
|
||||
private Token<TLabel>? _lastToken;
|
||||
|
||||
private TNode[] _nodeArray = new TNode[4];
|
||||
private Token<TLabel>[] _operatorArray = new Token<TLabel>[4];
|
||||
private Token<TLabel>[] _tokenArray = new Token<TLabel>[4];
|
||||
|
||||
private int _nodeCount,_tokenCount, _operatorCount;
|
||||
private RandomAccessibleStack<CompileDepthMark> _depthStack = new RandomAccessibleStack<CompileDepthMark>(
|
||||
);
|
||||
|
||||
private RandomAccessibleStack<OperandIndex> _isNode = new RandomAccessibleStack<OperandIndex>(
|
||||
8);
|
||||
private Stack<Stack<TNode>> _statementCache = new Stack<Stack<TNode>>();
|
||||
private TNode _lastNode;
|
||||
|
||||
public CompileStack()
|
||||
{
|
||||
_depthStack.Push(new CompileDepthMark(0, 0, 0, null!));
|
||||
_statementCache.Push(new Stack<TNode>());
|
||||
}
|
||||
|
||||
public bool IsLastAddedOperator { get; private set; }
|
||||
|
||||
public CompileDepthMark CurrentDepthMark
|
||||
{
|
||||
get => _depthStack.Peek();
|
||||
}
|
||||
|
||||
public int Depth => _depthStack.Count;
|
||||
|
||||
public int OperandCount => _isNode.Count;
|
||||
|
||||
public int OperatorCount => _operatorCount;
|
||||
|
||||
public int OperatorAheadOfDepth
|
||||
{
|
||||
get => OperatorCount - _depthStack.Peek().OperatorBegin;
|
||||
}
|
||||
|
||||
public int OperandAheadOfDepth
|
||||
{
|
||||
get => OperandCount - _depthStack.Peek().OperandBegin;
|
||||
}
|
||||
|
||||
public Stack<TNode> StatementsInDepth
|
||||
{
|
||||
get => _statementCache.Peek();
|
||||
}
|
||||
|
||||
public void DecreaseDepth()
|
||||
{
|
||||
CompileDepthMark mark = _depthStack.Pop();
|
||||
Stack<TNode> statementsInDepth = _statementCache.Pop();
|
||||
}
|
||||
|
||||
public bool GetOperandAt(
|
||||
Index i,
|
||||
out TNode operandNode,
|
||||
out Token<TLabel> operandToken
|
||||
)
|
||||
{
|
||||
OperandIndex index = _isNode[i];
|
||||
if (index.IsNode)
|
||||
{
|
||||
operandNode = _nodeArray[index.Index];
|
||||
operandToken = Token<TLabel>.Empty;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
operandToken = _tokenArray[index.Index];
|
||||
operandNode = default!;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetOperandAt(
|
||||
CompileDepthMark depth,
|
||||
Index i,
|
||||
out Token<TLabel> operandToken,
|
||||
out TNode operandNode
|
||||
)
|
||||
{
|
||||
OperandIndex index = _isNode[i];
|
||||
|
||||
_depthStack.Contains(depth);
|
||||
if (index.IsNode)
|
||||
{
|
||||
operandNode = _nodeArray[index.Index];
|
||||
operandToken = Token<TLabel>.Empty;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
operandToken = _tokenArray[index.Index];
|
||||
operandNode = default!;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public CompileDepthMark IncreaseDepth(
|
||||
int usage
|
||||
)
|
||||
{
|
||||
CompileDepthMark mark =
|
||||
new CompileDepthMark(OperatorCount, OperandCount, usage);
|
||||
|
||||
_depthStack.Push(mark);
|
||||
_statementCache.Push(new Stack<TNode>());
|
||||
return mark;
|
||||
}
|
||||
|
||||
public TNode PackAllStatements()
|
||||
{
|
||||
if (StatementsInDepth.Count == 0) {
|
||||
return TNode.Empty;
|
||||
}
|
||||
TNode end = StatementsInDepth.Peek();
|
||||
TNode first = end;
|
||||
while (StatementsInDepth.Count > 0)
|
||||
{
|
||||
first = StatementsInDepth.Pop();
|
||||
end.PrependNode(first);
|
||||
end = first;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
public bool PeekOperand(
|
||||
out Token<TLabel> t,
|
||||
out TNode n
|
||||
)
|
||||
{
|
||||
if (OperandAheadOfDepth <= 0)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = TNode.Empty;
|
||||
return false;
|
||||
}
|
||||
if (_isNode.Pop().IsNode)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = _nodeArray[_nodeCount - 1];
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
t = _tokenArray[_tokenCount - 1];
|
||||
n = TNode.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Token<TLabel> PeekOperator()
|
||||
{
|
||||
if (OperatorAheadOfDepth > 0) {
|
||||
return _operatorArray[_operatorCount - 1];
|
||||
}
|
||||
return Token<TLabel>.Empty;
|
||||
}
|
||||
|
||||
public bool PopOperand(
|
||||
out Token<TLabel> t,
|
||||
out TNode n
|
||||
)
|
||||
{
|
||||
if (OperandAheadOfDepth <= 0)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = TNode.Empty;
|
||||
return false;
|
||||
}
|
||||
if (_isNode.Pop().IsNode)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = _nodeArray[--_nodeCount];
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
t = _tokenArray[--_tokenCount];
|
||||
n = TNode.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Token<TLabel> PopOperator()
|
||||
{
|
||||
if (OperatorAheadOfDepth > 0)
|
||||
{
|
||||
_operatorCount--;
|
||||
return _operatorArray[_operatorCount];
|
||||
}
|
||||
return Token<TLabel>.Empty;
|
||||
}
|
||||
|
||||
public void PushOperand(
|
||||
TNode node
|
||||
)
|
||||
{
|
||||
if (_nodeArray.Length == _nodeCount) {
|
||||
Array.Resize(ref _nodeArray, _nodeArray.Length * 2);
|
||||
}
|
||||
_nodeArray[_nodeCount] = node;
|
||||
_isNode.Push(new(true, _nodeCount));
|
||||
_nodeCount++;
|
||||
IsLastAddedOperator = false;
|
||||
}
|
||||
|
||||
public void PushOperand(
|
||||
Token<TLabel> token
|
||||
)
|
||||
{
|
||||
if (_tokenArray.Length == _tokenCount) {
|
||||
Array.Resize(ref _tokenArray, _tokenArray.Length * 2);
|
||||
}
|
||||
_tokenArray[_tokenCount] = token;
|
||||
_isNode.Push(new(false, _tokenCount));
|
||||
_tokenCount++;
|
||||
IsLastAddedOperator = false;
|
||||
}
|
||||
|
||||
public void PushOperator(
|
||||
Token<TLabel> token
|
||||
)
|
||||
{
|
||||
if (_operatorArray.Length == _operatorCount) {
|
||||
Array.Resize(ref _operatorArray, _operatorArray.Length * 2);
|
||||
}
|
||||
_operatorArray[_operatorCount] = token;
|
||||
_operatorCount++;
|
||||
IsLastAddedOperator = true;
|
||||
}
|
||||
|
||||
public T StateOfCurrentDepth<T>() where T : class, ICompileDepthState
|
||||
{
|
||||
return (CurrentDepthMark.StateCache as T)!;
|
||||
}
|
||||
|
||||
public bool TryPeekOperand(
|
||||
out bool isNode,
|
||||
out Token<TLabel> t,
|
||||
out TNode n
|
||||
)
|
||||
{
|
||||
if (OperandAheadOfDepth <= 0)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = TNode.Empty;
|
||||
isNode = false;
|
||||
return false;
|
||||
}
|
||||
if (_isNode.Pop().IsNode)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = _nodeArray[_nodeCount - 1];
|
||||
isNode = true;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
t = _tokenArray[_tokenCount - 1];
|
||||
n = TNode.Empty;
|
||||
isNode = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryPeekOperator(
|
||||
out Token<TLabel> op
|
||||
)
|
||||
{
|
||||
if (OperatorAheadOfDepth > 0)
|
||||
{
|
||||
op = _operatorArray[_operatorCount - 1];
|
||||
return true;
|
||||
}
|
||||
op = Token<TLabel>.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryPopOperand(
|
||||
out bool isNode,
|
||||
out Token<TLabel> t,
|
||||
out TNode n
|
||||
)
|
||||
{
|
||||
if (OperandAheadOfDepth <= 0)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = TNode.Empty;
|
||||
isNode = false;
|
||||
return false;
|
||||
}
|
||||
if (_isNode.Pop().IsNode)
|
||||
{
|
||||
t = Token<TLabel>.Empty;
|
||||
n = _nodeArray[--_nodeCount];
|
||||
isNode = true;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
t = _tokenArray[--_tokenCount];
|
||||
n = TNode.Empty;
|
||||
isNode = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryPopOperator(
|
||||
out Token<TLabel> op
|
||||
)
|
||||
{
|
||||
if (OperatorAheadOfDepth > 0)
|
||||
{
|
||||
op = _operatorArray[--_operatorCount];
|
||||
return true;
|
||||
}
|
||||
op = Token<TLabel>.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
private record struct OperandIndex(
|
||||
bool IsNode,
|
||||
int Index
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="IScriptTokenReader"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
namespace StgSharp.RegularAnalysis.Abstraction
|
||||
{
|
||||
public interface IScriptTokenReader<TLabel> where TLabel : unmanaged
|
||||
{
|
||||
|
||||
bool IsEmpty { get; }
|
||||
|
||||
Token<TLabel> ReadToken();
|
||||
|
||||
bool TryReadToken(
|
||||
out Token<TLabel> t
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="ISyntaxNode"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.Collections;
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.Abstraction
|
||||
{
|
||||
public interface ISyntaxNode<TNode, TLabel> where TNode : ISyntaxNode<TNode, TLabel>
|
||||
where TLabel : unmanaged
|
||||
{
|
||||
|
||||
long NodeFlag { get; }
|
||||
|
||||
string CodeConvertTemplate { get; }
|
||||
|
||||
TLabel EqualityTypeConvert { get; }
|
||||
|
||||
TNode Previous { get; set; }
|
||||
|
||||
TNode Next { get; set; }
|
||||
|
||||
TNode Left { get; }
|
||||
|
||||
TNode Right { get; }
|
||||
|
||||
static abstract TNode Empty { get; }
|
||||
|
||||
Token<TLabel> Source { get; }
|
||||
|
||||
void AppendNode(
|
||||
TNode nextToken
|
||||
);
|
||||
|
||||
void PrependNode(
|
||||
TNode previousNode
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="Token"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.Abstraction
|
||||
{
|
||||
public readonly struct Token<TLabel> where TLabel : unmanaged
|
||||
{
|
||||
|
||||
private static readonly Token<TLabel> EmptyToken = new Token<TLabel>();
|
||||
|
||||
public readonly int Column;
|
||||
public readonly int Line;
|
||||
public readonly string Value;
|
||||
public readonly TLabel Flag;
|
||||
|
||||
public Token(
|
||||
string chars,
|
||||
int lineNumber,
|
||||
int columnNumber,
|
||||
TLabel flag
|
||||
)
|
||||
{
|
||||
Value = chars;
|
||||
Line = lineNumber;
|
||||
Column = columnNumber;
|
||||
Flag = flag;
|
||||
}
|
||||
|
||||
public static Token<TLabel> Empty => EmptyToken;
|
||||
|
||||
public override bool Equals(
|
||||
[NotNullWhen(true)] object? obj
|
||||
)
|
||||
{
|
||||
return base.Equals(obj);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Token<TLabel> ReLocate(
|
||||
int line,
|
||||
int column
|
||||
)
|
||||
{
|
||||
return new Token<TLabel>(Value, line, column, Flag);
|
||||
}
|
||||
|
||||
public static bool operator !=(
|
||||
Token<TLabel> left,
|
||||
Token<TLabel> right
|
||||
)
|
||||
{
|
||||
return left.Value.SequenceEqual(right.Value) &&
|
||||
left.Line == right.Line &&
|
||||
left.Column == right.Column &&
|
||||
left.Flag.Equals(right.Flag);
|
||||
}
|
||||
|
||||
public static bool operator ==(
|
||||
Token<TLabel> left,
|
||||
Token<TLabel> right
|
||||
)
|
||||
{
|
||||
return left.Value.SequenceEqual(right.Value) ||
|
||||
left.Line != right.Line ||
|
||||
left.Column != right.Column ||
|
||||
!(left.Flag.Equals(right.Flag));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
using StgSharp.RegularAnalysis.Abstraction;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.RegularAST
|
||||
{
|
||||
internal class RegularAST : AbstractSyntaxTree<RegularSyntaxNode, RegularType> { }
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="SequenceElementType"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.RegularAnalysis.Abstraction;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.RegularAST
|
||||
{
|
||||
internal class SequenceElementType<T> : ITypeSource<SequenceElementType<T>>
|
||||
where T : unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
public bool IsConvertable(
|
||||
SequenceElementType<T> targetType
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -36,9 +36,11 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis
|
||||
{
|
||||
internal class RegularBranchNode : RegularStateNode
|
||||
internal sealed class RegularBranchNode : RegularStateNode
|
||||
{
|
||||
|
||||
private int _afterBranch;
|
||||
|
||||
private int _lastBranch;
|
||||
|
||||
private List<BranchMeasureResult> _result;
|
||||
@@ -59,15 +61,26 @@ namespace StgSharp.RegularAnalysis
|
||||
out int label
|
||||
)
|
||||
{
|
||||
int pos = context.LastBranch.Peek();
|
||||
if (AvailableNodes.Length > _lastBranch)
|
||||
if (context.StateCode == 0)
|
||||
{
|
||||
// return measure result
|
||||
label = 0;
|
||||
// branch match
|
||||
label = _afterBranch;
|
||||
_ = context.LastBranch.Pop();
|
||||
_lastBranch = 0;
|
||||
return true;
|
||||
}
|
||||
label = FailNodeIndex;
|
||||
return false;
|
||||
|
||||
// restore sequence position
|
||||
int pos = context.LastBranch.Peek();
|
||||
context.Position = pos;
|
||||
if (AvailableNodes.Length > _lastBranch)
|
||||
{
|
||||
label = FailNodeIndex;
|
||||
return false;
|
||||
}
|
||||
_lastBranch++;
|
||||
label = AvailableNodes[_lastBranch];
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis
|
||||
{
|
||||
internal class RegularSequenceNode : RegularStateNode
|
||||
internal sealed class RegularSequenceNode : RegularStateNode
|
||||
{
|
||||
|
||||
private string _sequence;
|
||||
@@ -17,20 +18,9 @@ namespace StgSharp.RegularAnalysis
|
||||
RegularStateNode former,
|
||||
RegularContext context
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TryTransaction(
|
||||
ReadOnlySpan<RegularStateNode> nodeSpan,
|
||||
RegularContext context,
|
||||
out int label
|
||||
)
|
||||
{
|
||||
int pos = context.Position + 1;
|
||||
if (true) { }
|
||||
label = -1;
|
||||
return false;
|
||||
return context.CurrentCharSpan[pos.._sequence.Length].SequenceEqual(_sequence);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -127,6 +127,8 @@ namespace StgSharp.RegularAnalysis
|
||||
|
||||
public int Position { get; set; } = -1;
|
||||
|
||||
public int StateCode { get; set; } = 0;
|
||||
|
||||
public ReadOnlySpan<char> CurrentCharSpan => Source.AsSpan()[Begin..Position];
|
||||
|
||||
public string Source { get; init; }
|
||||
|
||||
@@ -10,4 +10,8 @@
|
||||
<ProjectReference Include="..\StgSharp.Common\StgSharp.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Abstraction\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="RegexAstLabel"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.TextRegex
|
||||
{
|
||||
internal enum RegexAstLabel
|
||||
{
|
||||
|
||||
CHAR,
|
||||
CHAR_SET,
|
||||
GROUP_NAME,
|
||||
GROUP_BEGIN,
|
||||
GROUP_END,
|
||||
COUNT,
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="RegexLexer"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.RegularAnalysis.Abstraction;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.TextRegex
|
||||
{
|
||||
internal class RegexLexer : IScriptTokenReader<RegexAstLabel>
|
||||
{
|
||||
|
||||
private static string _source;
|
||||
|
||||
private int position = 0;
|
||||
|
||||
public bool IsEmpty => string.IsNullOrEmpty(_source) || position >= _source.Length;
|
||||
|
||||
public Token<RegexAstLabel> ReadToken()
|
||||
{
|
||||
int pos = position;
|
||||
switch (_source[pos])
|
||||
{
|
||||
case '\\':
|
||||
if (pos + 1 == _source.Length) {
|
||||
throw new InvalidOperationException("Unclosed char");
|
||||
}
|
||||
position = pos + 2;
|
||||
return new Token<RegexAstLabel>(_source[(pos)..(pos + 2)], 0, pos,
|
||||
RegexAstLabel.CHAR);
|
||||
case '[':
|
||||
for (int i = pos + 1; i < _source.Length; i++)
|
||||
{
|
||||
if (_source[i] == ']' && _source[i - 1] != '\\')
|
||||
{
|
||||
int length = (i - pos - 1);
|
||||
position = i + 1;
|
||||
return new Token<RegexAstLabel>(_source[(pos - 1)..(i - 1)], 0,
|
||||
position, RegexAstLabel.CHAR_SET);
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException("Unclosed character set");
|
||||
case '(':
|
||||
|
||||
// very comlex here
|
||||
return ReadGroupBeginToken();
|
||||
case ')':
|
||||
position = pos + 1;
|
||||
return new Token<RegexAstLabel>(_source[(pos)..1], 0, pos,
|
||||
RegexAstLabel.GROUP_END);
|
||||
case '{':
|
||||
for (int i = pos + 1; i < _source.Length; i++)
|
||||
{
|
||||
if (_source[i] == '}')
|
||||
{
|
||||
position = i + 1;
|
||||
return new Token<RegexAstLabel>(_source[(pos)..(i - 1)], 0, pos,
|
||||
RegexAstLabel.COUNT);
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException("Unclosed count specifier");
|
||||
case '*' or '+':
|
||||
int count = _source[pos + 1] == '?' ? 2 : 1;
|
||||
position = pos + count;
|
||||
return new Token<RegexAstLabel>(_source[(pos)..(pos + count)], 0, pos,
|
||||
RegexAstLabel.COUNT);
|
||||
case '?':
|
||||
position = pos + 1;
|
||||
return new Token<RegexAstLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||
RegexAstLabel.COUNT);
|
||||
case '.':
|
||||
return new Token<RegexAstLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||
RegexAstLabel.CHAR_SET);
|
||||
default:
|
||||
position = pos + 1;
|
||||
return new Token<RegexAstLabel>(_source[(pos)..(pos + 1)], 0, pos,
|
||||
RegexAstLabel.CHAR);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryReadToken(
|
||||
out Token<RegexAstLabel> t
|
||||
)
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
t = Token<RegexAstLabel>.Empty;
|
||||
return false;
|
||||
}
|
||||
t = ReadToken();
|
||||
return Token<RegexAstLabel>.Empty == t;
|
||||
}
|
||||
|
||||
private Token<RegexAstLabel> ReadGroupBeginToken()
|
||||
{
|
||||
if (_source is null) {
|
||||
throw new InvalidOperationException("Source is null.");
|
||||
}
|
||||
|
||||
int start = position;
|
||||
|
||||
if (start >= _source.Length || _source[start] != '(') {
|
||||
throw new InvalidOperationException("ReadGroupBeginToken called when current char is not '('.");
|
||||
}
|
||||
|
||||
// Case 1: plain capturing group "("
|
||||
if (start + 1 >= _source.Length || _source[start + 1] != '?')
|
||||
{
|
||||
position = start + 1;
|
||||
return new Token<RegexAstLabel>("(", 0, start, RegexAstLabel.GROUP_BEGIN);
|
||||
}
|
||||
|
||||
// From here we have "(?"
|
||||
if (start + 2 >= _source.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Unfinished group prefix '(?'.");
|
||||
}
|
||||
|
||||
char c2 = _source[start + 2];
|
||||
|
||||
// Case 2: non-capturing group "(?:"
|
||||
if (c2 == ':')
|
||||
{
|
||||
position = start + 3;
|
||||
return new Token<RegexAstLabel>("(?:", 0, start, RegexAstLabel.GROUP_BEGIN);
|
||||
}
|
||||
|
||||
// Assertions (write the first-level cases, but not supported yet)
|
||||
if (c2 == '=')
|
||||
{
|
||||
// "(?="
|
||||
position = start + 3;
|
||||
throw new NotSupportedException("Positive lookahead '(?=...)' is not supported yet.");
|
||||
}
|
||||
if (c2 == '!')
|
||||
{
|
||||
// "(?!"
|
||||
position = start + 3;
|
||||
throw new NotSupportedException("Negative lookahead '(?!...)' is not supported yet.");
|
||||
}
|
||||
|
||||
// Named capturing group or lookbehind starts with "(?<"
|
||||
if (c2 == '<')
|
||||
{
|
||||
if (start + 3 >= _source.Length) {
|
||||
throw new InvalidOperationException("Unfinished group prefix '(?<'.");
|
||||
}
|
||||
|
||||
char c3 = _source[start + 3];
|
||||
|
||||
// Lookbehind prefixes: "(?<=" and "(?<!"
|
||||
if (c3 == '=')
|
||||
{
|
||||
position = start + 4;
|
||||
throw new NotSupportedException("Positive lookbehind '(?<=...)' is not supported yet.");
|
||||
}
|
||||
if (c3 == '!')
|
||||
{
|
||||
position = start + 4;
|
||||
throw new NotSupportedException("Negative lookbehind '(?<!...)' is not supported yet.");
|
||||
}
|
||||
|
||||
// Otherwise: "(?<name>"
|
||||
int nameStart = start + 3;
|
||||
|
||||
// Read name until '>'
|
||||
int i = nameStart;
|
||||
|
||||
// Name must start with [A-Za-z_]
|
||||
if (i >= _source.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Unfinished named group prefix.");
|
||||
}
|
||||
|
||||
char first = _source[i];
|
||||
if (!(first == '_' || char.IsLetter(first))) {
|
||||
throw new InvalidOperationException($"Invalid named group name start '{first}' at position {i}.");
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
while (i < _source.Length)
|
||||
{
|
||||
char ch = _source[i];
|
||||
if (ch == '>')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(ch == '_' || char.IsLetterOrDigit(ch))) {
|
||||
throw new InvalidOperationException($"Invalid character '{ch}' in group name at position {i}.");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= _source.Length || _source[i] != '>') {
|
||||
throw new InvalidOperationException("Unclosed named group prefix; missing '>'.");
|
||||
}
|
||||
|
||||
// Consume "(?<name>"
|
||||
int consumedLen = (i - start) + 1; // include '>'
|
||||
string text = _source.Substring(start, consumedLen);
|
||||
position = start + consumedLen;
|
||||
|
||||
return new Token<RegexAstLabel>(text, 0, start, RegexAstLabel.GROUP_BEGIN);
|
||||
}
|
||||
|
||||
// Optional: comments "(?#...)" or inline options "(?i:...)" etc.
|
||||
// First-level cases listed but not supported yet:
|
||||
if (c2 == '#')
|
||||
{
|
||||
position = start + 3;
|
||||
throw new NotSupportedException("Comment group '(?#...)' is not supported yet.");
|
||||
}
|
||||
|
||||
// Inline options: (?i:...), (?m:...), (?-i:...), (?im), etc.
|
||||
// Too many dialect differences; reserve the prefix but mark unsupported.
|
||||
if (char.IsLetter(c2) || c2 == '-')
|
||||
{
|
||||
// We don't know how long the option spec is here; do NOT advance position too much.
|
||||
// Keep position at '(' so caller can decide how to handle, or just throw.
|
||||
position = start;
|
||||
throw new NotSupportedException("Inline option groups like '(?i:...)' are not supported yet.");
|
||||
}
|
||||
|
||||
// Unknown "(?X" prefix
|
||||
position = start;
|
||||
throw new InvalidOperationException($"Unknown or unsupported group prefix starting at position {start}: '{_source.Substring(start, Math.Min(4, _source.Length - start))}'");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user