@@ -16,18 +16,19 @@ public class ExpressionEvaluator
1616 {
1717 #region Regex declarations
1818
19- private static Regex varOrFunctionRegEx = new Regex ( @"^((?<sign>[+-])|(?<inObject>(?<nullConditional>[?])?\.)?)(?<name>[a-zA-Z_][a-zA-Z0-9_]*)\s*((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![a-zA-Z0-9_]))|((?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))" , RegexOptions . IgnoreCase | RegexOptions . Compiled ) ;
20- private static Regex numberRegex = new Regex ( @"^(?<sign>[+-])?\d+(?<hasdecimal>\.?\d+(e[+-]?\d+)?)?(?<type>ul|[fdulm])?" , RegexOptions . IgnoreCase ) ;
21- private static Regex stringBeginningRegex = new Regex ( "^(?<interpolated>[$])?(?<escaped>[@])?[\" ]" ) ;
22- private static Regex internalCharRegex = new Regex ( @"^['](\\[']|[^'])*[']" ) ;
23- private static Regex castRegex = new Regex ( @"^\(\s*(?<typeName>[a-zA-Z_][a-zA-Z0-9_\.\[\]<>]*[?]?)\s*\)" ) ;
24- private static Regex indexingBeginningRegex = new Regex ( @"^[?]?\[" ) ;
25- private static Regex endOfStringWithDollar = new Regex ( "^[^\" {]*[\" {]" ) ;
26- private static Regex endOfStringWithoutDollar = new Regex ( "^[^\" ]*[\" ]" ) ;
27- private static Regex endOfStringInterpolationRegex = new Regex ( "^[^}\" ]*[}\" ]" ) ;
28- private static Regex stringBeginningForEndBlockRegex = new Regex ( "[$]?[@]?[\" ]$" ) ;
29- private static Regex lambdaExpressionRegex = new Regex ( @"^\s*(?<args>(\s*[(]\s*([a-zA-Z_][a-zA-Z0-9_]*\s*([,]\s*[a-zA-Z_][a-zA-Z0-9_]*\s*)*)?[)])|[a-zA-Z_][a-zA-Z0-9_]*)\s*=>(?<expression>.*)$" , RegexOptions . Singleline ) ;
30- private static Regex lambdaArgRegex = new Regex ( @"[a-zA-Z_][a-zA-Z0-9_]*" ) ;
19+ private static readonly Regex varOrFunctionRegEx = new Regex ( @"^((?<sign>[+-])|(?<inObject>(?<nullConditional>[?])?\.)?)(?<name>[a-zA-Z_][a-zA-Z0-9_]*)\s*((?<assignationOperator>(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>]))|(?<postfixOperator>([+][+]|--)(?![a-zA-Z0-9_]))|((?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?))" , RegexOptions . IgnoreCase | RegexOptions . Compiled ) ;
20+ private static readonly Regex numberRegex = new Regex ( @"^(?<sign>[+-])?\d+(?<hasdecimal>\.?\d+(e[+-]?\d+)?)?(?<type>ul|[fdulm])?" , RegexOptions . IgnoreCase ) ;
21+ private static readonly Regex stringBeginningRegex = new Regex ( "^(?<interpolated>[$])?(?<escaped>[@])?[\" ]" ) ;
22+ private static readonly Regex internalCharRegex = new Regex ( @"^['](\\[']|[^'])*[']" ) ;
23+ private static readonly Regex castRegex = new Regex ( @"^\(\s*(?<typeName>[a-zA-Z_][a-zA-Z0-9_\.\[\]<>]*[?]?)\s*\)" ) ;
24+ private static readonly Regex indexingBeginningRegex = new Regex ( @"^[?]?\[" ) ;
25+ private static readonly Regex assignationOperatorRegex = new Regex ( @"^\s*(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])" ) ;
26+ private static readonly Regex endOfStringWithDollar = new Regex ( "^[^\" {]*[\" {]" ) ;
27+ private static readonly Regex endOfStringWithoutDollar = new Regex ( "^[^\" ]*[\" ]" ) ;
28+ private static readonly Regex endOfStringInterpolationRegex = new Regex ( "^[^}\" ]*[}\" ]" ) ;
29+ private static readonly Regex stringBeginningForEndBlockRegex = new Regex ( "[$]?[@]?[\" ]$" ) ;
30+ private static readonly Regex lambdaExpressionRegex = new Regex ( @"^\s*(?<args>(\s*[(]\s*([a-zA-Z_][a-zA-Z0-9_]*\s*([,]\s*[a-zA-Z_][a-zA-Z0-9_]*\s*)*)?[)])|[a-zA-Z_][a-zA-Z0-9_]*)\s*=>(?<expression>.*)$" , RegexOptions . Singleline ) ;
31+ private static readonly Regex lambdaArgRegex = new Regex ( @"[a-zA-Z_][a-zA-Z0-9_]*" ) ;
3132
3233 private static readonly string instanceCreationWithNewKeywordRegexPattern = @"^new\s+(?<name>[a-zA-Z_][a-zA-Z0-9_.]*)\s*(?<isgeneric>[<](?>[^<>]+|(?<gentag>[<])|(?<-gentag>[>]))*(?(gentag)(?!))[>])?(?<isfunction>[(])?" ;
3334 private Regex instanceCreationWithNewKeywordRegex = new Regex ( instanceCreationWithNewKeywordRegexPattern ) ;
@@ -1641,9 +1642,52 @@ private bool EvaluateIndexing(string expr, string s, Stack<object> stack, ref in
16411642 ExpressionOperator op = indexingBeginningMatch . Length == 2 ? ExpressionOperator . IndexingWithNullConditional : ExpressionOperator . Indexing ;
16421643 dynamic left = stack . Pop ( ) ;
16431644
1644- stack . Push ( operatorsEvaluations [ 0 ] [ op ] ( left , right ) ) ;
1645+ Match assignationOperatorMatch ;
1646+
1647+ object valueToPush = null ;
1648+
1649+ if ( ( assignationOperatorMatch = assignationOperatorRegex . Match ( expr . Substring ( i + 1 ) ) ) . Success )
1650+ {
1651+ i += assignationOperatorMatch . Length + 1 ;
1652+
1653+ if ( stack . Count > 1 )
1654+ throw new ExpressionEvaluatorSyntaxErrorException ( "The left part of an assignation must be a variable, a property or an indexer." ) ;
1655+
1656+ string rightExpression = expr . Substring ( i ) ;
1657+ i = expr . Length ;
1658+
1659+ if ( op == ExpressionOperator . IndexingWithNullConditional )
1660+ throw new ExpressionEvaluatorSyntaxErrorException ( "Null coalescing is not usable left to an assignation" ) ;
1661+
1662+ if ( rightExpression . Trim ( ) . Equals ( string . Empty ) )
1663+ throw new ExpressionEvaluatorSyntaxErrorException ( "Right part is missing in assignation" ) ;
1664+
1665+ if ( assignationOperatorMatch . Groups [ "assignmentPrefix" ] . Success )
1666+ {
1667+ ExpressionOperator prefixOp = operatorsDictionary [ assignationOperatorMatch . Groups [ "assignmentPrefix" ] . Value ] ;
1668+
1669+ valueToPush = operatorsEvaluations [ 0 ] [ op ] ( left , right ) ;
1670+
1671+ valueToPush = operatorsEvaluations . Find ( dict => dict . ContainsKey ( prefixOp ) ) [ prefixOp ] ( valueToPush , Evaluate ( rightExpression ) ) ;
1672+ }
1673+ else
1674+ {
1675+ valueToPush = Evaluate ( rightExpression ) ;
1676+ }
1677+
1678+ left [ right ] = valueToPush ;
1679+
1680+ stack . Clear ( ) ;
1681+ }
1682+ else
1683+ {
1684+ valueToPush = operatorsEvaluations [ 0 ] [ op ] ( left , right ) ;
1685+ }
1686+
1687+ stack . Push ( valueToPush ) ;
16451688
16461689 return true ;
1690+
16471691 }
16481692
16491693 return false ;
0 commit comments