public ParseResult Parse(string yaml) { _contentNodes = new List <ContentNode>(); try { YamlRuleParser parser = new YamlRuleParser(yaml, null); _model = new Model.Model(parser.Header(), parser.Formulas().ToList(), parser.Tabellen().ToList(), parser.Flow().ToList()); List <string> inclusiveSituations = null; foreach (var step in _model.Steps) { if (step.IsSituational) { inclusiveSituations = step.Situation.Split(',') .Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x)) .ToList(); foreach (var inclusiveSituation in inclusiveSituations) { var contentNodeStep = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}") { Parameter = new Parameter(step.Name, false, TypeEnum.Step, ref _model) }; contentNodeStep.Parameter.SemanticKey = contentNodeStep.Name; contentNodeStep.Situation = inclusiveSituation; _contentNodes.Add(contentNodeStep); step.SemanticKey = contentNodeStep.Name; if (step.Choices != null) { foreach (var choice in step.Choices) { var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}.{YamlRuleParser.StepChoice}.{choice.Situation}") { Parameter = new Parameter(choice.Situation, false, TypeEnum.Boolean, ref _model) }; contentNode.Parameter.SemanticKey = contentNode.Name; contentNode.Situation = inclusiveSituation; _contentNodes.Add(contentNode); } } if (!string.IsNullOrEmpty(step.Value)) { var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}.{step.Value}"); contentNode.Parameter = new Parameter(step.Name, null, TypeEnum.Double, ref _model); contentNode.Parameter.SemanticKey = contentNode.Name; contentNodeStep.Situation = inclusiveSituation; _contentNodes.Add(contentNode); } ResolveToQuestion(step.Formula, ref _contentNodes, step.Situation, step.Name); if (step.Break != null && !string.IsNullOrEmpty(step.Break.Expression)) { ContentNode node = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepSituation}.{inclusiveSituation}.geen_recht") { IsBreak = true, IsSituational = step.IsSituational, Situation = inclusiveSituation, Parameter = new Parameter(name: "recht", value: null, type: TypeEnum.Boolean, model: ref _model) }; step.Break.SemanticKey = node.Name; node.Parameter.SemanticKey = node.Name; contentNodeStep.Situation = inclusiveSituation; _contentNodes.Add(node); } } } else { var contentNodeStep = new ContentNode($"{YamlRuleParser.Step}.{step.Name}") { Parameter = new Parameter(step.Name, false, TypeEnum.Step, ref _model) }; contentNodeStep.Parameter.SemanticKey = contentNodeStep.Name; _contentNodes.Add(contentNodeStep); step.SemanticKey = contentNodeStep.Name; if (step.Choices != null) { foreach (var choice in step.Choices) { var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepChoice}.{choice.Situation}") { Parameter = new Parameter(choice.Situation, false, TypeEnum.Boolean, ref _model) }; contentNode.Parameter.SemanticKey = contentNode.Name; _contentNodes.Add(contentNode); } } if (!string.IsNullOrEmpty(step.Value)) { var contentNode = new ContentNode($"{YamlRuleParser.Step}.{step.Name}.{YamlRuleParser.StepValue}.{step.Value}"); contentNode.Parameter = new Parameter(step.Name, null, TypeEnum.Double, ref _model); contentNode.Parameter.SemanticKey = contentNode.Name; _contentNodes.Add(contentNode); } ResolveToQuestion(step.Formula, ref _contentNodes, step.Situation, step.Name); if (step.Break != null && !string.IsNullOrEmpty(step.Break.Expression)) { step.Break.SemanticKey = string.Join('.', new[] { YamlRuleParser.Step, step.Name, "geen_recht" }.Where(s => !string.IsNullOrEmpty(s))); ContentNode node = new ContentNode(step.Break.SemanticKey) { IsBreak = true, IsSituational = step.IsSituational, Situation = step.Situation, Parameter = new Parameter(name: "recht", value: null, type: TypeEnum.Boolean, model: ref _model) }; node.Parameter.SemanticKey = step.Break.SemanticKey; _contentNodes.Add(node); } } } } catch (Exception ex) { var result = new ParseResult { IsError = true, Message = ex.Message }; return(result); } ContentNodes.Add(new ContentNode("end") { Parameter = new Parameter("end", null, TypeEnum.Step, ref _model) }); return(new ParseResult() { Message = Ok, ExpressionTree = new YamlDotNet.Serialization.Serializer().Serialize(_model), Model = _model }); }
private static Parameter Evaluate(FormulaExpressionContext caller, ref ExpressionContext context, ref Formula formula, ref ParametersCollection parameters1, QuestionDelegate onQuestion, ref Model.Model model) { if (parameters1 is null) { throw new ArgumentNullException(nameof(parameters1)); } IDynamicExpression e = null; if (!formula.IsSituational) { try { e = context.CompileDynamic(formula.Functions[0].Expression); var result = e.Evaluate().Infer(); Parameter parameter; parameter = new Parameter(formula.Name, result.Infer(), null, ref model); parameter.IsCalculated = true; parameters1.Add(parameter); if (context.Variables.ContainsKey(parameter.Name)) { context.Variables.Remove(parameter.Name); } context.Variables.Add(parameter.Name, parameter.Value.Infer()); return(parameter); } catch (ExpressionCompileException) { // Function can not evaluate further, before a Question/Answer sequence is fullfilled by the client. throw new UnresolvedException($"Function {formula.Functions[0].Expression} can not evaluate further, before a Question/Answer sequence is fullfilled by the client."); } } else { foreach (var function in formula.Functions) { foreach (var item in parameters1) { if (item.Name == function.Situation && (bool)item.Value == true) { try { e = context.CompileDynamic(function.Expression); var parameter = new Parameter(formula.Name, e.Evaluate().Infer(), null, ref model); parameter.IsCalculated = true; parameters1.Add(parameter); if (context.Variables.ContainsKey(parameter.Name)) { context.Variables.Remove(parameter.Name); } context.Variables.Add(parameter.Name, parameter.Value.Infer()); return(parameter); } catch (ExpressionCompileException) { // Function can not evaluate further, before a Question/Answer sequence is fullfilled by the client. throw new UnresolvedException($"Function {function.Expression} can not evaluate further, before a Question/Answer sequence is fullfilled by the client."); } } } } StringBuilder situations = new StringBuilder(); var parameters = new ParametersCollection(); foreach (var function in formula.Functions) { situations.Append(function.Situation + ","); var parameter = new Parameter(function.Situation, TypeInference.Infer(function).Type, null, ref model); parameters.Add(parameter); } if (onQuestion == null) { throw new Exception($"In order to evaluate variable one of the following situations: {situations.ToString().Trim(',')}, you need to provide a delegate callback to the client for providing an answer"); } onQuestion(caller, new QuestionArgs("", parameters)); // situation has to be formulated as an input parameter by the client. throw new UnresolvedException($"Can't evaluate formula {formula.Name} for situation. Please specify one of the following situations: {situations.ToString().Trim(',')}."); } }