⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eqcompiler.cs

📁 在LINUX下实现FFT,提供了源代码和编译函数
💻 CS
📖 第 1 页 / 共 3 页
字号:
using System;
using System.Collections;
using System.Runtime.InteropServices;

namespace dotMath
{
	/// <remarks>
	/// Copyright (c) 2001-2004, Stephen Hebert
	/// All rights reserved.
	/// 
	/// 
	/// Redistribution and use in source and binary forms, with or without modification, 
	/// are permitted provided that the following conditions are met:
	/// 
	/// Redistributions of source code must retain the above copyright notice, 
	/// this list of conditions and the following disclaimer. 
	/// 
	/// Redistributions in binary form must reproduce the above 
	/// copyright notice, this list of conditions and the following disclaimer 
	/// in the documentation and/or other materials provided with the distribution. 
	/// 
	/// Neither the name of the .Math, nor the names of its contributors 
	/// may be used to endorse or promote products derived from this software without 
	/// specific prior written permission. 
	/// 
	/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
	/// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
	/// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
	/// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
	/// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
	/// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
	/// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
	/// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
	/// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
	/// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
	/// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	/// 
	/// </remarks>
	/// 

	/// <summary>
	/// EqCompiler is the class that takes the parsed tokens and turns them
	/// into a network of pre-compiled objects that perform the designated
	/// functions.
	/// </summary>
	public class EqCompiler
	{
		private string m_sEquation;
		private CValue m_Function;
		private Parser.Token m_currentToken;
		private Parser.Token m_nextToken;
		private IEnumerator m_enumTokens;
		private SortedList m_slVariables = new SortedList();
		private SortedList m_slFunctions = new SortedList();
		private SortedList m_slOperations = new SortedList();

		private COperator[] m_aOps;


		#region Operations and Compiling Functions

		/// <summary>
		/// CSignNeg provides negative number functionality
		/// within an equation. 
		/// </summary>
		private class CSignNeg : CValue
		{
			CValue m_oValue;

			/// <summary>
			/// CSignNeg constructor:  Grabs onto the assigned
			///		CValue object and retains it for processing
			///		requested operations.
			/// </summary>
			/// <param name="oValue">Child operation this object operates upon.</param>
			public CSignNeg( CValue oValue )
			{
				m_oValue = oValue;
			}

			/// <summary>
			/// GetValue():  Performs the negative operation on the child operation and returns the value.
			/// </summary>
			/// <returns>A double value evaluated and returned with the opposite sign.</returns>
			public override double GetValue()
			{
				return m_oValue.GetValue() * -1;
			}


		}

		/// <summary>
		/// Paren() : This method evaluates Parenthesis in the equation and
		///		insures they are handled properly according to the Order of Operations. Because this is last in the chain,
		///		it also evaluates Variable and Function names.
		/// </summary>
		/// <returns>CValue object that holds an operation.</returns>
		private CValue Paren()
		{
			bool bFunc = false;
			CValue oValue = null;

			if( m_currentToken.ToString() == "(" )
			{
				PositionNextToken();


				oValue = Relational();

				if( m_currentToken.ToString() == "," )
					return oValue;

				if( m_currentToken.ToString() != ")" )
					throw new ApplicationException("Unmatched parenthesis in equation.");

			}
			else
			{
				switch( m_currentToken.TokenType )
				{
					case Parser.CharType.CT_NUMBER:
						oValue = new CNumber( m_currentToken.ToString() );
						break;

					case Parser.CharType.CT_LETTER:
					{
						if( m_nextToken.ToString() == "(" )
						{
							int iIdx = m_slFunctions.IndexOfKey(m_currentToken.ToString());

							if( iIdx < 0 )
								throw new ApplicationException("Function not found - " + m_currentToken.ToString());

							CFunction oFunc = (CFunction)m_slFunctions.GetByIndex( iIdx );

							ArrayList alValues = new ArrayList();

							do
							{
								PositionNextToken();
								oValue = Paren();

								alValues.Add( oValue );
							} while (m_currentToken.ToString() == "," );

							

							bFunc = true;


							oValue = oFunc.CreateInstance(alValues);
						}
						else
							oValue = GetVariableByName( m_currentToken.ToString() );

						break;
					}
				}

			}

			if( !bFunc )
				PositionNextToken();

			return oValue;
			
		}


		/// <summary>
		/// Sign():  This method detects the existence of sign operators before
		///		a number or variable.  
		/// </summary>
		/// <returns>CValue object representing an operation.</returns>
		private CValue Sign()
		{
			bool bNeg = false;
			Parser.Token oToken = null;
			if( m_currentToken == "+" || m_currentToken == "-" )
			{
				oToken = m_currentToken;
				bNeg = (m_currentToken == "-");
				PositionNextToken();
			}
			//CValue oFunc = Function();
			// sdh: should be function when ready.
			CValue oFunc = Paren();


			if( bNeg )
			{
				CheckParms( oToken, oFunc);
				oFunc = new CSignNeg( oFunc );
			}

			return oFunc;

			
		}

		/// <summary>
		/// Power():  Detects the operation to raise one number to the power
		///		of another (a^2).
		/// </summary>
		/// <returns>CValue object representing an operation.</returns>
		private CValue Power()
		{
			CValue oValue = Sign();

			while( m_currentToken == "^" )
			{
				Parser.Token oOp = m_currentToken;

				PositionNextToken();

				CValue oNextVal = Sign();

				CheckParms( oOp, oValue, oNextVal);
				oValue = OpFactory(oOp, oValue, oNextVal );
			}

			return oValue;
		}

		/// <summary>
		/// MultDiv(): Detects the operation to perform multiplication or division.
		/// </summary>
		/// <returns>CValue object representing an operation.</returns>
		private CValue MultDiv()
		{
			CValue oValue = Power();
			
			while( m_currentToken == "*" || m_currentToken == "/" )
			{
				Parser.Token oOp = m_currentToken;

				PositionNextToken();

				CValue oNextVal = Power();

				CheckParms( oOp, oValue, oNextVal);
				oValue = OpFactory( oOp, oValue, oNextVal );
			}

			return oValue;
		}
		
		/// <summary>
		/// AddSub(): Detects the operation to perform addition or substraction.
		/// </summary>
		/// <returns>CValue object representing an operation.</returns>
		private CValue AddSub()
		{
			CValue oValue = MultDiv();
			
			while( m_currentToken == "+" || m_currentToken == "-" )
			{
				Parser.Token oOp = m_currentToken;
				PositionNextToken();

				CValue oNextVal = MultDiv();
				
				CheckParms( oOp, oValue, oNextVal);
				oValue = OpFactory( oOp, oValue, oNextVal );
			}

			return oValue;
		}

		/// <summary>
		/// Relational():  Detects the operation to perform a relational operator (>, <, <=, etc.).
		/// </summary>
		/// <returns>CValue object representing an operation.</returns>
		private CValue Relational()
		{
			CValue oValue = AddSub();

			while (m_currentToken == "&&" ||
				m_currentToken == "||" ||
				m_currentToken == "==" ||
				m_currentToken == "<" ||
				m_currentToken == ">" ||
				m_currentToken == "<=" ||
				m_currentToken == ">=" ||
				m_currentToken == "!=" ||
				m_currentToken == "<>")
			{
				Parser.Token oOp = m_currentToken;
				PositionNextToken();
				CValue oNextVal = Relational();

				CheckParms( oOp, oValue, oNextVal);
				oValue = OpFactory( oOp, oValue, oNextVal );

			}

			return oValue;
		}

		/// <summary>
		/// OpFactor(...): Reads the passed operator, identifies the associated implementation object
		///		and requests an operation object to be used in evaluating the equation.
		/// </summary>
		/// <param name="oSourceOp">Parser.Token object representing the operator in question.</param>
		/// <param name="oValue1">The first value object to be operated on.</param>
		/// <param name="oValue2">The second value object to be operated on.</param>
		/// <returns>CValue object representing an operation.</returns>
		private CValue OpFactory( Parser.Token oSourceOp, CValue oValue1, CValue oValue2 )
		{

			foreach( COperator oOp in m_aOps ) 
			{

				if( oOp.IsMatch( oSourceOp ))
					return oOp.Factory(oValue1, oValue2);
			}

			throw new ApplicationException("Invalid operator in equation.");

		}


		#endregion

		#region Core Base Classes

		/// <summary>
		/// CBalue class:  This base is the basic building block of
		///		all operations, variables, functions, etc..  Any object
		///		may call to a CValue object asking for it to resolve itself
		///		and return it's processed value.
		/// </summary>
		public abstract class CValue
		{
			public abstract double GetValue();
		}


		/// <summary>
		/// CVariable class : Derived from CValue, CVariable implements
		///		a named expression variable, holding the name and associated value.
		///		This object is accessed when an expression is evaluated or when
		///		a user sets a variable value.
		/// </summary>
		public class CVariable : CValue
		{
			private string m_sVarName;
			private double m_dValue;

			/// <summary>
			/// CVariable(string) constructor: Creates the object and holds onto the 
			///		compile-time assigned variable name.
			/// </summary>
			/// <param name="sVarName">Name of the variable within the expression.</param>
			public CVariable( string sVarName )
			{
				m_sVarName = sVarName;
			}

			/// <summary>
			/// CVariable(string,double) constructor: Creates the objects and holds onto the
			///		compile-time assigned variable name and value.
			/// </summary>
			/// <param name="sVarName">string containing the variable name</param>
			/// <param name="dValue">double containing the assigned variable value</param>
			public CVariable( string sVarName, double dValue )
			{
                m_sVarName = sVarName;
			}

			/// <summary>
			/// SetValue(): Allows the setting of the variables value at runtime.
			/// </summary>
			/// <param name="dValue"></param>
			public void SetValue( double dValue )
			{
				m_dValue = dValue;
			}

			/// <summary>
			/// GetValue(): Returns the value of the variable to the calling client.
			/// </summary>
			/// <returns>double</returns>
			public override double GetValue()
			{
				return m_dValue;
			}
		}


		/// <summary>
		/// CNumber Class:  A CValue-derived class that implements a static
		///    numeric value in an expression.
		/// </summary>
		public class CNumber : CValue
		{
			private double m_dValue;

			/// <summary>
			/// CNumber(string) constructor:  take a string representation of a static number
			///		and stores it for future retrieval.
			/// </summary>
			/// <param name="sValue">string/text representation of a number</param>
			public CNumber( string sValue )
			{
				m_dValue = Convert.ToDouble(sValue);
			}

			/// <summary>
			/// CNumber(double) constructor: takes a double represenation of a static number
			/// and stores it for future retrieval.
			/// </summary>
			/// <param name="dValue"></param>
			public CNumber( double dValue )
			{
				m_dValue = dValue;
			}
			
			/// <summary>
			/// GetValue(): returns the static value when called upon.
			/// </summary>
			/// <returns>double</returns>
			public override double GetValue()
			{
                return m_dValue;
			}
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -