递归下降的表达式解析器(C#)

使用方法:10-2*3 得到结果 6。

ExpressionParser.cs

None.gif using  System;
None.gif
None.gif
namespace  IBMS.Text.Script
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ContractedSubBlock.gifExpandedSubBlockStart.gif    
Field#region Field
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Parser of syntax
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class ExpressionParser
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Threse are the token types
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public enum TokenTypes
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// Not defined type of token
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            None,
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// Delimiter token type
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            Delimiter,
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// Variable token type
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            Variable,
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// Number token type
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            Number,
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// These are the types of syntax errors
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public enum SyntaxErrors
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// All syntax error 
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            Synatx,
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// Bracket error
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            UnBalparens,
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// No expression error
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            NoExpression,
InBlock.gif            
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//// <summary>
InBlock.gif            
/// Divide by zero error
ExpandedSubBlockEnd.gif            
/// </summary>

InBlock.gif            DivByZero,
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// This token indicates end-of-expression
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        readonly private string EOE;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// refers to expression string
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private string exp;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Current index into the expression
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private int expIdx;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Holds current token
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private string token;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Holds current token's type
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private TokenTypes tokType;
InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif    
Public Mothord#region Public Mothord
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Constructor
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        public ExpressionParser()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            EOE
= "\0";
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Parsor entry point 
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="expstr">expression string</param>
ExpandedSubBlockEnd.gif        
/// <returns>result of the expression</returns>

InBlock.gif        public double Evaluate(string expstr)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
double result = 0.0;
InBlock.gif            exp 
=expstr;
InBlock.gif            expIdx 
= 0;
InBlock.gif
InBlock.gif            GetToken();
InBlock.gif            
if( token == EOE)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                HandleError(SyntaxErrors.NoExpression);    
//No expression present
ExpandedSubBlockEnd.gif
            }

InBlock.gif
InBlock.gif            
//Parse and evaluate the expression
InBlock.gif
            result = EvalExp2();
InBlock.gif            
if( token != EOE)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                HandleError(SyntaxErrors.Synatx);
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif    
Private Methord#region Private Methord
InBlock.gif        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Add or ssubtract two terms;
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns>Evaluated result</returns>

InBlock.gif        private double EvalExp2() 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
char op;
InBlock.gif            
double result;
InBlock.gif            
double partialResult;
InBlock.gif
InBlock.gif            result 
= EvalExp3();
InBlock.gif
InBlock.gif            
while( ((op=token[0]) ) == '+' || op == '-'
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                GetToken();
InBlock.gif                partialResult 
=  EvalExp3();
InBlock.gif                
switch(op)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
case '+':
InBlock.gif                        result  
+= partialResult;
InBlock.gif                        
break;
InBlock.gif                    
case '-':
InBlock.gif                        result 
-= partialResult;
InBlock.gif                        
break;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Multiply or divide two factors.
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns>Evaluated result</returns>

InBlock.gif        public double EvalExp3()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
char op;
InBlock.gif            
double result;
InBlock.gif            
double partialResult;
InBlock.gif
InBlock.gif            result 
= EvalExp4();
InBlock.gif
InBlock.gif            
while( (op= token[0]) == '*'|| op == '/' || op =='%')
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                GetToken();
InBlock.gif                partialResult 
= EvalExp4();
InBlock.gif                
switch(op)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
case '*':
InBlock.gif                        result 
*=partialResult;
InBlock.gif                        
break;
InBlock.gif                    
case '/':
InBlock.gif                        
if(partialResult == 0.0)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            HandleError(SyntaxErrors.DivByZero);
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        result 
/= partialResult;
InBlock.gif                        
break;
InBlock.gif                    
case '%':
InBlock.gif                        
if(partialResult == 0.0)
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            HandleError(SyntaxErrors.DivByZero);
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        result 
%= partialResult;
InBlock.gif                        
break;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
return result;
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Process an exponent
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        private double EvalExp4()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
double result;
InBlock.gif            
double partialResult;
InBlock.gif            
double ex;
InBlock.gif            
int t;
InBlock.gif
InBlock.gif            result 
= EvalExp5();
InBlock.gif                
InBlock.gif            
if(token =="^" )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                GetToken();
InBlock.gif                partialResult 
= EvalExp4();
InBlock.gif                ex 
= result;
InBlock.gif                
if(partialResult == 0.0 )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    result 
= 1.0;
ExpandedSubBlockEnd.gif                }

InBlock.gif                
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
for(t=(int)partialResult-1; t>0; t--)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        result 
*= ex;
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
//Evaluate a unary + or -
InBlock.gif
        private double EvalExp5()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
double result;
InBlock.gif            
string op;
InBlock.gif
InBlock.gif            op
="";
InBlock.gif            
InBlock.gif            
if( (tokType == TokenTypes.Delimiter) && ( token =="+" ||  token =="-") )
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                op 
= token;
InBlock.gif                GetToken();
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            result 
= EvalExp6();
InBlock.gif
InBlock.gif            
if(op == "-") result = - result;
InBlock.gif
InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private double EvalExp6()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
double result;
InBlock.gif            
if(token=="(")
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                GetToken();
InBlock.gif                result 
= EvalExp2();
InBlock.gif
InBlock.gif                
if(token!=")")
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    HandleError(SyntaxErrors.UnBalparens);
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                GetToken();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                result 
= Atom();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Get the value of a number
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <returns></returns>

InBlock.gif        private double Atom()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
double result = 0.0;
InBlock.gif
InBlock.gif            
switch(tokType)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
case TokenTypes.Number:
InBlock.gif                    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        result  
= Double.Parse(token);
ExpandedSubBlockEnd.gif                    }

InBlock.gif                    
catch(InvalidCastException)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        HandleError( SyntaxErrors.Synatx );
ExpandedSubBlockEnd.gif                    }

InBlock.gif
InBlock.gif                    GetToken();
InBlock.gif                    
break;
InBlock.gif                
default:
InBlock.gif                    HandleError( SyntaxErrors.Synatx );
InBlock.gif                    
break;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Handle an error
InBlock.gif        
/// </summary>
ExpandedSubBlockEnd.gif        
/// <param name="error">index of error</param>

InBlock.gif        void HandleError(SyntaxErrors error)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            String [] err 
= new string[]
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
"Syntax Error",
InBlock.gif                
"Unabalanced Parentheses",
InBlock.gif                
"No Expression Present",
InBlock.gif                
"Division By Zero"
ExpandedSubBlockEnd.gif            }
;
InBlock.gif
InBlock.gif            
throw new ExpressionParserException(err[(int)error]);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Obtain the next token
ExpandedSubBlockEnd.gif        
/// </summary>

InBlock.gif        private void GetToken()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            tokType 
= TokenTypes.None;
InBlock.gif            token 
= "";
InBlock.gif            
InBlock.gif            
//Check for end of expression.
InBlock.gif
            if( expIdx == exp.Length)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                token 
= EOE;
InBlock.gif                
return;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
//Skip over white space
InBlock.gif
            while( expIdx <exp.Length && char.IsWhiteSpace( exp[expIdx] ) ) ++expIdx;
InBlock.gif            
InBlock.gif            
//Trailing whitespace ends expression.
ExpandedSubBlockStart.gifContractedSubBlock.gif
            if( expIdx == exp.Length ) dot.gif{
InBlock.gif                token 
= EOE;
InBlock.gif                
return;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
if( IsDelimiter(exp[expIdx] ) )    //Is operator
ExpandedSubBlockStart.gifContractedSubBlock.gif
            dot.gif{
InBlock.gif                token
+=exp[expIdx];
InBlock.gif                expIdx
++;
InBlock.gif                tokType  
= TokenTypes.Delimiter;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else if (Char.IsLetter(exp[expIdx]))  //Is variable
ExpandedSubBlockStart.gifContractedSubBlock.gif
            dot.gif{
InBlock.gif                
while(!IsDelimiter( exp[expIdx]) )
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    token 
+= exp[expIdx];
InBlock.gif                    expIdx 
++;
InBlock.gif                    
if(expIdx >= exp.Length ) break;
ExpandedSubBlockEnd.gif                }

InBlock.gif                tokType 
= TokenTypes.Variable;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else ifchar.IsDigit(exp[expIdx])) //Is a number
ExpandedSubBlockStart.gifContractedSubBlock.gif
            dot.gif{
InBlock.gif                
while!IsDelimiter(exp[expIdx]))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    token 
+= exp[expIdx];
InBlock.gif                    expIdx 
++;
InBlock.gif                    
if( expIdx >= exp.Length ) break;
ExpandedSubBlockEnd.gif                }

InBlock.gif                tokType 
= TokenTypes.Number;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                token 
= EOE;
InBlock.gif                
return;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
InBlock.gif        
/// Check whether c is  a delimiter
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="c">the checked char</param>
ExpandedSubBlockEnd.gif        
/// <returns>Return true if c is a delimiter, else return false</returns>

InBlock.gif        private static bool IsDelimiter(char c)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if( (" +-/*%^=()".IndexOf(c) !=-1 ))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return true;
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
return false;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif        
ExpandedBlockEnd.gif    }

None.gif
None.gif}
None.gif


ExpressionParserException.cs
None.gifusing System;
None.gif
None.gifnamespace IBMS.Text.Script
ExpandedBlockStart.gif ContractedBlock.gif dot.gif{
ExpandedSubBlockStart.gif ContractedSubBlock.gif    /** <summary>
InBlock.gif    /// Exception class for parsor errors
ExpandedSubBlockEnd.gif    /// </summary>
InBlock.gif    public class ExpressionParserException:Exception
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
ExpandedSubBlockStart.gif ContractedSubBlock.gif        /** <summary>
InBlock.gif        /// Constructor
InBlock.gif        /// </summary>
ExpandedSubBlockEnd.gif        /// <param name="str">error message</param>
InBlock.gif        public ExpressionParserException(string str)
InBlock.gif            :base(str)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            
ExpandedSubBlockEnd.gif        }
InBlock.gif        
ExpandedSubBlockEnd.gif    }
ExpandedBlockEnd.gif}
None.gif

转载于:https://www.cnblogs.com/dyj057/archive/2006/03/22/356143.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值