@@ -42,10 +42,11 @@ public class ExpressionEvaluator
4242 private static readonly Regex newLineCharsRegex = new Regex ( @"\r\n|\r|\n" ) ;
4343
4444 // For script only
45- private static Regex variableAssignationRegex = new Regex ( @"^(?<name>[a-zA-Z_][a-zA-Z0-9_]*)\s*(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])" ) ;
46- private static Regex blockKeywordsBeginningRegex = new Regex ( @"^\s*(?<keyword>while|for|if|else\s+if)\s*[(]" , RegexOptions . IgnoreCase ) ;
47- private static Regex elseblockKeywordsBeginningRegex = new Regex ( @"^\s*(?<keyword>else)(?![a-zA-Z0-9_])" , RegexOptions . IgnoreCase ) ;
48- private static Regex blockBeginningRegex = new Regex ( @"^\s*[{]" ) ;
45+ private static readonly Regex variableAssignationRegex = new Regex ( @"^(?<name>[a-zA-Z_][a-zA-Z0-9_]*)\s*(?<assignmentPrefix>[+\-*/%&|^]|<<|>>)?=(?![=>])" ) ;
46+ private static readonly Regex blockKeywordsBeginningRegex = new Regex ( @"^\s*(?<keyword>while|for|if|else\s+if)\s*[(]" , RegexOptions . IgnoreCase ) ;
47+ private static readonly Regex elseblockKeywordsBeginningRegex = new Regex ( @"^\s*(?<keyword>else)(?![a-zA-Z0-9_])" , RegexOptions . IgnoreCase ) ;
48+ private static readonly Regex blockBeginningRegex = new Regex ( @"^\s*[{]" ) ;
49+ private static readonly Regex returnKeywordRegex = new Regex ( @"^return(\s+|\()" , RegexOptions . IgnoreCase | RegexOptions . Singleline ) ;
4950
5051 #endregion
5152
@@ -626,12 +627,21 @@ public ExpressionEvaluator(Dictionary<string, object> variables) : this()
626627 /// <summary>
627628 /// Evaluate a script (multiple expressions separated by semicolon)
628629 /// Support Assignation with [=] (for simple variable write in the Variables dictionary)
630+ /// support also if, else if, else while and for keywords
629631 /// </summary>
630632 /// <param name="script">the script to evaluate</param>
631633 /// <returns>The result of the last evaluated expression</returns>
632634 public object ScriptEvaluate ( string script )
635+ {
636+ bool isReturn = false ;
637+
638+ return ScriptEvaluate ( script , ref isReturn ) ;
639+ }
640+
641+ private object ScriptEvaluate ( string script , ref bool valueReturned )
633642 {
634643 object lastResult = null ;
644+ bool isReturn = valueReturned ;
635645 int startOfExpression = 0 ;
636646 IfBlockEvaluatedState ifBlockEvaluatedState = IfBlockEvaluatedState . NoBlockEvaluated ;
637647 List < List < string > > ifElseStatementsList = new List < List < string > > ( ) ;
@@ -645,6 +655,12 @@ object AssignationOrExpressionEval(string expression)
645655
646656 expression = expression . Trim ( ) ;
647657
658+ expression = returnKeywordRegex . Replace ( expression , match =>
659+ {
660+ isReturn = true ;
661+ return match . Value . Contains ( "(" ) ? "(" : string . Empty ;
662+ } ) ;
663+
648664 Match variableAssignationMatch = variableAssignationRegex . Match ( expression ) ;
649665
650666 if ( variableAssignationMatch . Success )
@@ -714,15 +730,15 @@ void ExecuteIfList()
714730 string ifScript = ifElseStatementsList . Find ( statement => ( bool ) AssignationOrExpressionEval ( statement [ 0 ] ) ) ? [ 1 ] ;
715731
716732 if ( ! string . IsNullOrEmpty ( ifScript ) )
717- lastResult = ScriptEvaluate ( ifScript ) ;
733+ lastResult = ScriptEvaluate ( ifScript , ref isReturn ) ;
718734
719735 ifElseStatementsList . Clear ( ) ;
720736 }
721737 }
722738
723739 int i = 0 ;
724740
725- while ( i < script . Length )
741+ while ( ! isReturn && i < script . Length )
726742 {
727743 Match blockKeywordsBeginingMatch ;
728744 Match elseBlockKeywordsBeginingMatch = null ;
@@ -813,16 +829,16 @@ void ExecuteIfList()
813829 }
814830 else if ( keyword . Equals ( "while" ) )
815831 {
816- while ( ( bool ) AssignationOrExpressionEval ( keywordAttributes [ 0 ] ) )
817- lastResult = ScriptEvaluate ( subScript ) ;
832+ while ( ! isReturn && ( bool ) AssignationOrExpressionEval ( keywordAttributes [ 0 ] ) )
833+ lastResult = ScriptEvaluate ( subScript , ref isReturn ) ;
818834 }
819835 else if ( keyword . Equals ( "for" ) )
820836 {
821837 void forAction ( int index )
822838 { if ( keywordAttributes . Count > index && ! keywordAttributes [ index ] . Trim ( ) . Equals ( string . Empty ) ) AssignationOrExpressionEval ( keywordAttributes [ index ] ) ; }
823839
824- for ( forAction ( 0 ) ; ( bool ) AssignationOrExpressionEval ( keywordAttributes [ 1 ] ) ; forAction ( 2 ) )
825- lastResult = ScriptEvaluate ( subScript ) ;
840+ for ( forAction ( 0 ) ; ! isReturn && ( bool ) AssignationOrExpressionEval ( keywordAttributes [ 1 ] ) ; forAction ( 2 ) )
841+ lastResult = ScriptEvaluate ( subScript , ref isReturn ) ;
826842 }
827843 }
828844
@@ -848,10 +864,12 @@ void forAction(int index)
848864 }
849865 }
850866
867+ if ( ! script . Substring ( startOfExpression ) . Trim ( ) . Equals ( string . Empty ) && ! isReturn )
868+ throw new ExpressionEvaluatorSyntaxErrorException ( "A [;] character is missing." ) ;
869+
851870 ExecuteIfList ( ) ;
852871
853- if ( ! script . Substring ( startOfExpression ) . Trim ( ) . Equals ( string . Empty ) )
854- lastResult = ScriptExpressionEvaluate ( ref i ) ;
872+ valueReturned = isReturn ;
855873
856874 return lastResult ;
857875 }
@@ -1700,7 +1718,7 @@ private bool GetLambdaExpression(string expr, Stack<object> stack)
17001718 . Cast < Match > ( ) . ToList ( )
17011719 . ConvertAll ( argMatch => argMatch . Value ) ;
17021720
1703- stack . Push ( new lambdaExpressionDelegate ( delegate ( object [ ] args )
1721+ stack . Push ( new lambdaExpressionDelegate ( ( object [ ] args ) =>
17041722 {
17051723 Dictionary < string , object > vars = new Dictionary < string , object > ( Variables ) ;
17061724
0 commit comments