diff --git a/StgSharp.Script/Express/ExpAstNode/ExpRepeatNode.cs b/StgSharp.Script/Express/ExpAstNode/ExpRepeatNode.cs index bda6f1ea..3f2b7455 100644 --- a/StgSharp.Script/Express/ExpAstNode/ExpRepeatNode.cs +++ b/StgSharp.Script/Express/ExpAstNode/ExpRepeatNode.cs @@ -64,11 +64,11 @@ namespace StgSharp.Script.Express switch( ( ExpNodeFlag )variable.NodeFlag | ExpNodeFlag.BuiltinType_Any ) { case ExpNodeFlag.BuiltinType_Float: increment = new ExpLiteralGenericNode( - $"{name}_defaultIncrement", context, 1.0f ); + $"{name}_defaultIncrement", 1.0f ); break; case ExpNodeFlag.BuiltinType_Int: increment = new ExpLiteralGenericNode( - $"{name}_defaultIncrement", context, 1 ); + $"{name}_defaultIncrement", 1 ); break; default: throw new ExpInvalidTypeException( diff --git a/StgSharp.Script/Express/ExpAstNode/_ExpNode.cs b/StgSharp.Script/Express/ExpAstNode/_ExpNode.cs index 0f554fc9..e5b29316 100644 --- a/StgSharp.Script/Express/ExpAstNode/_ExpNode.cs +++ b/StgSharp.Script/Express/ExpAstNode/_ExpNode.cs @@ -133,7 +133,11 @@ namespace StgSharp.Script.Express { IExpElementSource tLeft = left.EqualityTypeConvert, tRight = right.EqualityTypeConvert; - if( tLeft == null || tRight == null ) { + if( tLeft is not ExpInstantiableElement tLeftIns || tRight is not ExpInstantiableElement tRightIns ) { + return false; + } + if( ExpInstantiableElement.IsNullOrVoid( tLeftIns ) || ExpInstantiableElement.IsNullOrVoid( + tLeftIns ) ) { return false; } return tLeft.IsConvertable( tRight ); diff --git a/StgSharp.Script/Express/NodeGenerator/ExpNodeGenerator.cs b/StgSharp.Script/Express/NodeGenerator/ExpNodeGenerator.cs index d88c5857..0b405d79 100644 --- a/StgSharp.Script/Express/NodeGenerator/ExpNodeGenerator.cs +++ b/StgSharp.Script/Express/NodeGenerator/ExpNodeGenerator.cs @@ -51,6 +51,7 @@ namespace StgSharp.Script.Express private GeneratedExpSchema _context; private IExpElementSource _local; private List _cache; + private Stack> _operands; private Stack _operandsNode; private Stack _operandsToken; private Stack _operators; @@ -58,25 +59,64 @@ namespace StgSharp.Script.Express public ExpNodeGenerator() { _operators = new Stack(); - _operandsToken = new Stack(); + _operands = new Stack>(); } + private TokenNodeStack CurrentOperands => _operands.Peek( + ); + /// /// Append a token to top of cache. This method will automatically convert token to node if /// meets separators or operators. /// - /// - public ExpNode AppendToken( Token expToken ) + public void AppendToken( Token expToken ) { switch( expToken.Flag ) { case TokenFlag.Symbol_Unary or TokenFlag.Symbol_Binary: - _operandsToken.Push( expToken ); + int cmp = -1; + processPrecedence: + Token tmp = _operators.Peek(); + cmp = CompareOperatorPrecedence( expToken, tmp ); + if( cmp <= 0 ) { + ConvertOneOperator(); + goto processPrecedence; + } + CurrentOperands.Push( expToken ); break; - case TokenFlag.Number or TokenFlag.String or TokenFlag.Member: + case TokenFlag.Number or TokenFlag.String or TokenFlag.Member: + CurrentOperands.Push( expToken ); break; - case TokenFlag.Separator_Single: // a , ; found + case TokenFlag.Separator_Single: //a , ; found + //if operator stack is not empty, convert all operators to node until meet a separator + Token t; + ExpNode n = _operandsNode.Peek(); + int count = 0; + processSection: + t = _operators.Peek(); + bool isEnd = expToken.Value switch + { + "," => ",[(".IndexOf( t.Value[ 0 ] ) != -1, + ";" => ";{".IndexOf( t.Value[ 0 ] ) != -1, + _ => false + }; + if( isEnd ) { + if( count == 0 ) { + ExpNode newNode = ExpNode.NonOperation( + string.Empty ); + newNode.AppendNode( n ); + } else { + ExpNode newNode = _operandsNode.Pop(); + newNode.AppendNode( n ); + CurrentOperands.Push( newNode ); + } + } else { + count++; + ConvertOneOperator(); + goto processSection; + } break; case TokenFlag.Separator_Left: //a ( [ { found + _operators.Push( expToken ); break; case TokenFlag.Separator_Right: //a } ] ) found break; @@ -91,30 +131,43 @@ namespace StgSharp.Script.Express public ExpNode GetNextOperandCache() { - if( _operandsNode.Count != 0 ) { - return _operandsNode.Pop(); + if( CurrentOperands.Pop( out Token t, out ExpNode? n ) ) { + return n; + } else { + //TODO convert token to a node } - if( _operandsToken.Count != 0 ) { - Token token = _operandsToken.Pop(); - } - return ExpNode.Empty; } - //ConvertOneOperator not finish + /// + /// WARNING: This method cannot process INDEXOF, FUNCTION CALLING, LOOP and any ENDING + /// SYMBOLS. + /// private void ConvertOneOperator() { Token @operator = _operators.Pop(); switch( @operator.Flag ) { case TokenFlag.Symbol_Unary: + TryGenerateUnaryNode( @operator, out ExpNode? node ); + CurrentOperands.Push( node ); break; case TokenFlag.Symbol_Binary: - break; - case TokenFlag.Index_Left: + TryGenerateBinaryNode( @operator, out node ); + CurrentOperands.Push( node ); break; default: break; } } + private void DecreaseOperandsStackDepth() + { + _operands.Pop(); + } + + private void IncreaseOperandsStackDepth() + { + _operands.Push( new TokenNodeStack() ); + } + } } diff --git a/StgSharp.Script/Express/NodeGenerator/GenerateOperatorToken.cs b/StgSharp.Script/Express/NodeGenerator/GenerateOperatorToken.cs new file mode 100644 index 00000000..a55def78 --- /dev/null +++ b/StgSharp.Script/Express/NodeGenerator/GenerateOperatorToken.cs @@ -0,0 +1,94 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="GenerateOperatorToken.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.Script.Express +{ + public partial class ExpNodeGenerator + { + + public int CompareOperatorPrecedence( Token left, Token right ) + { + ExpCompile.TryGetOperatorPrecedence( + left.Value, out int leftPrecedence ); + ExpCompile.TryGetOperatorPrecedence( + right.Value, out int rightPrecedence ); + return leftPrecedence - rightPrecedence; + } + + public bool TryGenerateBinaryNode( Token t, out ExpNode node ) + { + ExpNode left = GetNextOperandCache(); + ExpNode right = GetNextOperandCache(); + switch( t.Value ) { + case ExpCompile.KeyWord.ADD: + node = ExpBinaryOperatorNode.Add( left, right ); + return true; + case ExpCompile.KeyWord.SUB: + node = ExpBinaryOperatorNode.Sub( left, right ); + return true; + case ExpCompile.KeyWord.MUL: + node = ExpBinaryOperatorNode.Mul( left, right ); + return true; + case ExpCompile.KeyWord.DIV: + node = ExpBinaryOperatorNode.Div( left, right ); + return true; + default: + node = ExpNode.Empty; + return false; + } + } + + public bool TryGenerateUnaryNode( Token t, out ExpNode node ) + { + ExpNode operand = GetNextOperandCache(); + switch( t.Value ) { + case ExpCompile.KeyWord.UnaryPlus: + node = ExpUnaryOperatorNode.UnaryPlus( operand ); + return true; + case ExpCompile.KeyWord.UnaryMinus: + node = ExpUnaryOperatorNode.UnaryMinus( operand ); + return true; + case ExpCompile.KeyWord.NOT: + node = ExpUnaryOperatorNode.UnaryNot( operand ); + return true; + default: + node = ExpNode.Empty; + return false; + } + } + + } +} diff --git a/StgSharp.Script/IASTNode.cs b/StgSharp.Script/IASTNode.cs index de4b0b08..dcab775a 100644 --- a/StgSharp.Script/IASTNode.cs +++ b/StgSharp.Script/IASTNode.cs @@ -34,6 +34,7 @@ using StgSharp.Script.Express; using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; using System.Text; namespace StgSharp.Script @@ -79,6 +80,11 @@ namespace StgSharp.Script get; } + static abstract TNode Empty + { + get; + } + TType EqualityTypeConvert { get; diff --git a/StgSharp.Script/Token.cs b/StgSharp.Script/Token.cs index 299bbaa4..2130c705 100644 --- a/StgSharp.Script/Token.cs +++ b/StgSharp.Script/Token.cs @@ -39,6 +39,8 @@ namespace StgSharp.Script public readonly struct Token { + private static Token EmptyToken = new Token(); + public readonly int Column; public readonly int Line; public readonly string Value; @@ -56,6 +58,8 @@ namespace StgSharp.Script Flag = flag; } + public static Token Empty => EmptyToken; + } public enum TokenFlag : int diff --git a/StgSharp.Script/TokenNodeStack.cs b/StgSharp.Script/TokenNodeStack.cs new file mode 100644 index 00000000..13421ea7 --- /dev/null +++ b/StgSharp.Script/TokenNodeStack.cs @@ -0,0 +1,99 @@ +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// file="TokenNodeStack.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.Data; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.Script +{ + public class TokenNodeStack + where TNode: IASTNode + where TType: ITypeSource + { + + private Stack _isNode; + + private Stack _nodes; + private Stack _tokens; + + public TokenNodeStack() + { + _nodes = new Stack( 4 ); + _tokens = new Stack( 4 ); + _isNode = new Stack( 8 ); + } + + public int Count => _isNode.Count; + + public bool Peek( out Token t, TNode n ) + { + if( _isNode.Peek() ) { + n = _nodes.Peek(); + t = Token.Empty; + return true; + } else { + t = _tokens.Peek(); + n = TNode.Empty; + return false; + } + } + + public bool Pop( out Token t, out TNode n ) + { + if( _isNode.Pop() ) { + n = _nodes.Pop(); + t = Token.Empty; + return true; + } else { + t = _tokens.Pop(); + n = TNode.Empty; + return false; + } + } + + public void Push( TNode node ) + { + _nodes.Push( node ); + _isNode.Push( true ); + } + + public void Push( Token token ) + { + _tokens.Push( token ); + _isNode.Push( false ); + } + + } +} diff --git a/StgSharp.Script/obj/x64/Debug/net8.0/StgSharp.Script.AssemblyInfo.cs b/StgSharp.Script/obj/x64/Debug/net8.0/StgSharp.Script.AssemblyInfo.cs index 9f3994d3..1d9b5571 100644 --- a/StgSharp.Script/obj/x64/Debug/net8.0/StgSharp.Script.AssemblyInfo.cs +++ b/StgSharp.Script/obj/x64/Debug/net8.0/StgSharp.Script.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("StgSharp.Script")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+5d4f516a2836a307ab61298b3d96c20a81324634")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+c5777f4bfe31231c2026f5e0ffd291d5db793843")] [assembly: System.Reflection.AssemblyProductAttribute("StgSharp.Script")] [assembly: System.Reflection.AssemblyTitleAttribute("StgSharp.Script")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]