private void ParseRule( )
{
// flag to incicate we are on consequent state
bool consequent = false;
// tokens like IF and THEN will be searched always in upper case
string upRule = rule.ToUpper( );
// the rule must start with IF, and must have a THEN somewhere
if ( !upRule.StartsWith( "IF" ) )
throw new ArgumentException( "A Fuzzy Rule must start with an IF statement." );
if ( upRule.IndexOf( "THEN" ) < 0 )
throw new ArgumentException( "Missing the consequent (THEN) statement." );
// building a list with all the expression (rule) string tokens
string spacedRule = rule.Replace( "(", " ( " ).Replace( ")", " ) " );
// getting the tokens list
string[] tokensList = GetRuleTokens( spacedRule );
// stack to convert to RPN
Stack<string> s = new Stack<string>( );
// storing the last token
string lastToken = "IF";
// linguistic var read, used to build clause
LinguisticVariable lingVar = null;
// verifying each token
for ( int i = 0; i < tokensList.Length; i++ )
{
// removing spaces
string token = tokensList[i].Trim( );
// getting upper case
string upToken = token.ToUpper( );
// ignoring these tokens
if ( upToken == "" || upToken == "IF" ) continue;
// if the THEN is found, the rule is now on consequent
if ( upToken == "THEN" )
{
lastToken = upToken;
consequent = true;
continue;
}
// if we got a linguistic variable, an IS statement and a label is needed
if ( lastToken == "VAR" )
{
if ( upToken == "IS" )
lastToken = upToken;
else
throw new ArgumentException( "An IS statement is expected after a linguistic variable." );
}
// if we got an IS statement, a label must follow it
else if ( lastToken == "IS" )
{
try
{
FuzzySet fs = lingVar.GetLabel( token );
Clause c = new Clause( lingVar, fs );
if ( consequent )
output = c;
else
rpnTokenList.Add( c );
lastToken = "LAB";
}
catch ( KeyNotFoundException )
{
throw new ArgumentException( "Linguistic label " + token + " was not found on the variable " + lingVar.Name + "." );
}
}
// not VAR and not IS statement
else
{
// openning new scope
if ( upToken == "(" )
{
// if we are on consequent, only variables can be found
if ( consequent )
throw new ArgumentException( "Linguistic variable expected after a THEN statement." );
// if its a (, just push it
s.Push( upToken );
lastToken = upToken;
}
// operators
else if ( upToken == "AND" || upToken == "OR" || unaryOperators.IndexOf( upToken ) >= 0 )
{
// if we are on consequent, only variables can be found
if ( consequent )
throw new ArgumentException( "Linguistic variable expected after a THEN statement." );
// pop all the higher priority operators until the stack is empty
while ( ( s.Count > 0 ) && ( Priority( s.Peek( ) ) > Priority( upToken ) ) )
rpnTokenList.Add( s.Pop( ) );
// pushing the operator
s.Push( upToken );
lastToken = upToken;
}
// closing the scope
else if ( upToken == ")" )
{
// if we are on consequent, only variables can be found
if ( consequent )
throw new ArgumentException( "Linguistic variable expected after a THEN statement." );
// if there is nothing on the stack, an oppening parenthesis is missing.
if ( s.Count == 0 )
throw new ArgumentException( "Openning parenthesis missing." );
// pop the tokens and copy to output until openning is found
while ( s.Peek( ) != "(" )
{
rpnTokenList.Add( s.Pop( ) );
if ( s.Count == 0 )
throw new ArgumentException( "Openning parenthesis missing." );
}
s.Pop( );
// saving last token...
lastToken = upToken;
}
// finally, the token is a variable
else
{
// find the variable
try
{
lingVar = database.GetVariable( token );
lastToken = "VAR";
}
catch ( KeyNotFoundException )
{
throw new ArgumentException( "Linguistic variable " + token + " was not found on the database." );
}
}
}
}
// popping all operators left in stack
while ( s.Count > 0 )
rpnTokenList.Add( s.Pop( ) );
}