📄 ruleparser.cs
字号:
/*
*
* fuzzynet: Fuzzy Logic Library for Microsoft .NET
* Copyright (C) 2008 Dmitry Kaluzhny (kaluzhny_dmitrie@mail.ru)
*
* */
using System;
using System.Collections.Generic;
using System.Text;
namespace AI.Fuzzy.Library
{
/// <summary>
/// Class responsible for parsing
/// </summary>
internal class RuleParser
{
static string[] KEYWORDS = new string[] { "if", "then", "is", "and", "or", "not", "(", ")"};
#region Public helpers
/// <summary>
/// Check the name of variable/term.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
static public bool IsValidName(string name)
{
//
// Empty names are not allowed
//
if (name.Length == 0)
{
return false;
}
for (int i = 0; i < name.Length; i++)
{
//
// Only letters, numbers or '_' are allowed
//
if (!System.Char.IsDigit(name, i) ||
!System.Char.IsDigit(name, i) ||
name[i] != '_')
{
return false;
}
}
//
// Identifier cannot be a keword
//
foreach (string keyword in KEYWORDS)
{
if (name == keyword)
{
return false;
}
}
return true;
}
#endregion
#region Rule expression hierarchy
interface IExpression
{
string Text { get; }
}
abstract class Lexem : IExpression
{
public abstract string Text { get; }
public override string ToString()
{
return this.Text;
}
}
class ConditionExpression : IExpression
{
List<IExpression> _expressions = null;
SingleCondition _condition = null;
public ConditionExpression(List<IExpression> expressions, SingleCondition condition)
{
_expressions = expressions;
_condition = condition;
}
public List<IExpression> Expressions
{
get { return _expressions; }
set { _expressions = value; }
}
public SingleCondition Condition
{
get { return _condition; }
set { _condition = value; }
}
public string Text
{
get
{
StringBuilder sb = new StringBuilder();
foreach (IExpression ex in _expressions)
{
sb.Append(ex.Text);
}
return sb.ToString();
}
}
}
class KeywordLexem : Lexem
{
string _name;
public KeywordLexem(string name)
{
_name = name;
}
public override string Text
{
get { return _name; }
}
}
class VarLexem : Lexem
{
FuzzyVariable _var = null;
bool _input = true;
public VarLexem(FuzzyVariable var, bool input)
{
_var = var;
_input = input;
}
public FuzzyVariable Var
{
get { return _var; }
set { _var = value; }
}
public override string Text
{
get { return _var.Name; }
}
public bool Input
{
get { return _input; }
set { _input = value; }
}
}
class TermLexem : Lexem
{
FuzzyTerm _term = null;
bool _input = true;
public TermLexem(FuzzyTerm term, bool input)
{
_term = term;
_input = input;
}
public FuzzyTerm Term
{
get { return _term; }
set { _term = value; }
}
public override string Text
{
get { return _term.Name; }
}
}
#endregion
static private List<Lexem> BuildLexemsList(List<FuzzyVariable> input, List<FuzzyVariable> output)
{
List<Lexem> lexems = new List<Lexem>();
foreach (string keyword in KEYWORDS)
{
lexems.Add(new KeywordLexem(keyword));
}
foreach (FuzzyVariable var in input)
{
lexems.AddRange(BuildLexemsList(var, true));
}
foreach (FuzzyVariable var in output)
{
lexems.AddRange(BuildLexemsList(var, false));
}
return lexems;
}
static private List<Lexem> BuildLexemsList(FuzzyVariable var, bool input)
{
List<Lexem> lexems = new List<Lexem>();
lexems.Add(new VarLexem(var, input));
foreach (FuzzyTerm term in var.Terms)
{
lexems.Add(new TermLexem(term, input));
}
return lexems;
}
static private List<IExpression> ParseLexems(string rule, Dictionary<string, Lexem> lexems)
{
List<IExpression> expressions = new List<IExpression>();
string []words = rule.Split(' ');
foreach (string word in words)
{
Lexem lexem;
if (lexems.TryGetValue(word, out lexem))
{
expressions.Add(lexem);
}
else
{
throw new System.Exception(string.Format("Unknown identifier: {0}", word));
}
}
return expressions;
}
static private List<IExpression> ExtractSingleCondidtions(List<IExpression> conditionExpression, List<FuzzyVariable> input, Dictionary<string, Lexem> lexems)
{
List<IExpression> copyExpressions = conditionExpression.GetRange(0, conditionExpression.Count);
List<IExpression> expressions = new List<IExpression>();
while (copyExpressions.Count > 0)
{
if (copyExpressions[0] is VarLexem)
{
//
// Parse variable
//
VarLexem varLexem = (VarLexem)copyExpressions[0];
if (copyExpressions.Count < 3)
{
throw new Exception(string.Format("Condition strated with '{0}' is incorrect.", varLexem.Text));
}
if (varLexem.Input == false)
{
throw new Exception("The variable in condition part must be an intput variable.");
}
//
// Parse 'is' lexem
//
Lexem exprIs = (Lexem)copyExpressions[1];
if (exprIs != lexems["is"])
{
throw new Exception(string.Format("'is' keyword must go after {0} identifier.", varLexem.Text));
}
//
// Parse 'not' lexem (if exists)
//
int cur = 2;
bool not = false;
if (copyExpressions[cur] == lexems["not"])
{
not = true;
cur++;
if (copyExpressions.Count <= cur)
{
throw new Exception("Error at 'not' in condition part of the rule.");
}
}
//
// Parse term
//
Lexem exprTerm = (Lexem)copyExpressions[cur];
if (!(exprTerm is TermLexem))
{
throw new Exception(string.Format("Wrong identifier '{0}' in conclusion part of the rule.", exprTerm.Text));
}
TermLexem termLexem = (TermLexem)exprTerm;
if (!varLexem.Var.Terms.Contains(termLexem.Term))
{
throw new Exception(string.Format("The term ({0}) in condition part does not belong to the specified variable ({1}).", termLexem.Text, varLexem.Text));
}
//
// Add new condition expression
//
SingleCondition condition = new SingleCondition(varLexem.Var, termLexem.Term, not);
expressions.Add(new ConditionExpression(copyExpressions.GetRange(0, cur + 1), condition));
copyExpressions.RemoveRange(0, cur + 1);
}
else
{
IExpression expr = copyExpressions[0];
if (expr == lexems["and"] ||
expr == lexems["or"] ||
expr == lexems["("] ||
expr == lexems[")"])
{
expressions.Add(expr);
copyExpressions.RemoveAt(0);
}
else
{
Lexem unknownLexem = (Lexem)expr;
throw new Exception(string.Format("Lexem '{0}' found at the wrong place in condition part of the rule.", unknownLexem.Text));
}
}
}
return expressions;
}
static private Conditions ParseConditions(List<IExpression> conditionExpression, List<FuzzyVariable> input, Dictionary<string, Lexem> lexems)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -