This commit is contained in:
Nitload
2025-08-25 09:50:30 +08:00
parent bd0e31e922
commit 1359ff4ecc
1630 changed files with 738486 additions and 2399 deletions
@@ -0,0 +1,290 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepExpSyntaxAnalyzer.Common.cs"
// 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 Microsoft.CodeAnalysis.CSharp.Syntax;
using StgSharp.Script;
using StgSharp.Script.Express;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Schema;
using ExpKeyword = StgSharp.Script.Express.ExpressCompile.Keyword;
namespace StgSharp.Modeling.Step
{
public partial class StepExpSyntaxAnalyzer
{
private bool IsSeparatorMatch( Token leftSperator, Token rightSeparator )
{
return leftSperator.Value switch
{
ExpKeyword.LeftBrace => rightSeparator.Value == ExpKeyword.RightBrace,
ExpKeyword.LeftParen => rightSeparator.Value == ExpKeyword.RightParen,
ExpKeyword.Comma => rightSeparator.Value == ExpKeyword.Comma,
ExpKeyword.Semicolon => rightSeparator.Value == ExpKeyword.Semicolon,
_ => false
};
}
private bool TryAppendIndexLeft( Token t )
{
if( t.Flag != TokenFlag.Index_Left ) {
return false;
}
if( _cache.TryPeekOperand( out bool isNode, out _, out ExpNode? node ) )
{
if( node.EqualityTypeConvert is not ExpCollectionBase ) {
ExpInvalidSyntaxException.ThrowNonCollectionIndex( t );
}
}
_cache.PushOperator( t );
_cache.IncreaseDepth( ( int )ExpCompileStateCode.CollectionIndex );
return true;
}
private bool TryAppendIndexRight( Token t )
{
if( t.Flag != TokenFlag.Index_Right ) {
return false;
}
//reverse building
ClosePrefixReverse( t );
//make index node
_cache.PopOperand( out _, out ExpNode? expNode );
if( !_cache.PopOperand( out Token colleToken, out ExpNode? colleNode ) ) { }
_cache.PushOperand(
ExpCollectionIndexNode.Create(
t, ( colleNode as ExpCollectionInstanceBase )!, expNode ) );
return true;
}
private bool TryAppendMember( Token t )
{
if( t.Flag != TokenFlag.Member ) {
return false;
}
if( TryParseConstant( t ) ) {
return true;
}
if( TryParseFunction( t ) ) {
return true;
}
if( TryParseInstance( t ) ) {
return true;
}
if( TryParseKeyword( t ) ) {
return true;
}
if( TryParseElementName( t ) ) {
return true;
}
//Many thing miss here
_cache.PushOperand( ExpElementMemberNameNode.Create( t ) );
return true;
}
private bool TryAppendMiddleSeparator( Token t )
{
if( t.Flag != TokenFlag.Separator_Middle ) {
return false;
}
while( _cache.OperatorAheadOfDepth > 0 )
{
_cache.TryPopOperator( out Token op );
ExpNode node = ConvertAndPushOneOperator( op );
}
switch( _cache.OperandAheadOfDepth )
{
case 0:
if( t.Value == ";" ) {
return true;
}
_cache.StatementsInDepth.Push( ExpNode.Empty );
goto case 1;
case 1:
_cache.PopOperand( out _, out ExpNode? statement );
_cache.StatementsInDepth.Push( statement );
return true;
default:
ExpInvalidSyntaxException.ThrowNoOperator( t );
break;
}
return true;
}
private bool TryAppendNumAndStrLiteral( Token t )
{
if( ( t.Flag & ( TokenFlag.String | TokenFlag.Number ) ) == 0 ) {
return false;
}
_cache.PushOperand( ExpElementInstance.CreateLiteral( t ) );
return true;
}
private bool TryAppendPrefixSeparator( Token t )
{
if( t.Flag != TokenFlag.Separator_Left ) {
return false;
}
_cache.PushOperator( t );
_cache.IncreaseDepth( ( int )ExpCompileStateCode.Common );
return true;
}
private bool TryAppendPrefixSeparatorEnd( Token t )
{
if( t.Flag != TokenFlag.Separator_Right ) {
return false;
}
ClosePrefixReverse( t );
return true;
}
private bool TryAppendSymbol( Token t )
{
if( ( t.Flag & ( TokenFlag.Symbol_Unary | TokenFlag.Symbol_Binary ) ) == 0 ) {
return false;
}
int cmp = -1;
processPrecedence:
if( _cache.TryPeekOperator( out Token tmp ) )
{
cmp = CompareOperatorPrecedence( t, tmp );
if( cmp >= 0 )
{
_cache.PopOperator();
ExpNode node = ConvertAndPushOneOperator( tmp );
goto processPrecedence;
}
}
_cache.PushOperator( t );
return true;
}
private bool TryParseConstant( Token t )
{
switch( t.Value )
{
case ExpKeyword.E:
_cache.PushOperand( new ExpRealNumberNode( t, MathF.E, true ) );
return true;
case ExpKeyword.Pi:
_cache.PushOperand( new ExpRealNumberNode( t, MathF.PI, true ) );
return true;
default:
if( ExpElementInstance.TryCreateLiteral( t, out ExpElementInstance? node ) )
{
_cache.PushOperand( node );
return true;
}
return false;
}
}
private bool TryParseElementName( Token t )
{
if( _context.TryGetType( t.Value, out ExpTypeSource? type ) )
{
_cache.PushOperand( ExpMetaRefNode.RefType( t, type ) );
return true;
}
if( _context.TryGetEntity( t.Value, out ExpEntitySource? entity ) )
{
_cache.PushOperand( ExpMetaRefNode.RefEntity( t, entity ) );
return true;
}
return false;
}
private bool TryParseFunction( Token t )
{
if( ExpKeyword.BuiltinFunctions.Contains( t.Value ) )
{
_cache.PushOperator( t );
return true;
} else if( _context.TryGetFunction( t.Value, out ExpFunctionSource? f ) )
{
_cache.PushOperand( t );
return true;
}
return false;
}
private bool TryParseInstance( Token t )
{
if( _local.TryGetMember( t.Value,
out ExpNode? node ) && node is ExpElementInstance instance )
{
_cache.PushOperand( ExpInstanceReferenceNode.MakeReferenceFrom( t, instance ) );
return true;
} else if( _cache.IsLastAddedOperator )
{
if( _cache.PeekOperand( out _,
out ExpNode? typenode ) && typenode is ExpMetaRefNode typeRef )
{
_cache.PopOperand( out _, out _ );
_local.AddMember( t.Value, typeRef.SourceRef.CreateInstanceNode( t ) );
} else
{
return false;
}
}
return false;
}
private bool TryParseKeyword( Token t )
{
switch( t.Value )
{
case ExpKeyword.Return:
_cache.PushOperator( t );
return true;
case ExpKeyword.Skip:
_cache.PushOperand( ExpProcedureControlNode.Skip( t ) );
return true;
default:
return false;
}
}
}
}
@@ -0,0 +1,56 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="ExpSyntaxAnalyzer.ErrorProcess.cs"
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.Modeling.Step
{
public partial class StepExpSyntaxAnalyzer
{
public void ThrowCompileException( int errorCode )
{
switch( errorCode )
{
case 0 or 1:
return;
case TokenTypeNotMatch:
throw new Exception();
default:
break;
}
}
}
}
@@ -0,0 +1,184 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="ExpSyntaxAnalyzer.OperatorParser.cs"
// 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 StgSharp.Script;
using StgSharp.Script.Express;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExpKeyword = StgSharp.Script.Express.ExpressCompile.Keyword;
namespace StgSharp.Modeling.Step
{
public partial class StepExpSyntaxAnalyzer
{
public int CompareOperatorPrecedence( Token left, Token right )
{
ExpressCompile.TryGetOperatorPrecedence( left.Value, out int leftPrecedence );
ExpressCompile.TryGetOperatorPrecedence( right.Value, out int rightPrecedence );
return leftPrecedence - rightPrecedence;
}
public bool TryGenerateUnaryNode( Token t, out ExpNode node )
{
ExpNode operand = GetNextOperandCache();
switch( t.Value )
{
case ExpKeyword.UnaryPlus:
node = ExpUnaryOperatorNode.UnaryPlus( t, operand );
return true;
case ExpKeyword.UnaryMinus:
node = ExpUnaryOperatorNode.UnaryMinus( t, operand );
return true;
case ExpKeyword.Not:
node = ExpUnaryOperatorNode.UnaryNot( t, operand );
return true;
default:
node = ExpNode.Empty;
return false;
}
}
/// <summary>
/// WARNING: This method cannot process INDEXOF, FUNCTION CALLING, LOOP and any ENDING
/// SYMBOLS.
/// </summary>
private ExpNode ConvertAndPushOneOperator( Token op )
{
switch( op.Flag )
{
case TokenFlag.Symbol_Unary:
TryGenerateUnaryNode( op, out ExpNode? node );
_cache.PushOperand( node );
return node;
case TokenFlag.Symbol_Binary:
TryGenerateBinaryNode( op, out node );
_cache.PushOperand( node );
return node;
case TokenFlag.Member:
if( _context.TryGetFunction( op.Value, out ExpFunctionSource? f ) )
{
if( !_cache.PopOperand( out Token t, out ExpNode? p ) )
{
node = ExpFunctionCallingNode.CallFunction( op, f, p );
return node;
} else
{
throw new ExpCompileException(
t,
"An ExpNode for function calling is needed, but a token was popped" );
}
} else if( _context.TryGetProcedure( op.Value, out ExpProcedureSource? p ) )
{
if( !_cache.PopOperand( out Token t, out ExpNode? param ) )
{
node = ExpProcedureCallingNode.CallProcedure( op, p, param );
return node;
} else
{
throw new ExpCompileException(
t,
"An ExpNode for function calling is needed, but a token was popped" );
}
} else if( ExpSchema.BuiltinSchema.TryGetFunction( op.Value, out f ) )
{
if( !_cache.PopOperand( out Token t, out ExpNode? param ) )
{
node = ExpFunctionCallingNode.CallFunction( op, f, param );
return node;
} else
{
throw new ExpCompileException(
t,
"An ExpNode for function calling is needed, but a token was popped" );
}
} else
{
throw new NotImplementedException();
//uncertain case here
}
default:
throw new NotImplementedException();
}
}
private bool TryGenerateBinaryNode( Token t, out ExpNode node )
{
ExpNode right = GetNextOperandCache();
ExpNode left = GetNextOperandCache();
switch( t.Value )
{
case ExpKeyword.Add:
node = ExpBinaryOperatorNode.Add( t, left, right );
return true;
case ExpKeyword.Sub:
node = ExpBinaryOperatorNode.Sub( t, left, right );
return true;
case ExpKeyword.Mul:
node = ExpBinaryOperatorNode.Mul( t, left, right );
return true;
case ExpKeyword.Div:
node = ExpBinaryOperatorNode.Div( t, left, right );
return true;
case ExpKeyword.Equal:
node = ExpBinaryOperatorNode.EqualTo( t, left, right );
return true;
case ExpKeyword.NotEqual:
node = ExpBinaryOperatorNode.NotEqualTo( t, left, right );
return true;
case ExpKeyword.GreaterThan:
node = ExpBinaryOperatorNode.GreaterThan( t, left, right );
return true;
case ExpKeyword.LessThan:
node = ExpBinaryOperatorNode.LessThan( t, left, right );
return true;
case ExpKeyword.Assignment:
node = ExpBinaryOperatorNode.Assign( t, left, right );
return true;
case ExpKeyword.InstanceEqual:
node = ExpBinaryOperatorNode.CompareInstanceEqual( t, left, right );
return true;
case ExpKeyword.InstanceNotEqual:
node = ExpBinaryOperatorNode.CompareInstanceNotEqual( t, left, right );
return true;
default:
node = ExpNode.Empty;
return false;
}
}
}
}
@@ -0,0 +1,85 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepExpSyntaxAnalyzer.PrefixReverseAnalysing.cs"
// 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 StgSharp.Script;
using StgSharp.Script.Express;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExpKeyword = StgSharp.Script.Express.ExpressCompile.Keyword;
namespace StgSharp.Modeling.Step
{
public partial class StepExpSyntaxAnalyzer
{
private void ClosePrefixReverse( Token rightSeparator )
{
Token op;
ExpNode root;
if( _cache.OperatorAheadOfDepth == 0 )
{
if( _cache.OperandAheadOfDepth == 1 )
{
_cache.PopOperand( out _, out ExpNode? statement );
_cache.StatementsInDepth.Push( statement );
} else
{
ExpInvalidSyntaxException.ThrowNoOperator( rightSeparator );
}
} else
{
while( _cache.TryPopOperator( out op ) ) {
ConvertAndPushOneOperator( op );
}
_cache.PopOperand( out _, out root );
_cache.StatementsInDepth.Push( root );
}
root = _cache.PackAllStatements();
_cache.DecreaseDepth();
if( IsSeparatorMatch( _cache.PeekOperator(), rightSeparator ) )
{
_cache.PopOperator();
_cache.PushOperand( root );
} else
{
throw new ExpCompileException(
rightSeparator, "Ending of block does not match its begging" );
}
}
}
}
@@ -0,0 +1,145 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepExpSyntaxAnalyzer.cs"
// 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 Microsoft.CodeAnalysis.CSharp.Syntax;
using StgSharp.Script;
using StgSharp.Script.Express;
using StgSharp.Threading;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExpKeyword = StgSharp.Script.Express.ExpressCompile.Keyword;
namespace StgSharp.Modeling.Step
{
public partial class StepExpSyntaxAnalyzer : ISyntaxAnalyzer
{
private const int EndLine = 1;
private const int TokenGenerated = 0;
private const int TokenTypeNotMatch = -1;
private CompileStack<ExpNode, IExpElementSource> _cache;
private ExpNode _lastStatement;
private ExpSchema _context;
private IExpElementSource _local;
public StepExpSyntaxAnalyzer()
{
_cache = new CompileStack<ExpNode, IExpElementSource>();
}
public StepExpSyntaxAnalyzer( ExpSchema context, IExpElementSource local )
{
_cache = new CompileStack<ExpNode, IExpElementSource>();
ArgumentNullException.ThrowIfNull( context );
if( context is not ExpSchema_Builtin )
{
_context = context;
} else
{
throw new InvalidCastException( "Not a valid Schema type" );
}
_local = local;
}
/// <summary>
/// Append a token to top of cache. This method will automatically convert token to node
/// if meets separators or operators.
/// </summary>
public void AppendToken( Token expToken )
{
switch( expToken.Flag )
{
case TokenFlag.Symbol_Unary or TokenFlag.Symbol_Binary:
TryAppendSymbol( expToken );
break;
case TokenFlag.Number or TokenFlag.String:
ExpElementInstance node = ExpElementInstance.CreateLiteral( expToken );
_cache.PushOperand( node );
break;
case TokenFlag.Separator_Left:
TryAppendPrefixSeparator( expToken );
break;
case TokenFlag.Separator_Right:
TryAppendPrefixSeparatorEnd( expToken );
break;
case TokenFlag.Separator_Middle:
TryAppendMiddleSeparator( expToken );
break;
case TokenFlag.Index_Left:
TryAppendIndexLeft( expToken );
break;
case TokenFlag.Index_Right:
TryAppendIndexRight( expToken );
break;
case TokenFlag.Member:
TryAppendMember( expToken );
break;
default:
break;
}
}
public ExpNode GetNextOperandCache()
{
if( _cache.PopOperand( out Token t, out ExpNode? n ) )
{
return n;
} else
{
// process some rare case here
}
throw new NotImplementedException();
}
public enum ExpCompileStateCode
{
Common,
ForLoop,
RepeatLoop,
UntilLoop,
IfBranch,
CaseBranch,
CollectionIndex,
}
}
}
@@ -0,0 +1,90 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepDataReader.cs"
// 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.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.Modeling.STEP
{
public partial class StepReader
{
private Regex expressionSpilitter = GetExpressionSplitter();
private ThreadLocal<ConcurrentQueue<StepCodeLine>> _codeLineQueue
= new ThreadLocal<ConcurrentQueue<StepCodeLine>>();
public ConcurrentQueue<StepCodeLine> DataSectionPool
{
get => _codeLineQueue.Value;
}
public void ReadDataSection()
{
if( _codeLineQueue.Value == null ) {
_codeLineQueue.Value = new ConcurrentQueue<StepCodeLine>();
}
using( MemoryMappedViewStream ms = _memoryFile.CreateViewStream(
0, _size, MemoryMappedFileAccess.Read ) )
{
using( StreamReader sr = new StreamReader( ms ) )
{
long pos = _headStart;
string line;
while( string.IsNullOrEmpty( line = sr.ReadLine()! ) )
{
Match match = expressionSpilitter.Match( line );
if( match.Success )
{
int id = int.Parse( match.Groups[ "id" ].Value );
string expression = match.Groups[ "expression" ].Value;
StepCodeLine stepExpression = new StepCodeLine( id, expression );
_codeLineQueue.Value.Enqueue( stepExpression );
}
}
}
}
}
[GeneratedRegex(
@"^#(?<id>[0-9]+)\s*?=\s*?(?<expression>\S.*?)\s*;$",
RegexOptions.Compiled | RegexOptions.Singleline )]
private static partial Regex GetExpressionSplitter();
}
}
@@ -0,0 +1,143 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepDataSectionTokenReader.cs"
// 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 StgSharp.Modeling.Step;
using StgSharp.Script;
using StgSharp.Script.Express;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.Modeling.Step
{
public class StepDataSectionTokenReader : IScriptTokenReader
{
private ExpSourceReader _reader;
private Queue<Token> _cache = new Queue<Token>();
private StepDataSectionTransmitter _transmitter;
public StepDataSectionTokenReader( StepDataSectionTransmitter transmitter )
{
_reader = new ExpSourceReader( transmitter );
_transmitter = transmitter;
}
public Token ReadToken()
{
if( _cache.Count == 0 )
{
if( _reader.TryReadToken( out Token token0 ) && ( token0.Value != "." ) ) {
return token0;
}
if( _reader.TryReadToken( out Token token1 ) && ( token1.Value != "T" || token1.Value !=
"F" ) )
{
_cache.Enqueue( token1 );
return token0;
}
if( _reader.TryReadToken( out Token token2 ) && ( token2.Value != "." ) )
{
_cache.Enqueue( token1 );
_cache.Enqueue( token2 );
return token0;
}
switch( token1.Value )
{
case "T":
return new Token( ".T.", token0.Line, token1.Column, TokenFlag.Member );
case "F":
return new Token( ".F.", token0.Line, token1.Column, TokenFlag.Member );
default:
break;
}
}
return _cache.Dequeue();
}
public bool TryReadToken( out Token t )
{
if( _cache.Count == 0 )
{
if( _reader.TryReadToken( out Token token0 ) )
{
if( token0.Value != "." )
{
t = token0;
return true;
}
} else
{
t = Token.Empty;
return false;
}
if( _reader.TryReadToken( out Token token1 ) )
{
if( token1.Value != "T" || token1.Value != "F" )
{
_cache.Enqueue( token1 );
t = token0;
return true;
}
} else
{
t = Token.Empty;
return false;
}
if( _reader.TryReadToken( out Token token2 ) )
{
if( token2.Value != "." )
{
_cache.Enqueue( token1 );
_cache.Enqueue( token2 );
t = token0;
return true;
}
} else
{
t = Token.Empty;
return false;
}
t = token1.Value switch
{
"T" => new Token( ".T.", token0.Line, token1.Column, TokenFlag.Member ),
"F" => new Token( ".F.", token0.Line, token1.Column, TokenFlag.Member ),
_ => Token.Empty
};
}
return _reader.TryReadToken( out t );
}
}
}
@@ -0,0 +1,95 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepDataSectionsTranmitter.cs"
// 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 StgSharp.Script;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.Modeling.Step
{
public class StepDataSectionTransmitter : IScriptSourceProvider
{
private bool _isEmpty;
private ConcurrentQueue<string> _cache = new ConcurrentQueue<string>();
private int _line = 0;
public bool IsEmpty => _isEmpty;
public int Location => _line;
public void EndWriting()
{
_cache.Enqueue( "END_DATA" );
}
public string ReadLine()
{
_cache.TryDequeue( out string? line );
while( !IsEmpty )
{
if( _cache.TryDequeue( out line ) )
{
if( line == "END_DATA" )
{
_isEmpty = true;
return string.Empty;
}
_line++;
return line;
}
}
return string.Empty;
}
public string ReadLine( out int position )
{
string ret = ReadLine();
position = _line;
return ret;
}
public void WriteLine( string line )
{
_cache.Enqueue( line );
}
IScriptSourceProvider IScriptSourceProvider.Slice( int location, int count )
{
throw new NotSupportedException();
}
}
}
@@ -0,0 +1,112 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepDataTokenReader.cs"
// 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 StgSharp.Modeling.Step;
using StgSharp.Script;
using StgSharp.Script.Express;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace StgSharp.Modeling.Step
{
public class StepDataTokenReader : IScriptTokenReader
{
private ExpTokenReader _reader;
private HashSet<string> token1Hash = [
"T","F","UNSPECIFIED"
];
private Queue<Token> _cache = new Queue<Token>();
private StepDataSectionTransmitter _transmitter;
public StepDataTokenReader( StepDataSectionTransmitter transmitter )
{
_reader = new ExpTokenReader( transmitter );
_reader.TokenReaderPreProcessor = new TokenPreReader();
_transmitter = transmitter;
}
public Token ReadToken()
{
return _reader.ReadToken();
}
public bool TryReadToken( out Token t )
{
return _reader.TryReadToken( out t );
}
private class TokenPreReader : ExpTokenReaderPreProcessor
{
private static Regex NextEnumPattern = GetNextEnumPattern();
public override bool Process( string codeLine, int line, ref int current, out Token t )
{
ReadOnlySpan<char> chars = codeLine.AsSpan( current );
char c = chars[ 0 ];
if( c != '.' )
{
t = Token.Empty;
return false;
}
Match match = NextEnumPattern.Match( codeLine, current );
if( match.Success )
{
int begin = match.Groups[ "begin" ].Index;
int end = match.Groups[ "end" ].Length;
int rest = match.Groups[ "rets" ].Length;
current = rest;
t = new Token( match.Groups[ "begin" ].Value, line, begin, TokenFlag.Enum );
return true;
} else
{
t = Token.Empty;
return false;
}
}
[GeneratedRegex(
@"(?<begin>\.[A-Za-z_]+\.)(?<end>\s*)(?<rest>\S*)",
RegexOptions.Singleline )]
private static extern Regex GetNextEnumPattern();
}
}
}
@@ -0,0 +1,57 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepExpressParser.cs"
// 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 StgSharp.Modeling.Step;
using StgSharp.Script;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.Modeling.Step
{
public class StepExpressSyntaxParser : ISyntaxAnalyzer
{
private StepExpSyntaxAnalyzer _analyzer;
public StepExpressSyntaxParser()
{
_analyzer = new StepExpSyntaxAnalyzer();
}
public void AppendToken( Token t )
{
}
}
}
@@ -0,0 +1,112 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepHeadReader.cs"
// 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.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace StgSharp.Modeling.STEP
{
public partial class StepReader
{
/**/
private static Regex expressionSplitter = new Regex(
@"^(?<CALLER>[A-Z_]+)\s?\((?<PARAM>.+)\)\;",
RegexOptions.Compiled );
public StepInfo GetInfo()
{
StepInfo info = new StepInfo();
List<StepObjectConstructor> constructorList = new List<StepObjectConstructor>();
using( MemoryMappedViewStream ms = _memoryFile.CreateViewStream(
0, _size, MemoryMappedFileAccess.Read ) ) {
using( StreamReader sr = new StreamReader( ms ) ) {
long pos = _headStart;
ms.Seek( _headStart, SeekOrigin.Begin );
while( pos <= _headEnd ) {
string token = ReadToken( sr, ref pos );
if( token == "HEADER;" ) {
continue;
}
if( token == "ENDSEC;" ) {
break;
}
GroupCollection match = expressionSplitter.Match(
token )
.Groups;
constructorList.Add(
new StepObjectConstructor(
0, match[ "CALLER" ].ToString(),
match[ "PARAM" ].ToString() ) );
}
foreach( StepObjectConstructor constructor in constructorList ) {
switch( constructor.Caller ) {
case "FILE_DESCRIPTION":
info.Description = StepDataParser.ToString(
constructor[ 0 ] );
info.Level = StepDataParser.ToVersion(
constructor[ 1 ] );
break;
case "FILE_NAME":
info.Name = StepDataParser.ToString(
constructor[ 0 ] );
info.TimeStamp = StepDataParser.ToDateTime(
constructor[ 1 ] );
info.Author = StepDataParser.ToString(
constructor[ 2 ] );
info.Organization = StepDataParser.ToString(
constructor[ 3 ] );
info.PreprocessorVersion = StepDataParser.ToString(
constructor[ 4 ] );
info.OriginatingSystem = StepDataParser.ToString(
constructor[ 5 ] );
info.Authorization = StepDataParser.ToString(
constructor[ 6 ] );
break;
default:
break;
}
}
}
}
return info;
}
/**/
}
}
+158
View File
@@ -0,0 +1,158 @@
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="StepReader.cs"
// 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 StgSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace StgSharp.Modeling.STEP
{
public partial class StepReader : IDisposable
{
private const string fileLabel = "ISO-10303-21;";
private bool disposedValue;
private FileStream _fileStream;
private long _headStart = -1, _headEnd = -1, _dataStart = -1, _size;
private MemoryMappedFile _memoryFile;
private StepReader() { }
private StepReader( FileStream stream, long size )
{
_fileStream = stream;
_size = size;
_memoryFile = MemoryMappedFile.CreateFromFile(
stream, mapName: null, size, MemoryMappedFileAccess.Read,
HandleInheritability.None, leaveOpen: true );
}
// ~StepReader()
// {
// Dispose(disposing: false);
// }
public void Dispose()
{
Dispose( disposing: true );
GC.SuppressFinalize( this );
}
public static bool FromFile( string path, out StepReader reader )
{
FileInfo info = new FileInfo( path );
if( !info.Exists ) {
reader = null!;
return false;
}
FileStream stream = new FileStream(
path, FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true );
byte[] fileHead = new byte[40];
stream.Read( fileHead, 0, fileLabel.Length );
if( !Encoding.UTF8.GetString( fileHead ).Contains( fileLabel ) ) {
throw new InvalidDataException(
"The given file is not a STEP file" );
}
reader = new StepReader( stream, info.Length );
reader.LocateSection();
return reader != null;
}
private void LocateSection()
{
long startPos = 0;
byte[] buffer = new byte[1024];
Span<byte> bufferSpan = buffer,
headerSec = Encoding.UTF8.GetBytes( "HEADER;" ),
endsecSec = Encoding.UTF8.GetBytes( "ENDSEC;" ),
dataSec = Encoding.UTF8.GetBytes( "DATA;" );
_fileStream.Position = 0;
for( ; startPos < _size; startPos += 1000 ) {
_fileStream.Read( buffer );
if( _headStart == -1 ) {
long pos = bufferSpan.IndexOf( headerSec );
if( pos >= 0 ) {
_headStart = startPos + pos;
}
}
if( _headEnd == -1 ) {
long pos = bufferSpan.IndexOf( endsecSec );
if( pos >= 0 ) {
_headEnd = startPos + pos;
}
}
if( _dataStart == -1 ) {
long pos = bufferSpan.IndexOf( dataSec );
if( pos >= 0 ) {
_dataStart = startPos + pos;
}
} else {
break;
}
_fileStream.Seek( 1000, SeekOrigin.Current );
}
}
private string ReadToken( StreamReader reader, ref long posCache )
{
StringBuilder token = new StringBuilder( 100 );
while( token.Length == 0 || token[ token.Length - 1 ] != ';' ) {
string subString = reader.ReadLine();
if( subString == null ) {
break;
}
token.Append( subString.TrimStart() );
}
posCache += token.Length;
return token.ToString();
}
private protected virtual void Dispose( bool disposing )
{
if( !disposedValue ) {
if( disposing ) {
_fileStream.Dispose();
_memoryFile.Dispose();
}
disposedValue = true;
}
}
}
}