@@ -29,11 +29,10 @@ public class ExpressionEvaluator
2929 private static readonly string diactitics = "áàâãåǎăāąæéèêëěēĕėęěìíîïīĭįijóôõöōŏőøðœùúûüǔũūŭůűųýþÿŷıćĉċčçďđĝğġģĥħĵķĺļľŀłńņňŋñŕŗřśŝşšţťŧŵźżžÁÀÂÃÅǍĂĀĄÆÉÈÊËĚĒĔĖĘĚÌÍÎÏĪĬĮIJÓÔÕÖŌŎŐØÐŒÙÚÛÜǓŨŪŬŮŰŲÝÞŸŶIĆĈĊČÇĎĐĜĞĠĢĤĦĴĶĹĻĽĿŁŃŅŇŊÑŔŖŘŚŜŞŠŢŤŦŴŹŻŽß" ;
3030 private static readonly string diactiticsKeywordsRegexPattern = "a-zA-Z_" + diactitics ;
3131
32- private static readonly Regex varOrFunctionRegEx = new Regex ( @"^((?<sign>[+-])|(?<inObject>(?<nullConditional>[?])?\.)?)(?<name>[" + diactiticsKeywordsRegexPattern + @"][" + diactiticsKeywordsRegexPattern + @" 0-9]*)\s*((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![" + diactiticsKeywordsRegexPattern + @" 0-9]))|((?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))", RegexOptions . IgnoreCase | RegexOptions . Compiled ) ;
32+ private static readonly Regex varOrFunctionRegEx = new Regex ( $ @ "^((?<sign>[+-])|(?<inObject>(?<nullConditional>[?])?\.)?)(?<name>[{ diactiticsKeywordsRegexPattern } ][ { diactiticsKeywordsRegexPattern } 0-9]*)\s*((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![{ diactiticsKeywordsRegexPattern } 0-9]))|((?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))", RegexOptions . IgnoreCase | RegexOptions . Compiled ) ;
3333 private static readonly Regex numberRegex = new Regex ( @"^(?<sign>[+-])?\d+(?<hasdecimal>\.?\d+(e[+-]?\d+)?)?(?<type>ul|[fdulm])?" , RegexOptions . IgnoreCase ) ;
3434 private static readonly Regex stringBeginningRegex = new Regex ( "^(?<interpolated>[$])?(?<escaped>[@])?[\" ]" ) ;
3535 private static readonly Regex internalCharRegex = new Regex ( @"^['](\\[']|[^'])*[']" ) ;
36- private static readonly Regex castRegex = new Regex ( @"^\(\s*(?<typeName>[" + diactiticsKeywordsRegexPattern + @"][" + diactiticsKeywordsRegexPattern + @"0-9\.\[\]<>]*[?]?)\s*\)" ) ;
3736 private static readonly Regex indexingBeginningRegex = new Regex ( @"^[?]?\[" ) ;
3837 private static readonly Regex assignationOrPostFixOperatorRegex = new Regex ( @"^\s*((?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])|(?<postfixOperator>([+][+]|--)(?![" + diactiticsKeywordsRegexPattern + @"0-9])))" ) ;
3938
@@ -43,13 +42,18 @@ public class ExpressionEvaluator
4342 private static readonly Regex endOfStringWithoutDollarWithAt = new Regex ( "^[^\" ]*[\" ]" ) ;
4443 private static readonly Regex endOfStringInterpolationRegex = new Regex ( "^('\" '|[^}\" ])*[}\" ]" ) ;
4544 private static readonly Regex stringBeginningForEndBlockRegex = new Regex ( "[$]?[@]?[\" ]$" ) ;
46- private static readonly Regex lambdaExpressionRegex = new Regex ( @"^\s*(?<args>(\s*[(]\s*([" + diactiticsKeywordsRegexPattern + @"][" + diactiticsKeywordsRegexPattern + @" 0-9]*\s*([,]\s*[" + diactiticsKeywordsRegexPattern + @"][" + diactiticsKeywordsRegexPattern + @" 0-9]*\s*)*)?[)])|[" + diactiticsKeywordsRegexPattern + @"][" + diactiticsKeywordsRegexPattern + @" 0-9]*)\s*=>(?<expression>.*)$", RegexOptions . Singleline ) ;
47- private static readonly Regex lambdaArgRegex = new Regex ( @"[" + diactiticsKeywordsRegexPattern + @"][" + diactiticsKeywordsRegexPattern + @" 0-9]*") ;
45+ private static readonly Regex lambdaExpressionRegex = new Regex ( $ @ "^\s*(?<args>(\s*[(]\s*([{ diactiticsKeywordsRegexPattern } ][ { diactiticsKeywordsRegexPattern } 0-9]*\s*([,]\s*[{ diactiticsKeywordsRegexPattern } ][ { diactiticsKeywordsRegexPattern } 0-9]*\s*)*)?[)])|[{ diactiticsKeywordsRegexPattern } ][ { diactiticsKeywordsRegexPattern } 0-9]*)\s*=>(?<expression>.*)$", RegexOptions . Singleline ) ;
46+ private static readonly Regex lambdaArgRegex = new Regex ( $ @ "[{ diactiticsKeywordsRegexPattern } ][ { diactiticsKeywordsRegexPattern } 0-9]*") ;
4847 private static readonly Regex initInNewBeginningRegex = new Regex ( @"^\s*{" ) ;
4948 private static readonly Regex OtherDimentionArrayInNewBeginningRegex = new Regex ( @"^\s*\[" ) ;
5049
51- private static readonly string instanceCreationWithNewKeywordRegexPattern = @"^new\s+(?<name>[" + diactiticsKeywordsRegexPattern + @"][" + diactiticsKeywordsRegexPattern + @"0-9.]*)\s*(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?\s*((?<isfunction>[(])|(?<isArray>\[))?" ;
52- private Regex instanceCreationWithNewKeywordRegex = new Regex ( instanceCreationWithNewKeywordRegexPattern ) ;
50+
51+ // Depending on OptionInlineNamespacesEvaluationActive. Initialized in constructor
52+ private string CastRegexPattern { get { return $@ "^\(\s*(?<typeName>[{ diactiticsKeywordsRegexPattern } ][{ diactiticsKeywordsRegexPattern } 0-9\{ ( OptionInlineNamespacesEvaluationActive ? @"\." : string . Empty ) } [\]<>]*[?]?)\s*\)"; } }
53+ private string InstanceCreationWithNewKeywordRegexPattern { get { return $@ "^new\s+(?<name>[{ diactiticsKeywordsRegexPattern } ][{ diactiticsKeywordsRegexPattern } 0-9{ ( OptionInlineNamespacesEvaluationActive ? @"\." : string . Empty ) } ]*)\s*(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?\s*((?<isfunction>[(])|(?<isArray>\[))?"; } }
54+ private Regex instanceCreationWithNewKeywordRegex = null ;
55+ private Regex castRegex = null ;
56+
5357 private static readonly string primaryTypesRegexPattern = @"(?<=^|[^" + diactiticsKeywordsRegexPattern + @"])(?<primaryType>object|string|bool[?]?|byte[?]?|char[?]?|decimal[?]?|double[?]?|short[?]?|int[?]?|long[?]?|sbyte[?]?|float[?]?|ushort[?]?|uint[?]?|void)(?=[^a-zA-Z_]|$)" ;
5458 private Regex primaryTypesRegex = new Regex ( primaryTypesRegexPattern ) ;
5559
@@ -462,7 +466,7 @@ public bool OptionCaseSensitiveEvaluationActive
462466 simpleDoubleMathFuncsDictionary = new Dictionary < string , Func < double , double > > ( simpleDoubleMathFuncsDictionary , StringComparerForCasing ) ;
463467 doubleDoubleMathFuncsDictionary = new Dictionary < string , Func < double , double , double > > ( doubleDoubleMathFuncsDictionary , StringComparerForCasing ) ;
464468 complexStandardFuncsDictionary = new Dictionary < string , Func < ExpressionEvaluator , List < string > , object > > ( complexStandardFuncsDictionary , StringComparerForCasing ) ;
465- instanceCreationWithNewKeywordRegex = new Regex ( instanceCreationWithNewKeywordRegexPattern , ( optionCaseSensitiveEvaluationActive ? RegexOptions . None : RegexOptions . IgnoreCase ) ) ;
469+ instanceCreationWithNewKeywordRegex = new Regex ( InstanceCreationWithNewKeywordRegexPattern , ( optionCaseSensitiveEvaluationActive ? RegexOptions . None : RegexOptions . IgnoreCase ) ) ;
466470 primaryTypesRegex = new Regex ( primaryTypesRegexPattern , ( optionCaseSensitiveEvaluationActive ? RegexOptions . None : RegexOptions . IgnoreCase ) ) ;
467471 }
468472 }
@@ -489,6 +493,22 @@ private StringComparer StringComparerForCasing
489493 /// </summary>
490494 public bool OptionNewKeywordEvaluationActive { get ; set ; } = true ;
491495
496+ /// <summary>
497+ /// if <c>true</c> allow the use of inline namespace (Can be slow, and is less secure).
498+ /// if <c>false</c> unactive inline namespace (only namespaces in Namespaces list are available).
499+ /// By default : true
500+ /// </summary>
501+ public bool OptionInlineNamespacesEvaluationActive
502+ {
503+ get { return optionInlineNamespacesEvaluationActive ; }
504+ set
505+ {
506+ optionInlineNamespacesEvaluationActive = value ;
507+ instanceCreationWithNewKeywordRegex = new Regex ( InstanceCreationWithNewKeywordRegexPattern , ( optionCaseSensitiveEvaluationActive ? RegexOptions . None : RegexOptions . IgnoreCase ) ) ;
508+ castRegex = new Regex ( CastRegexPattern , ( optionCaseSensitiveEvaluationActive ? RegexOptions . None : RegexOptions . IgnoreCase ) ) ;
509+ }
510+ }
511+
492512 private Func < ExpressionEvaluator , List < string > , object > newMethodMem ;
493513
494514 /// <summary>
@@ -673,6 +693,8 @@ public Dictionary<string, object> Variables
673693 public ExpressionEvaluator ( )
674694 {
675695 Assemblies . AddRange ( AppDomain . CurrentDomain . GetAssemblies ( ) ) ;
696+ instanceCreationWithNewKeywordRegex = new Regex ( InstanceCreationWithNewKeywordRegexPattern ) ;
697+ castRegex = new Regex ( CastRegexPattern ) ;
676698 }
677699
678700 /// <summary>
@@ -689,6 +711,7 @@ public ExpressionEvaluator(Dictionary<string, object> variables) : this()
689711 #region Main evaluate methods (Expressions and scripts ==> public)
690712
691713 private bool inScript = false ;
714+ private bool optionInlineNamespacesEvaluationActive = true ;
692715
693716 /// <summary>
694717 /// Evaluate a script (multiple expressions separated by semicolon)
@@ -1766,6 +1789,35 @@ private bool EvaluateVarOrFunc(string expr, string restOfExpression, Stack<objec
17661789 string typeName = $ "{ varFuncName } { ( ( i < expr . Length && expr . Substring ( i ) [ 0 ] == '?' ) ? "?" : "" ) } ";
17671790 Type staticType = GetTypeByFriendlyName ( typeName ) ;
17681791
1792+ if ( staticType == null && OptionInlineNamespacesEvaluationActive )
1793+ {
1794+ int subIndex = 0 ;
1795+ Match namespaceMatch = varOrFunctionRegEx . Match ( expr . Substring ( i + subIndex ) ) ;
1796+
1797+ while ( staticType == null &&
1798+ namespaceMatch . Success &&
1799+ ! namespaceMatch . Groups [ "sign" ] . Success &&
1800+ ! namespaceMatch . Groups [ "assignationOperator" ] . Success &&
1801+ ! namespaceMatch . Groups [ "postfixOperator" ] . Success &&
1802+ ! namespaceMatch . Groups [ "postfixOperator" ] . Success &&
1803+ ! namespaceMatch . Groups [ "isfunction" ] . Success &&
1804+ i + subIndex < expr . Length &&
1805+ ! typeName . EndsWith ( "?" ) )
1806+ {
1807+ subIndex += namespaceMatch . Length ;
1808+ typeName += $ "{ namespaceMatch . Value } { ( ( i + subIndex < expr . Length && expr . Substring ( i + subIndex ) [ 0 ] == '?' ) ? "?" : "" ) } ";
1809+ staticType = GetTypeByFriendlyName ( typeName ) ;
1810+
1811+ if ( staticType != null )
1812+ {
1813+ i += subIndex ;
1814+ break ;
1815+ }
1816+
1817+ namespaceMatch = varOrFunctionRegEx . Match ( expr . Substring ( i + subIndex ) ) ;
1818+ }
1819+ }
1820+
17691821 if ( typeName . EndsWith ( "?" ) && staticType != null )
17701822 i ++ ;
17711823
@@ -2560,7 +2612,7 @@ private bool DefaultFunctions(string name, List<string> args, out object result)
25602612 return functionExists ;
25612613 }
25622614
2563- private Type GetTypeByFriendlyName ( string typeName )
2615+ private Type GetTypeByFriendlyName ( string typeName , bool withNameSpace = false )
25642616 {
25652617 Type result = null ;
25662618 try
@@ -2586,9 +2638,12 @@ private Type GetTypeByFriendlyName(string typeName)
25862638 {
25872639 result = Type . GetType ( $ "{ typeName } ,{ Assemblies [ a ] . FullName } ", false , ! OptionCaseSensitiveEvaluationActive ) ;
25882640
2589- for ( int i = 0 ; i < Namespaces . Count && result == null ; i ++ )
2641+ if ( ! typeName . Contains ( "." ) )
25902642 {
2591- result = Type . GetType ( $ "{ Namespaces [ i ] } .{ typeName } ,{ Assemblies [ a ] . FullName } ", false , ! OptionCaseSensitiveEvaluationActive ) ;
2643+ for ( int i = 0 ; i < Namespaces . Count && result == null ; i ++ )
2644+ {
2645+ result = Type . GetType ( $ "{ Namespaces [ i ] } .{ typeName } ,{ Assemblies [ a ] . FullName } ", false , ! OptionCaseSensitiveEvaluationActive ) ;
2646+ }
25922647 }
25932648 }
25942649 }
0 commit comments