static internal RuleType Parse(string rule, RuleType emptyRule, List <FuzzyVariable> input, List <OutputVariableType> output) { if (rule.Length == 0) { throw new ArgumentException("Rule cannot be empty."); } // // Surround brakes with spaces, remove double spaces // System.Text.StringBuilder sb = new StringBuilder(); foreach (char ch in rule) { if (ch == ')' || ch == '(') { if (sb.Length > 0 && sb[sb.Length - 1] == ' ') { // Do not duplicate spaces } else { sb.Append(' '); } sb.Append(ch); sb.Append(' '); } else { if (ch == ' ' && sb.Length > 0 && sb[sb.Length - 1] == ' ') { // Do not duplicate spaces } else { sb.Append(ch); } } } // // Remove spaces // string prepRule = sb.ToString().Trim(); // // Build lexems dictionary // Dictionary <string, Lexem> lexemsDict = BuildLexemsList(input, output); // // At first we parse lexems // List <IExpression> expressions = ParseLexems(prepRule, lexemsDict); if (expressions.Count == 0) { throw new System.Exception("No valid identifiers found."); } // // Find condition & conclusion parts part // if (expressions[0] != lexemsDict["if"]) { throw new System.Exception("'if' should be the first identifier."); } int thenIndex = -1; for (int i = 1; i < expressions.Count; i++) { if (expressions[i] == lexemsDict["then"]) { thenIndex = i; break; } } if (thenIndex == -1) { throw new System.Exception("'then' identifier not found."); } int conditionLen = thenIndex - 1; if (conditionLen < 1) { throw new System.Exception("Condition part of the rule not found."); } int conclusionLen = expressions.Count - thenIndex - 1; if (conclusionLen < 1) { throw new System.Exception("Conclusion part of the rule not found."); } List <IExpression> conditionExpressions = expressions.GetRange(1, conditionLen); List <IExpression> conclusionExpressions = expressions.GetRange(thenIndex + 1, conclusionLen); Conditions conditions = ParseConditions(conditionExpressions, input, lexemsDict); SingleCondition <OutputVariableType, OutputValueType> conclusion = ParseConclusion <OutputVariableType, OutputValueType>(conclusionExpressions, output, lexemsDict); emptyRule.Condition = conditions; emptyRule.Conclusion = conclusion; return(emptyRule); }
static private ICondition ParseConditionsRecurse(List <IExpression> expressions, Dictionary <string, Lexem> lexems) { if (expressions.Count < 1) { throw new Exception("Empty condition found."); } if (expressions[0] == lexems["("] && FindPairBracket(expressions, lexems) == expressions.Count) { // // Remove extra brackets // return(ParseConditionsRecurse(expressions.GetRange(1, expressions.Count - 2), lexems)); } else if (expressions.Count == 1 && expressions[0] is ConditionExpression) { // // Return single conditions // return(((ConditionExpression)expressions[0]).Condition); } else { // // Parse list of one level conditions connected by or/and // List <IExpression> copyExpressions = expressions.GetRange(0, expressions.Count); Conditions conds = new Conditions(); bool setOrAnd = false; while (copyExpressions.Count > 0) { ICondition cond = null; if (copyExpressions[0] == lexems["("]) { // // Find pair bracket // int closeBracket = FindPairBracket(copyExpressions, lexems); if (closeBracket == -1) { throw new Exception("Parenthesis error."); } cond = ParseConditionsRecurse(copyExpressions.GetRange(1, closeBracket - 1), lexems); copyExpressions.RemoveRange(0, closeBracket + 1); } else if (copyExpressions[0] is ConditionExpression) { cond = ((ConditionExpression)copyExpressions[0]).Condition; copyExpressions.RemoveAt(0); } else { throw new ArgumentException(string.Format("Wrong expression in condition part at '{0}'"), copyExpressions[0].Text); } // // And condition to the list // conds.ConditionsList.Add(cond); if (copyExpressions.Count > 0) { if (copyExpressions[0] == lexems["and"] || copyExpressions[0] == lexems["or"]) { if (copyExpressions.Count < 2) { throw new Exception(string.Format("Error at {0} in condition part.", copyExpressions[0].Text)); } // // Set and/or for conditions list // OperatorType newOp = (copyExpressions[0] == lexems["and"]) ? OperatorType.And : OperatorType.Or; if (setOrAnd) { if (conds.Op != newOp) { throw new Exception("At the one nesting level cannot be mixed and/or operations."); } } else { conds.Op = newOp; setOrAnd = true; } copyExpressions.RemoveAt(0); } else { throw new Exception(string.Format("{1} cannot goes after {0}", copyExpressions[0].Text, copyExpressions[1].Text)); } } } return(conds); } }