/// <summary> /// Decode the token, is it an operand type double number? /// </summary> /// <param name="token"></param> /// <param name="result"></param> /// <param name="exprFinalOperand"></param> /// <returns></returns> private bool IsOperandDouble(ExprToken token, ParseResult result, ExprFinalOperand exprFinalOperand) { global::System.IFormatProvider culture = null; if (_exprEvalConfig.DecimalAndFunctionSeparators == DecimalAndFunctionSeparators.Standard) { // the decimal separator is a point, exp: 123.45 culture = new global::System.Globalization.CultureInfo("en-US"); } else { // the decimal separator is a comma, exp: 123,45 culture = new global::System.Globalization.CultureInfo("fr-fr"); } //NumberStyles styles = NumberStyles.AllowExponent | NumberStyles.AllowThousands | NumberStyles.AllowDecimalPoint; NumberStyles styles = NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign; double numberDouble; if (double.TryParse(token.Value, styles, culture, out numberDouble)) { exprFinalOperand.ContentType = OperandType.ValueDouble; exprFinalOperand.ValueDouble = numberDouble; return(true); } // its not a double operand value return(false); }
private bool CheckObjectNameSyntax(ExprToken token, ParseResult result, ExprFinalOperand exprFinalOperand) { exprFinalOperand.ContentType = OperandType.ObjectName; // the first char mut be: a letter or an underscore if (!char.IsLetter(token.Value[0]) && token.Value[0] != '_') { // erreur! plus de token, token attendu: opérande gauche. ExprError error = new ExprError(); error.Code = ErrorCode.ObjectNameSyntaxWrong; result.ListError.Add(error); return(false); } // check others char of the objectName // ici(); exprFinalOperand.ContentType = OperandType.ObjectName; return(true); }
/// <summary> /// decode les tokens de l'expression. /// construit une structure d'objets arborescente binaire basée sur la classe BoolBinExprBase. /// /// Compact the tokens before decoding it. /// </summary> /// <param name="expr"></param> /// <param name="listTokens"></param> /// <returns></returns> public ParseResult Parse(string expr, List <ExprToken> listTokens) { ParseResult result = new ParseResult(); result.Expression = expr; result.ListExprToken.AddRange(listTokens); // err, any operator (bool and comp) is defined if (_exprEvalConfig == null) { ExprError error = new ExprError(); // its an internal error! error.Code = ErrorCode.AnyOperatorDefined; result.ListError.Add(error); return(result); } // err, the expression is null or empty if (listTokens.Count == 0) { // erreur! plus de token, token attendu: opérande gauche. ExprError error = new ExprError(); error.Code = ErrorCode.ExprIsNullOrEmpty; result.ListError.Add(error); return(result); } // adds open and close bracket to the tokens, exp A=B -> (A=B) AddBrackets(listTokens); // init stack pour gérer les parenthèse Stack <ExpressionBase> stack = new Stack <ExpressionBase>(); // parcours les tokens un à un foreach (ExprToken token in listTokens) { //----parenthèse ouvrante? empile le token if (token.Value == "(") { ExprBracketOpen bracketOpen = new ExprBracketOpen(); bracketOpen.Token = token; stack.Push(bracketOpen); continue; } //----closed bracket found? pop tokens from the stack until find the open bracket, build a sub-expression. if (token.Value == ")") { SubExprDecoder subExprDecoder = new SubExprDecoder(); if (!subExprDecoder.DecodeExpr(stack, token, result)) { break; } continue; } //----opérateur? empile le token // selon langue, recupere la liste des opérateurs et compare. if (DecodeTokenOperator(stack, token)) { continue; } //----is it function Call parameter separator? if (DecodeTokenFunctionCallParameterSeparator(stack, token)) { continue; } //----opérande? empile le token // n'est ni une parenthèse ouvrante, fermante, ni un opérateur. ExprFinalOperand exprFinalOperand = BuildOperand(token, result); stack.Push(exprFinalOperand); } // decoder le résultat du traitement: la pile ne doit contenir qu'une seule expr AnalyzeStackContent(stack, result); return(result); }
/// <summary> /// Build the final operand: not a separator. /// can be a number (positive or negative), an object name (var, fct,...) or a string. /// /// The string can be well-formed or bad-formed: the end tag is missing. /// </summary> /// <param name="token"></param> /// <returns></returns> private ExprFinalOperand BuildOperand(ExprToken token, ParseResult result) { ExprFinalOperand exprFinalOperand = new ExprFinalOperand(); exprFinalOperand.Operand = token.Value; exprFinalOperand.Token = token; //----is the value a string? starts with a string tag (quote or double-quote) if (_exprEvalConfig.StringTagValue == token.Value[0].ToString()) { // is the last char a string tag? //if (_exprEvalConfig.ListStringTag.Contains(token.Value[token.Value.Length-1]) && token.Value.Length>1) if (_exprEvalConfig.StringTagValue == token.Value[token.Value.Length - 1].ToString() && token.Value.Length > 1) { exprFinalOperand.ContentType = OperandType.ValueString; return(exprFinalOperand); } exprFinalOperand.ContentType = OperandType.ValueStringBadFormed; ExprError error = new ExprError(); error.Token = token; error.Code = ErrorCode.ValueStringBadFormed; result.ListError.Add(error); return(exprFinalOperand); } //----is the value an integer? int numberInt; if (int.TryParse(token.Value, out numberInt)) { exprFinalOperand.ContentType = OperandType.ValueInt; exprFinalOperand.ValueInt = numberInt; return(exprFinalOperand); } //----is the value a double? if (IsOperandDouble(token, result, exprFinalOperand)) { return(exprFinalOperand); } // is it a bad-formed number? (seems to be number: start with minus or a digit) if (token.Value[0] == '-' || char.IsDigit(token.Value[0])) { exprFinalOperand.ContentType = OperandType.ValueNumberBadFormed; ExprError error = new ExprError(); error.Token = token; error.Code = ErrorCode.ValueNumberBadFormed; result.ListError.Add(error); return(exprFinalOperand); } //-----is it a bool value? // todo: get values from the configurator: true/false, vrai/faux BoolConst boolConst = _exprEvalConfig.ListBoolConst.Find(bc => bc.BoolStringValue.Equals(token.Value, StringComparison.InvariantCultureIgnoreCase)); if (boolConst != null) { exprFinalOperand.ContentType = OperandType.ValueBool; exprFinalOperand.ValueBool = boolConst.BoolValue; return(exprFinalOperand); } // it's an object name, (sure?) check the syntax CheckObjectNameSyntax(token, result, exprFinalOperand); return(exprFinalOperand); }
/// <summary> /// analyze and return the list of variables and functionCalls found in the expression to define before execute it. /// Do also some checks. /// </summary> /// <param name="exprParseResult"></param> /// <param name="expr"></param> /// <returns></returns> private bool AnalyzeSyntaxTree(ParseResult result, ExpressionBase expr) { //----is it a final operand? ExprFinalOperand exprFinalOperand = expr as ExprFinalOperand; if (exprFinalOperand != null) { if (exprFinalOperand.ContentType == OperandType.ObjectName) { // save the objectName (variable) result.AddVariable(exprFinalOperand.Operand); } return(true); } //----is it a function call? ExprFunctionCall exprFunctionCall = expr as ExprFunctionCall; if (exprFunctionCall != null) { // scan parameters of the function call foreach (ExpressionBase exprParam in exprFunctionCall.ListExprParameters) { AnalyzeSyntaxTree(result, exprParam); } result.AddFunctionCall(exprFunctionCall.FunctionName, exprFunctionCall.ListExprParameters.Count); return(true); } //----is it an expression comparison? ExprComparison exprComparison = expr as ExprComparison; if (exprComparison != null) { AnalyzeSyntaxTree(result, exprComparison.ExprLeft); AnalyzeSyntaxTree(result, exprComparison.ExprRight); return(true); } //----is it an expression logical? ExprLogical exprLogical = expr as ExprLogical; if (exprLogical != null) { AnalyzeSyntaxTree(result, exprLogical.ExprLeft); AnalyzeSyntaxTree(result, exprLogical.ExprRight); return(true); } //----is it an expression logical NOT? ExprLogicalNot exprLogicalNot = expr as ExprLogicalNot; if (exprLogicalNot != null) { AnalyzeSyntaxTree(result, exprLogicalNot.ExprBase); return(true); } //----is it an expression calculation? ExprCalculation exprCalculation = expr as ExprCalculation; if (exprCalculation != null) { // analyze all operands of the calculation expression bool res = true; foreach (ExpressionBase exprChild in exprCalculation.ListExprOperand) { res = res && AnalyzeSyntaxTree(result, exprChild); } //AnalyzeSyntaxTree(result, exprCalculation.ExprLeft); //AnalyzeSyntaxTree(result, exprCalculation.ExprRight); return(res); } //----is it a set value expression ? // todo: throw new Exception("todo: AnalyzeSyntaxTree(), expression type not yet implemented!"); }
private bool ExecExpressionFinalOperand(ExecResult exprExecResult, ExprFinalOperand finalOperand, out ExpressionExecBase exprExecBase) { // is the operand a variable or a call function? if (finalOperand.ContentType == OperandType.ObjectName) { // is it a variable? ExprVariableBase exprVariableBase = _expressionData.ExprExecResult.ListExprVariable.Find(v => v.Name.Equals(finalOperand.Operand, StringComparison.InvariantCultureIgnoreCase)); if (exprVariableBase != null) { // the operand is a string variable? ExprVariableString exprVariableString = exprVariableBase as ExprVariableString; if (exprVariableString != null) { // create a var instance, depending on the type ExprExecVarString exprExecVar = new ExprExecVarString(); exprExecVar.ExprVariableString = exprVariableString; exprExecVar.Expr = finalOperand; // set the value exprExecVar.Value = exprVariableString.Value; exprExecBase = exprExecVar; return(true); } // the operand is an int variable? ExprVariableInt exprVariableInt = exprVariableBase as ExprVariableInt; if (exprVariableInt != null) { // create a var instance, depending on the type ExprExecVarInt exprExecVar = new ExprExecVarInt(); exprExecVar.ExprVariableInt = exprVariableInt; exprExecVar.Expr = finalOperand; // set the value exprExecVar.Value = exprVariableInt.Value; exprExecBase = exprExecVar; return(true); } // the operand is a double variable? ExprVariableDouble exprVariableDouble = exprVariableBase as ExprVariableDouble; if (exprVariableDouble != null) { // create a var instance, depending on the type ExprExecVarDouble exprExecVar = new ExprExecVarDouble(); exprExecVar.ExprVariableDouble = exprVariableDouble; exprExecVar.Expr = finalOperand; // set the value exprExecVar.Value = exprVariableDouble.Value; exprExecBase = exprExecVar; return(true); } // the operand is a bool variable? ExprVariableBool exprVariableBool = exprVariableBase as ExprVariableBool; if (exprVariableBool != null) { // create a var instance, depending on the type ExprExecVarBool exprExecVar = new ExprExecVarBool(); exprExecVar.ExprVariableBool = exprVariableBool; exprExecVar.Expr = finalOperand; // set the value exprExecVar.Value = exprVariableBool.Value; exprExecBase = exprExecVar; return(true); } // todo; create an error throw new Exception("The operand variable type is not yet implemented!"); } // so its a function call // todo: rechercher dans la liste des fonctions? throw new Exception("The function call is not yet implemented!"); } // is the operand a string value (a const string value)? if (finalOperand.ContentType == OperandType.ValueString) { ExprExecValueString exprValueString = new ExprExecValueString(); exprValueString.Value = finalOperand.Operand; exprExecBase = exprValueString; exprValueString.Expr = finalOperand; return(true); } // is the operand an int value? if (finalOperand.ContentType == OperandType.ValueInt) { ExprExecValueInt exprValueInt = new ExprExecValueInt(); exprValueInt.Expr = finalOperand; exprValueInt.Value = finalOperand.ValueInt; exprExecBase = exprValueInt; return(true); } // is the operand a double value? if (finalOperand.ContentType == OperandType.ValueDouble) { ExprExecValueDouble exprValueDouble = new ExprExecValueDouble(); exprValueDouble.Expr = finalOperand; exprValueDouble.Value = finalOperand.ValueDouble; exprExecBase = exprValueDouble; return(true); } // is the operand a bool value? if (finalOperand.ContentType == OperandType.ValueBool) { ExprExecValueBool exprValueBool = new ExprExecValueBool(); exprValueBool.Expr = finalOperand; exprValueBool.Value = finalOperand.ValueBool; exprExecBase = exprValueBool; return(true); } // todo: create an error throw new Exception("The operand const value is not yet implemented!"); }
/// <summary> /// start the execution, analyze and return the list of variables to create. /// todo: recréer un syntax tree, avec des valeurs! /// /// -->Doit renvoyer comme résultat un objet de type ExprValueXXX, non?? (si pas d'erreur). /// </summary> /// <returns></returns> private bool ExecExpression(ExecResult exprExecResult, ExpressionBase expr, out ExpressionExecBase exprExecBase) { exprExecBase = null; //----is it a final operand (value, var or call function)? ExprFinalOperand finalOperand = expr as ExprFinalOperand; if (finalOperand != null) { return(ExecExpressionFinalOperand(exprExecResult, finalOperand, out exprExecBase)); } //----is it a comparison expression? ExprComparison exprComparison = expr as ExprComparison; if (exprComparison != null) { // execute the expression, execute the right part, execute the left part, then exec the expr (as 2 value operands) return(ExecExpressionComparison(exprExecResult, exprComparison, out exprExecBase)); } //----is it a logical expression (bin/2 operands)? ExprLogical exprLogical = expr as ExprLogical; if (exprLogical != null) { return(ExecExpressionLogical(exprExecResult, exprLogical, out exprExecBase)); } //----is it a NOT logical expression? ExprLogicalNot exprLogicalNot = expr as ExprLogicalNot; if (exprLogicalNot != null) { return(ExecExpressionLogicalNot(exprExecResult, exprLogicalNot, out exprExecBase)); } //----is it a calculation expression? ExprCalculation exprCalculation = expr as ExprCalculation; if (exprCalculation != null) { // execute the expression, execute the right part, execute the left part, then exec the expr (as 2 value operands) return(ExecExpressionCalculation(exprExecResult, exprCalculation, out exprExecBase)); } //----is it function call? ExprFunctionCall exprFunctionCall = expr as ExprFunctionCall; if (exprFunctionCall != null) { return(ExecExpressionFunctionCall(exprExecResult, exprFunctionCall, out exprExecBase)); } //----is it a setValue expression? // todo: future // todo: error, expression not yet implemented!! exprExecResult.AddErrorExec(ErrorCode.ExpressionTypeNotYetImplemented, "Expr", expr.GetType().ToString()); return(false); }