|
Hello.
Can you give some examples; While bformula is true?
How to enter hashtable?
|
|
|
|
|
Hi,
I would like to know if it is possible to reuse the source code you posted. What is the license attached to it?
Thanks by advance,
Jerome
|
|
|
|
|
if we divide 4/2 answers Divide by Zero Error
|
|
|
|
|
|
deepedie's RPN Parser and staarkannan's inclusion of ! operator are useful. VB source code equivalent of staarkannan's posting:
Imports System.Collections
Imports System.Text
Imports System.Text.RegularExpressions
#Region "RPN"
Public Class RPNParser
Public Sub New()
End Sub
Public Function EvaluateExpression(szExpr As String, varType As Type, bFormula As Boolean, htValues As Hashtable) As Object
Dim arrExpr As ArrayList = GetPostFixNotation(szExpr, varType, bFormula)
Return EvaluateRPN(arrExpr, varType, htValues)
End Function
Public Function EvaluateExpression(szExpr As String) As Object
Dim myType As Long = 0
Dim arrExpr As ArrayList = GetPostFixNotation(szExpr, myType.[GetType](), False)
Return EvaluateRPN(arrExpr, myType.[GetType](), Nothing)
End Function
#Region "RPN_Parser"
Public Function GetPostFixNotation(szExpr As String, varType As Type, bFormula As Boolean) As ArrayList
Dim stkOp As New Stack()
Dim arrFinalExpr As New ArrayList()
Dim szResult As String = ""
Dim szLastItem As String = ""
Dim bApplyNegative As Boolean = False
Dim tknzr As Tokenizer = Nothing
Select Case varType.ToString()
Case "System.Int32", "System.Int64"
tknzr = New Tokenizer(szExpr, ExpressionType.ET_ARITHMETIC Or ExpressionType.ET_COMPARISON Or ExpressionType.ET_LOGICAL)
Exit Select
Case "System.String"
tknzr = New Tokenizer(szExpr, ExpressionType.ET_COMPARISON)
Exit Select
End Select
For Each token As Token In tknzr
Dim szToken As String = token.Value.Trim()
If szToken.Length = 0 Then
Continue For
End If
Select Case varType.ToString()
Case "System.Int32", "System.Int64"
If Not OperatorHelper.IsOperator(szToken) Then
Dim oprnd As Operand
If szToken.IndexOf("""") <> -1 Then
Dim myStringType As String = ""
oprnd = OperandHelper.CreateOperand(szToken, myStringType.[GetType]())
Else
oprnd = OperandHelper.CreateOperand(szToken, varType)
End If
oprnd.ExtractAndSetValue(szToken, bFormula)
arrFinalExpr.Add(oprnd)
szResult += szToken
szLastItem = szToken
Continue For
End If
Exit Select
Case "System.String"
If Not OperatorHelper.IsComparisonOperator(szToken) Then
Dim oprnd As Operand = OperandHelper.CreateOperand(szToken, varType)
oprnd.ExtractAndSetValue(szToken, bFormula)
arrFinalExpr.Add(oprnd)
szResult += szToken
szLastItem = szToken
Continue For
End If
Exit Select
End Select
Dim szOp As String = szToken
If szOp = "(" Then
stkOp.Push(szOp)
ElseIf szOp = "!" Then
stkOp.Push(szOp)
ElseIf szOp = ")" Then
Dim szTop As String
While (InlineAssignHelper(szTop, DirectCast(stkOp.Pop(), String))) <> "("
Dim oprtr As IOperator = OperatorHelper.CreateOperator(szTop)
arrFinalExpr.Add(oprtr)
szResult += szTop
If stkOp.Count = 0 Then
Throw New RPN_Exception("Unmatched braces!")
End If
End While
ElseIf szOp = "==" Then
If stkOp.Count = 0 OrElse DirectCast(stkOp.Peek(), String) = "(" OrElse OperatorHelper.IsHigherPrecOperator(szOp, DirectCast(stkOp.Peek(), String)) Then
stkOp.Push(szOp)
Else
While stkOp.Count <> 0
If OperatorHelper.IsLowerPrecOperator(szOp, DirectCast(stkOp.Peek(), String)) OrElse OperatorHelper.IsEqualPrecOperator(szOp, DirectCast(stkOp.Peek(), String)) Then
Dim szTop As String = DirectCast(stkOp.Peek(), String)
If szTop = "(" Then
Exit While
End If
szTop = DirectCast(stkOp.Pop(), String)
Dim oprtr As IOperator = OperatorHelper.CreateOperator(szTop)
arrFinalExpr.Add(oprtr)
szResult += szTop
Else
Exit While
End If
End While
stkOp.Push(szOp)
End If
Else
If szOp = "-" AndAlso (Not StringContentCheck.IsAlphaNumeric(szLastItem) OrElse szLastItem = "") Then
bApplyNegative = True
stkOp.Push("~")
Else
If stkOp.Count = 0 OrElse DirectCast(stkOp.Peek(), String) = "(" OrElse OperatorHelper.IsHigherPrecOperator(szOp, DirectCast(stkOp.Peek(), String)) Then
stkOp.Push(szOp)
Else
While stkOp.Count <> 0
If OperatorHelper.IsLowerPrecOperator(szOp, DirectCast(stkOp.Peek(), String)) OrElse OperatorHelper.IsEqualPrecOperator(szOp, DirectCast(stkOp.Peek(), String)) Then
Dim szTop As String = DirectCast(stkOp.Peek(), String)
If szTop = "(" Then
Exit While
End If
szTop = DirectCast(stkOp.Pop(), String)
Dim oprtr As IOperator = OperatorHelper.CreateOperator(szTop)
arrFinalExpr.Add(oprtr)
szResult += szTop
Else
Exit While
End If
End While
stkOp.Push(szOp)
End If
End If
End If
szLastItem = szToken
Next
While stkOp.Count <> 0
Dim szTop As String = DirectCast(stkOp.Pop(), String)
If szTop = "(" Then
Throw New RPN_Exception("Unmatched braces")
End If
Dim oprtr As IOperator = OperatorHelper.CreateOperator(szTop)
arrFinalExpr.Add(oprtr)
szResult += szTop
End While
Return arrFinalExpr
End Function
#End Region
Public Function Convert2String(arrExpr As ArrayList) As String
Dim szResult As String = ""
For Each obj As Object In arrExpr
szResult += obj.ToString()
Next
Return szResult
End Function
#Region "RPN_Evaluator"
Public Function EvaluateRPN(arrExpr As ArrayList, varType As Type, htValues As Hashtable) As Object
Dim stPad As New Stack()
For Each var As Object In arrExpr
Dim op1 As Operand = Nothing
Dim op2 As Operand = Nothing
Dim oprtr As IOperator = Nothing
If TypeOf var Is IOperand Then
stPad.Push(var)
ElseIf TypeOf var Is IOperator Then
If OperatorHelper.IsUnaryOperator(DirectCast(var, [Operator]).ToString()) Then
op1 = DirectCast(stPad.Pop(), Operand)
If htValues IsNot Nothing Then
op1.Value = htValues(op1.Name)
End If
oprtr = DirectCast(var, IOperator)
Dim opRes As IOperand = oprtr.Eval(op1)
stPad.Push(opRes)
Else
op2 = DirectCast(stPad.Pop(), Operand)
If htValues IsNot Nothing Then
op2.Value = htValues(op2.Name)
End If
op1 = DirectCast(stPad.Pop(), Operand)
If htValues IsNot Nothing Then
op1.Value = htValues(op1.Name)
End If
oprtr = DirectCast(var, IOperator)
Dim opRes As IOperand = oprtr.Eval(op1, op2)
stPad.Push(opRes)
End If
End If
Next
Return DirectCast(stPad.Pop(), Operand).Value
End Function
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
#End Region
End Class
#End Region
#Region "UtilClasses"
<Flags()> _
Public Enum ExpressionType
ET_ARITHMETIC = &H1
ET_COMPARISON = &H2
ET_LOGICAL = &H4
End Enum
Public Enum TokenType
TT_OPERATOR
TT_OPERAND
End Enum
Public Class Token
Public Sub New(szValue As String)
m_szValue = szValue
End Sub
Public ReadOnly Property Value() As String
Get
Return m_szValue
End Get
End Property
Private m_szValue As String
End Class
Public Class Tokenizer
Implements IEnumerable
Public Sub New(szExpression As String)
Me.New(szExpression, ExpressionType.ET_ARITHMETIC Or ExpressionType.ET_COMPARISON Or ExpressionType.ET_LOGICAL)
End Sub
Public Sub New(szExpression As String, exType As ExpressionType)
m_szExpression = szExpression
m_exType = exType
m_RegEx = New Regex(OperatorHelper.GetOperatorsRegEx(m_exType))
m_strarrTokens = SplitExpression(szExpression)
End Sub
Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return New TokenEnumerator(m_strarrTokens)
End Function
Public Function SplitExpression(szExpression As String) As String()
Return m_RegEx.Split(szExpression)
End Function
Private m_exType As ExpressionType
Private m_szExpression As String
Private m_strarrTokens As String()
Private m_RegEx As Regex
End Class
Public Class TokenEnumerator
Implements IEnumerator
Private m_Token As Token
Private m_nIdx As Integer
Private m_strarrTokens As String()
Public Sub New(strarrTokens As String())
m_strarrTokens = strarrTokens
Reset()
End Sub
Public ReadOnly Property Current() As Object Implements IEnumerator.Current
Get
Return m_Token
End Get
End Property
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
If m_nIdx >= m_strarrTokens.Length Then
Return False
End If
m_Token = New Token(m_strarrTokens(m_nIdx))
m_nIdx += 1
Return True
End Function
Public Sub Reset() Implements IEnumerator.Reset
m_nIdx = 0
End Sub
End Class
#Region "Exceptions"
Public Class RPN_Exception
Inherits ApplicationException
Public Sub New()
End Sub
Public Sub New(szMessage As String)
MyBase.New(szMessage)
End Sub
Public Sub New(szMessage As String, innerException As Exception)
MyBase.New(szMessage, innerException)
End Sub
End Class
#End Region
#End Region
#Region "Interfaces"
ublic Interface IOperand
End Interface
Public Interface IOperator
Function Eval(lhs As IOperand, rhs As IOperand) As IOperand
Function Eval(lhs As IOperand) As IOperand
End Interface
Public Interface IArithmeticOperations
Function Plus(rhs As IOperand) As IOperand
Function Minus(rhs As IOperand) As IOperand
Function Multiply(rhs As IOperand) As IOperand
Function Divide(rhs As IOperand) As IOperand
Function Modulo(rhs As IOperand) As IOperand
Function [Not]() As IOperand
Function Negate() As IOperand
End Interface
Public Interface IComparisonOperations
Function EqualTo(rhs As IOperand) As IOperand
Function NotEqualTo(rhs As IOperand) As IOperand
Function LessThan(rhs As IOperand) As IOperand
Function LessThanOrEqualTo(rhs As IOperand) As IOperand
Function GreaterThan(rhs As IOperand) As IOperand
Function GreaterThanOrEqualTo(rhs As IOperand) As IOperand
End Interface
Public Interface ILogicalOperations
Function [OR](rhs As IOperand) As IOperand
Function [AND](rhs As IOperand) As IOperand
End Interface
#End Region
#Region "Operands"
Public MustInherit Class Operand
Implements IOperand
Public Sub New(szVarName As String, varValue As Object)
m_szVarName = szVarName
m_VarValue = varValue
End Sub
Public Sub New(szVarName As String)
m_szVarName = szVarName
End Sub
Public Overrides Function ToString() As String
Return m_szVarName
End Function
Public MustOverride Sub ExtractAndSetValue(szValue As String, bFormula As Boolean)
Public Property Name() As String
Get
Return m_szVarName
End Get
Set(value As String)
m_szVarName = value
End Set
End Property
Public Property Value() As Object
Get
Return m_VarValue
End Get
Set(value As Object)
m_VarValue = value
End Set
End Property
Protected m_szVarName As String = ""
Protected m_VarValue As Object = Nothing
End Class
Public Class LongOperand
Inherits Operand
Implements IArithmeticOperations
Implements IComparisonOperations
Public Sub New(szVarName As String, varValue As Object)
MyBase.New(szVarName, varValue)
End Sub
Public Sub New(szVarName As String)
MyBase.New(szVarName)
End Sub
Public Overrides Function ToString() As String
Return m_szVarName
End Function
Public Overrides Sub ExtractAndSetValue(szValue As String, bFormula As Boolean)
Select Case szValue
Case "true"
szValue = "1"
m_VarValue = If(Not bFormula, Convert.ToInt64(szValue), 0)
Exit Select
Case "false"
szValue = "0"
m_VarValue = If(Not bFormula, Convert.ToInt64(szValue), 0)
Exit Select
Case Else
m_VarValue = If(Not bFormula, Convert.ToInt64(szValue), 0)
Exit Select
End Select
End Sub
Public Function Plus(rhs As IOperand) As IOperand Implements IArithmeticOperations.Plus
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.Plus : rhs")
End If
Dim oprResult As New LongOperand("Result", Type.[GetType]("System.Int64"))
oprResult.Value = CLng(Me.Value) + CLng(DirectCast(rhs, Operand).Value)
Return oprResult
End Function
Public Function Minus(rhs As IOperand) As IOperand Implements IArithmeticOperations.Minus
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.Minus : rhs")
End If
Dim oprResult As New LongOperand("Result", Type.[GetType]("System.Int64"))
oprResult.Value = CLng(Me.Value) - CLng(DirectCast(rhs, Operand).Value)
Return oprResult
End Function
Public Function Multiply(rhs As IOperand) As IOperand Implements IArithmeticOperations.Multiply
If Not (TypeOf rhs Is LongOperand) Then
Throw New ArgumentException("Argument invalid in LongOperand.Multiply : rhs")
End If
Dim oprResult As New LongOperand("Result", Type.[GetType]("System.Int64"))
oprResult.Value = CLng(Me.Value) * CLng(DirectCast(rhs, Operand).Value)
Return oprResult
End Function
Public Function Negate() As IOperand Implements IArithmeticOperations.Negate
Dim oprResult As New LongOperand("Result", Type.[GetType]("System.Int64"))
oprResult.Value = CLng(Me.Value) * -1
Return oprResult
End Function
Public Function [Not]() As IOperand Implements IArithmeticOperations.[Not]
Dim oprResult As New BoolOperand("Result", Type.[GetType]("System.Boolean"))
Select Case Convert.ToString(Me.Value)
Case "0"
oprResult.Value = Not (False)
Exit Select
Case "1"
oprResult.Value = Not (True)
Exit Select
Case Else
Exit Select
End Select
Return oprResult
End Function
Public Function Divide(rhs As IOperand) As IOperand Implements IArithmeticOperations.Divide
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.Divide : rhs")
End If
Dim oprResult As New LongOperand("Result", Type.[GetType]("System.Int64"))
oprResult.Value = CLng(Me.Value) \ CLng(DirectCast(rhs, Operand).Value)
Return oprResult
End Function
Public Function Modulo(rhs As IOperand) As IOperand Implements IArithmeticOperations.Modulo
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.Modulo : rhs")
End If
Dim oprResult As New LongOperand("Result", Type.[GetType]("System.Int64"))
oprResult.Value = CLng(Me.Value) Mod CLng(DirectCast(rhs, Operand).Value)
Return oprResult
End Function
Public Function EqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.EqualTo
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.== : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = CLng(Me.Value) = CLng(DirectCast(rhs, Operand).Value)
Return oprResult
End Function
Public Function NotEqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.NotEqualTo
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.!= : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((CLng(Me.Value) <> CLng(DirectCast(rhs, Operand).Value)), True, False)
Return oprResult
End Function
Public Function LessThan(rhs As IOperand) As IOperand Implements IComparisonOperations.LessThan
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.< : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((CLng(Me.Value) < CLng(DirectCast(rhs, Operand).Value)), True, False)
Return oprResult
End Function
Public Function LessThanOrEqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.LessThanOrEqualTo
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.<= : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((CLng(Me.Value) <= CLng(DirectCast(rhs, Operand).Value)), True, False)
Return oprResult
End Function
Public Function GreaterThan(rhs As IOperand) As IOperand Implements IComparisonOperations.GreaterThan
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.> : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((CLng(Me.Value) > CLng(DirectCast(rhs, Operand).Value)), True, False)
Return oprResult
End Function
Public Function GreaterThanOrEqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.GreaterThanOrEqualTo
If Not (TypeOf rhs Is LongOperand) Then
Throw New RPN_Exception("Argument invalid in LongOperand.>= : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((CLng(Me.Value) >= CLng(DirectCast(rhs, Operand).Value)), True, False)
Return oprResult
End Function
End Class
Public Class BoolOperand
Inherits Operand
Implements ILogicalOperations
Public Sub New(szVarName As String, varValue As Object)
MyBase.New(szVarName, varValue)
End Sub
Public Sub New(szVarName As String)
MyBase.New(szVarName)
End Sub
Public Overrides Function ToString() As String
Return Me.Value.ToString()
End Function
Public Overrides Sub ExtractAndSetValue(szValue As String, bFormula As Boolean)
m_VarValue = If(Not bFormula, Convert.ToBoolean(szValue), False)
End Sub
Public Function [AND](rhs As IOperand) As IOperand Implements ILogicalOperations.[AND]
If Not (TypeOf rhs Is BoolOperand) Then
Throw New RPN_Exception("Argument invalid in BoolOperand.&& : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((CBool(Me.Value) AndAlso CBool(DirectCast(rhs, Operand).Value)), True, False)
Return oprResult
End Function
Public Function [OR](rhs As IOperand) As IOperand Implements ILogicalOperations.[OR]
If Not (TypeOf rhs Is BoolOperand) Then
Throw New RPN_Exception("Argument invalid in BoolOperand.|| : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((CBool(Me.Value) OrElse CBool(DirectCast(rhs, Operand).Value)), True, False)
Return oprResult
End Function
Public Function Negate() As IOperand
Dim oprResult As New LongOperand("Result", Type.[GetType]("System.Int64"))
oprResult.Value = CLng(Me.Value) * -1
Return oprResult
End Function
Public Function [Not]() As IOperand
Dim oprResult As New BoolOperand("Result", Type.[GetType]("System.Boolean"))
Select Case Convert.ToString(Me.Value)
Case "False"
oprResult.Value = Not (False)
Exit Select
Case "True"
oprResult.Value = Not (True)
Exit Select
Case Else
Exit Select
End Select
Return oprResult
End Function
End Class
Public Class OperandHelper
Public Shared Function CreateOperand(szVarName As String, varType As Type, varValue As Object) As Operand
Dim oprResult As Operand = Nothing
Dim IsBoolean As Boolean
If [Boolean].TryParse(szVarName, IsBoolean) Then
oprResult = New BoolOperand(szVarName, varValue)
Return oprResult
Else
Select Case varType.ToString()
Case "System.Int32", "System.Int64"
oprResult = New LongOperand(szVarName, varValue)
Return oprResult
Case "System.String"
oprResult = New StringOperand(szVarName, varValue)
Return oprResult
End Select
End If
Throw New RPN_Exception("Unhandled type : " & varType.ToString())
End Function
Public Shared Function CreateOperand(szVarName As String, varType As Type) As Operand
Return OperandHelper.CreateOperand(szVarName, varType, Nothing)
End Function
End Class
Public Class StringOperand
Inherits Operand
Implements IComparisonOperations
Public Sub New(szVarName As String, varValue As Object)
MyBase.New(szVarName, varValue)
End Sub
Public Sub New(szVarName As String)
MyBase.New(szVarName)
End Sub
Public Overrides Function ToString() As String
Return m_szVarName
End Function
Public Overrides Sub ExtractAndSetValue(szValue As String, bFormula As Boolean)
m_VarValue = If(Not bFormula, Convert.ToString(szValue), "")
End Sub
Public Function EqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.EqualTo
If Not (TypeOf rhs Is StringOperand) Then
Throw New RPN_Exception("Argument invalid in StringOperand.== : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = DirectCast(Me.Value, String) = DirectCast(DirectCast(rhs, Operand).Value, String)
Return oprResult
End Function
Public Function NotEqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.NotEqualTo
If Not (TypeOf rhs Is StringOperand) Then
Throw New RPN_Exception("Argument invalid in StringOperand.!= : rhs")
End If
Dim oprResult As New BoolOperand("Result")
oprResult.Value = If((DirectCast(Me.Value, String) <> DirectCast(DirectCast(rhs, Operand).Value, String)), True, False)
Return oprResult
End Function
Public Function LessThan(rhs As IOperand) As IOperand Implements IComparisonOperations.LessThan
Throw New RPN_Exception("LessThan operator is invalid for string")
End Function
Public Function LessThanOrEqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.LessThanOrEqualTo
Throw New RPN_Exception("LessThanOrEqualTo operator is invalid for string")
End Function
Public Function GreaterThan(rhs As IOperand) As IOperand Implements IComparisonOperations.GreaterThan
Throw New RPN_Exception("GreaterThan operator is invalid for string")
End Function
Public Function GreaterThanOrEqualTo(rhs As IOperand) As IOperand Implements IComparisonOperations.GreaterThanOrEqualTo
Throw New RPN_Exception("GreaterThanOrEqualTo operator is invalid for string")
End Function
End Class
#End Region
#Region "Operators"
Public MustInherit Class [Operator]
Implements IOperator
Public Sub New(cOperator As Char)
m_szOperator = New [String](cOperator, 1)
End Sub
Public Sub New(szOperator As String)
m_szOperator = szOperator
End Sub
Public Overrides Function ToString() As String
Return m_szOperator
End Function
Public MustOverride Function Eval(lhs As IOperand, rhs As IOperand) As IOperand Implements IOperator.Eval
Public MustOverride Function Eval(lhs As IOperand) As IOperand Implements IOperator.Eval
Public Property Value() As String
Get
Return m_szOperator
End Get
Set(value As String)
m_szOperator = value
End Set
End Property
Protected m_szOperator As String = ""
End Class
Public Class ArithmeticOperator
Inherits [Operator]
Public Sub New(cOperator As Char)
MyBase.New(cOperator)
End Sub
Public Sub New(szOperator As String)
MyBase.New(szOperator)
End Sub
Public Overrides Function Eval(lhs As IOperand, rhs As IOperand) As IOperand
If Not (TypeOf lhs Is IArithmeticOperations) Then
Throw New RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs")
End If
Select Case m_szOperator
Case "+"
Return DirectCast(lhs, IArithmeticOperations).Plus(rhs)
Case "-"
Return DirectCast(lhs, IArithmeticOperations).Minus(rhs)
Case "*"
Return DirectCast(lhs, IArithmeticOperations).Multiply(rhs)
Case "/"
Return DirectCast(lhs, IArithmeticOperations).Divide(rhs)
Case "%"
Return DirectCast(lhs, IArithmeticOperations).Modulo(rhs)
End Select
Throw New RPN_Exception("Unsupported Arithmetic operation " & m_szOperator)
End Function
Public Overrides Function Eval(lhs As IOperand) As IOperand
If TypeOf lhs Is IArithmeticOperations Then
Select Case m_szOperator
Case "~"
Return DirectCast(lhs, IArithmeticOperations).Negate()
Case "!"
Return DirectCast(lhs, IArithmeticOperations).[Not]()
End Select
ElseIf TypeOf lhs Is BoolOperand Then
Select Case m_szOperator
Case "~"
Return DirectCast(lhs, BoolOperand).Negate()
Case "!"
Return DirectCast(lhs, BoolOperand).[Not]()
End Select
End If
Throw New RPN_Exception("Unsupported Arithmetic operation " & m_szOperator)
End Function
End Class
Public Class ComparisonOperator
Inherits [Operator]
Public Sub New(cOperator As Char)
MyBase.New(cOperator)
End Sub
Public Sub New(szOperator As String)
MyBase.New(szOperator)
End Sub
Public Overrides Function Eval(lhs As IOperand) As IOperand
Return Nothing
End Function
Public Overrides Function Eval(lhs As IOperand, rhs As IOperand) As IOperand
If Not (TypeOf lhs Is IComparisonOperations) Then
Throw New RPN_Exception("Argument invalid in ComparisonOperator.Eval - Invalid Expression : lhs")
End If
Select Case m_szOperator
Case "=="
Return DirectCast(lhs, IComparisonOperations).EqualTo(rhs)
Case "!="
Return DirectCast(lhs, IComparisonOperations).NotEqualTo(rhs)
Case "<"
Return DirectCast(lhs, IComparisonOperations).LessThan(rhs)
Case "<="
Return DirectCast(lhs, IComparisonOperations).LessThanOrEqualTo(rhs)
Case ">"
Return DirectCast(lhs, IComparisonOperations).GreaterThan(rhs)
Case ">="
Return DirectCast(lhs, IComparisonOperations).GreaterThanOrEqualTo(rhs)
End Select
Throw New RPN_Exception("Unsupported Comparison operation " & m_szOperator)
End Function
End Class
Public Class LogicalOperator
Inherits [Operator]
Public Sub New(cOperator As Char)
MyBase.New(cOperator)
End Sub
Public Sub New(szOperator As String)
MyBase.New(szOperator)
End Sub
Public Overrides Function Eval(lhs As IOperand) As IOperand
Return Nothing
End Function
Public Overrides Function Eval(lhs As IOperand, rhs As IOperand) As IOperand
If Not (TypeOf lhs Is ILogicalOperations) Then
Throw New RPN_Exception("Argument invalid in LogicalOperator.Eval - Invalid Expression : lhs")
End If
Select Case m_szOperator
Case "&&"
Return DirectCast(lhs, ILogicalOperations).[AND](rhs)
Case "||"
Return DirectCast(lhs, ILogicalOperations).[OR](rhs)
End Select
Throw New RPN_Exception("Unsupported Logical operation " & m_szOperator)
End Function
End Class
Public Class OperatorHelper
Public Shared Function CreateOperator(szOperator As String) As IOperator
Dim oprtr As IOperator = Nothing
If OperatorHelper.IsArithmeticOperator(szOperator) Then
oprtr = New ArithmeticOperator(szOperator)
Return oprtr
End If
If OperatorHelper.IsComparisonOperator(szOperator) Then
oprtr = New ComparisonOperator(szOperator)
Return oprtr
End If
If OperatorHelper.IsLogicalOperator(szOperator) Then
oprtr = New LogicalOperator(szOperator)
Return oprtr
End If
Throw New RPN_Exception("Unhandled Operator : " & szOperator)
End Function
Public Shared Function CreateOperator(cOperator As Char) As IOperator
Return CreateOperator(New String(cOperator, 1))
End Function
Public Shared Function IsOperator(currentOp As String) As Boolean
Dim nPos As Integer = Array.IndexOf(m_AllOps, currentOp.Trim())
If nPos <> -1 Then
Return True
Else
Return False
End If
End Function
Public Shared Function IsUnaryOperator(currentOp As String) As Boolean
Dim nPos As Integer = Array.IndexOf(m_AllUnaryOps, currentOp.Trim())
If nPos <> -1 Then
Return True
Else
Return False
End If
End Function
Public Shared Function IsArithmeticOperator(currentOp As String) As Boolean
Dim nPos As Integer = Array.IndexOf(m_AllArithmeticOps, currentOp)
If nPos <> -1 Then
Return True
Else
Return False
End If
End Function
Public Shared Function IsComparisonOperator(currentOp As String) As Boolean
Dim nPos As Integer = Array.IndexOf(m_AllComparisonOps, currentOp)
If nPos <> -1 Then
Return True
Else
Return False
End If
End Function
Public Shared Function IsLogicalOperator(currentOp As String) As Boolean
Dim nPos As Integer = Array.IndexOf(m_AllLogicalOps, currentOp)
If nPos <> -1 Then
Return True
Else
Return False
End If
End Function
#Region "Precedence"
Public Shared Function IsLowerPrecOperator(currentOp As String, prevOp As String) As Boolean
Dim nCurrIdx As Integer
Dim nPrevIdx As Integer
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, nCurrIdx, nPrevIdx)
If nCurrIdx < nPrevIdx Then
Return True
End If
Return False
End Function
Public Shared Function IsHigherPrecOperator(currentOp As String, prevOp As String) As Boolean
Dim nCurrIdx As Integer
Dim nPrevIdx As Integer
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, nCurrIdx, nPrevIdx)
If nCurrIdx > nPrevIdx Then
Return True
End If
Return False
End Function
Public Shared Function IsEqualPrecOperator(currentOp As String, prevOp As String) As Boolean
Dim nCurrIdx As Integer
Dim nPrevIdx As Integer
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, nCurrIdx, nPrevIdx)
If nCurrIdx = nPrevIdx Then
Return True
End If
Return False
End Function
Private Shared Sub GetCurrentAndPreviousIndex(allOps As String(), currentOp As String, prevOp As String, ByRef nCurrIdx As Integer, ByRef nPrevIdx As Integer)
nCurrIdx = -1
nPrevIdx = -1
For nIdx As Integer = 0 To allOps.Length - 1
If allOps(nIdx) = currentOp Then
nCurrIdx = nIdx
End If
If allOps(nIdx) = prevOp Then
nPrevIdx = nIdx
End If
If nPrevIdx <> -1 AndAlso nCurrIdx <> -1 Then
Exit For
End If
Next
If nCurrIdx = -1 Then
Throw New RPN_Exception("Unknown operator - " & currentOp)
End If
If nPrevIdx = -1 Then
Throw New RPN_Exception("Unknown operator - " & prevOp)
End If
End Sub
#End Region
#Region "RegEx"
Public Shared Function GetOperatorsRegEx(exType As ExpressionType) As String
Dim strRegex As New StringBuilder()
If (exType And ExpressionType.ET_ARITHMETIC).Equals(ExpressionType.ET_ARITHMETIC) Then
If strRegex.Length = 0 Then
strRegex.Append(m_szArthmtcRegEx)
Else
strRegex.Append("|" & m_szArthmtcRegEx)
End If
End If
If (exType And ExpressionType.ET_COMPARISON).Equals(ExpressionType.ET_COMPARISON) Then
If strRegex.Length = 0 Then
strRegex.Append(m_szCmprsnRegEx)
Else
strRegex.Append("|" & m_szCmprsnRegEx)
End If
End If
If (exType And ExpressionType.ET_LOGICAL).Equals(ExpressionType.ET_LOGICAL) Then
If strRegex.Length = 0 Then
strRegex.Append(m_szLgclRegEx)
Else
strRegex.Append("|" & m_szLgclRegEx)
End If
End If
If strRegex.Length = 0 Then
Throw New RPN_Exception("Invalid combination of ExpressionType value")
End If
Return "(" & strRegex.ToString() & ")"
End Function
Shared m_szArthmtcRegEx As String = "[+\-*/%()]{1}"
Shared m_szCmprsnRegEx As String = "[=<>!]{1,2}"
Shared m_szLgclRegEx As String = "[&|]{2}"
#End Region
Public Shared ReadOnly Property AllOperators() As String()
Get
Return m_AllOps
End Get
End Property
Shared m_AllOps As String() = {"||", "&&", "|", "^", "&", "==", _
"!=", "<", "<=", ">", ">=", "+", _
"-", "*", "/", "~", "%", "(", _
")", "!"}
Shared m_AllArithmeticOps As String() = {"+", "-", "~", "*", "/", "%", _
"!"}
Shared m_AllComparisonOps As String() = {"==", "!=", "<", "<=", ">", ">="}
Shared m_AllLogicalOps As String() = {"&&", "||"}
Shared m_AllUnaryOps As String() = {"~", "!"}
End Class
#End Region
#Region "TODO List"
TODO: Support for unary operators
#End Region
#Region "Content check"
ublic Class StringContentCheck
Public Shared Function IsNaturalNumber(strNumber As [String]) As Boolean
Dim objNotNaturalPattern As New Regex("[^0-9]")
Dim objNaturalPattern As New Regex("0*[1-9][0-9]*")
Return Not objNotNaturalPattern.IsMatch(strNumber) AndAlso objNaturalPattern.IsMatch(strNumber)
End Function
Public Shared Function IsWholeNumber(strNumber As [String]) As Boolean
Dim objNotWholePattern As New Regex("[^0-9]")
Return Not objNotWholePattern.IsMatch(strNumber)
End Function
Public Shared Function IsInteger(strNumber As [String]) As Boolean
Dim objNotIntPattern As New Regex("[^0-9-]")
Dim objIntPattern As New Regex("^-[0-9]+$|^[0-9]+$")
Return Not objNotIntPattern.IsMatch(strNumber) AndAlso objIntPattern.IsMatch(strNumber)
End Function
Public Shared Function IsPositiveNumber(strNumber As [String]) As Boolean
Dim objNotPositivePattern As New Regex("[^0-9.]")
Dim objPositivePattern As New Regex("^[.][0-9]+$|[0-9]*[.]*[0-9]+$")
Dim objTwoDotPattern As New Regex("[0-9]*[.][0-9]*[.][0-9]*")
Return Not objNotPositivePattern.IsMatch(strNumber) AndAlso objPositivePattern.IsMatch(strNumber) AndAlso Not objTwoDotPattern.IsMatch(strNumber)
End Function
Public Shared Function IsNumber(strNumber As [String]) As Boolean
Dim objNotNumberPattern As New Regex("[^0-9.-]")
Dim objTwoDotPattern As New Regex("[0-9]*[.][0-9]*[.][0-9]*")
Dim objTwoMinusPattern As New Regex("[0-9]*[-][0-9]*[-][0-9]*")
Dim strValidRealPattern As [String] = "^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$"
Dim strValidIntegerPattern As [String] = "^([-]|[0-9])[0-9]*$"
Dim objNumberPattern As New Regex("(" & strValidRealPattern & ")|(" & strValidIntegerPattern & ")")
Return Not objNotNumberPattern.IsMatch(strNumber) AndAlso Not objTwoDotPattern.IsMatch(strNumber) AndAlso Not objTwoMinusPattern.IsMatch(strNumber) AndAlso objNumberPattern.IsMatch(strNumber)
End Function
Public Shared Function IsAlpha(strToCheck As [String]) As Boolean
Dim objAlphaPattern As New Regex("[^a-zA-Z ]")
Return Not objAlphaPattern.IsMatch(strToCheck)
End Function
Public Shared Function IsAlphaNumeric(strToCheck As [String]) As Boolean
Dim objAlphaNumericPattern As New Regex("[^a-zA-Z0-9 ]")
Return Not objAlphaNumericPattern.IsMatch(strToCheck)
End Function
End Class
#End Region
Usage example:
Dim p As RPNParser = New RPNParser
Dim testString as String = "1 != 2"
Textbox1.Text = p.EvaluateExpression(testString)
Expected result "True".
You may need to use also this line:
Imports RPNParser
This code functioned properly on VB 2010 Express .NET Framework 4.
modified 21-Mar-19 15:12pm.
|
|
|
|
|
Hello
I am not able to parse string with condtional operator.
ex - ((3+4>5)? 5 : 8
Please guide we can implement this .
Thanks
|
|
|
|
|
|
I thank for your code. I have made some changes in this code to make use on Not (!) Operator and other Unary operators and string comparisions etc.,. Here is the code.
using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
#region RPN
public class RPNParser
{
public RPNParser()
{
}
public object EvaluateExpression(string szExpr, Type varType, bool bFormula, Hashtable htValues)
{
ArrayList arrExpr = GetPostFixNotation(szExpr, varType, bFormula);
return EvaluateRPN(arrExpr, varType, htValues);
}
public object EvaluateExpression(string szExpr)
{
long myType = 0;
ArrayList arrExpr = GetPostFixNotation(szExpr, myType.GetType(), false);
return EvaluateRPN(arrExpr, myType.GetType(), null);
}
#region RPN_Parser
public ArrayList GetPostFixNotation(string szExpr, Type varType, bool bFormula)
{
Stack stkOp = new Stack();
ArrayList arrFinalExpr = new ArrayList();
string szResult = "";
string szLastItem = "";
bool bApplyNegative = false;
Tokenizer tknzr = null;
switch (varType.ToString())
{
case "System.Int32":
case "System.Int64":
tknzr = new Tokenizer(szExpr, ExpressionType.ET_ARITHMETIC |
ExpressionType.ET_COMPARISON |
ExpressionType.ET_LOGICAL);
break;
case "System.String":
tknzr = new Tokenizer(szExpr, ExpressionType.ET_COMPARISON);
break;
}
foreach (Token token in tknzr)
{
string szToken = token.Value.Trim();
if (szToken.Length == 0)
continue;
switch (varType.ToString())
{
case "System.Int32":
case "System.Int64":
if (!OperatorHelper.IsOperator(szToken))
{
Operand oprnd;
if (szToken.IndexOf("\"") != -1)
{
string myStringType = "";
oprnd = OperandHelper.CreateOperand(szToken, myStringType.GetType());
}
else oprnd = OperandHelper.CreateOperand(szToken, varType);
oprnd.ExtractAndSetValue(szToken, bFormula);
arrFinalExpr.Add(oprnd);
szResult += szToken;
szLastItem = szToken;
continue;
}
break;
case "System.String":
if (!OperatorHelper.IsComparisonOperator(szToken))
{
Operand oprnd = OperandHelper.CreateOperand(szToken, varType);
oprnd.ExtractAndSetValue(szToken, bFormula);
arrFinalExpr.Add(oprnd);
szResult += szToken;
szLastItem = szToken;
continue;
}
break;
}
string szOp = szToken;
if (szOp == "(")
{
stkOp.Push(szOp);
}
else if (szOp == "!")
{
stkOp.Push(szOp);
}
else if (szOp == ")")
{
string szTop;
while ((szTop = (string)stkOp.Pop()) != "(")
{
IOperator oprtr = OperatorHelper.CreateOperator(szTop);
arrFinalExpr.Add(oprtr);
szResult += szTop;
if (stkOp.Count == 0)
throw new RPN_Exception("Unmatched braces!");
}
}
else if (szOp == "==")
{
if (stkOp.Count == 0 || (string)stkOp.Peek() == "("
|| OperatorHelper.IsHigherPrecOperator(szOp, (string)stkOp.Peek()))
{
stkOp.Push(szOp);
}
else
{
while (stkOp.Count != 0)
{
if (OperatorHelper.IsLowerPrecOperator(szOp, (string)stkOp.Peek())
|| OperatorHelper.IsEqualPrecOperator(szOp, (string)stkOp.Peek()))
{
string szTop = (string)stkOp.Peek();
if (szTop == "(")
break;
szTop = (string)stkOp.Pop();
IOperator oprtr = OperatorHelper.CreateOperator(szTop);
arrFinalExpr.Add(oprtr);
szResult += szTop;
}
else
break;
}
stkOp.Push(szOp);
}
}
else
{
if (szOp == "-" && (!StringContentCheck.IsAlphaNumeric(szLastItem) || szLastItem == ""))
{
bApplyNegative = true;
stkOp.Push("~");
}
else
{
if (stkOp.Count == 0 || (string)stkOp.Peek() == "("
|| OperatorHelper.IsHigherPrecOperator(szOp, (string)stkOp.Peek()))
{
stkOp.Push(szOp);
}
else
{
while (stkOp.Count != 0)
{
if (OperatorHelper.IsLowerPrecOperator(szOp, (string)stkOp.Peek())
|| OperatorHelper.IsEqualPrecOperator(szOp, (string)stkOp.Peek()))
{
string szTop = (string)stkOp.Peek();
if (szTop == "(")
break;
szTop = (string)stkOp.Pop();
IOperator oprtr = OperatorHelper.CreateOperator(szTop);
arrFinalExpr.Add(oprtr);
szResult += szTop;
}
else
break;
}
stkOp.Push(szOp);
}
}
}
szLastItem = szToken;
}
while (stkOp.Count != 0)
{
string szTop = (string)stkOp.Pop();
if (szTop == "(")
throw new RPN_Exception("Unmatched braces");
IOperator oprtr = OperatorHelper.CreateOperator(szTop);
arrFinalExpr.Add(oprtr);
szResult += szTop;
}
return arrFinalExpr;
}
#endregion
public string Convert2String(ArrayList arrExpr)
{
string szResult = "";
foreach (object obj in arrExpr)
{
szResult += obj.ToString();
}
return szResult;
}
#region RPN_Evaluator
public object EvaluateRPN(ArrayList arrExpr, Type varType, Hashtable htValues)
{
Stack stPad = new Stack();
foreach (object var in arrExpr)
{
Operand op1 = null;
Operand op2 = null;
IOperator oprtr = null;
if (var is IOperand)
{
stPad.Push(var);
}
else if (var is IOperator)
{
if (OperatorHelper.IsUnaryOperator(((Operator)var).ToString()))
{
op1 = (Operand)stPad.Pop();
if (htValues != null)
{
op1.Value = htValues[op1.Name];
}
oprtr = (IOperator)var;
IOperand opRes = oprtr.Eval(op1);
stPad.Push(opRes);
}
else
{
op2 = (Operand)stPad.Pop();
if (htValues != null)
{
op2.Value = htValues[op2.Name];
}
op1 = (Operand)stPad.Pop();
if (htValues != null)
{
op1.Value = htValues[op1.Name];
}
oprtr = (IOperator)var;
IOperand opRes = oprtr.Eval(op1, op2);
stPad.Push(opRes);
}
}
}
return ((Operand)stPad.Pop()).Value;
}
#endregion
}
#endregion
#region UtilClasses
[Flags]
public enum ExpressionType
{
ET_ARITHMETIC = 0x0001,
ET_COMPARISON = 0x0002,
ET_LOGICAL = 0x0004
}
public enum TokenType
{
TT_OPERATOR,
TT_OPERAND
}
public class Token
{
public Token(string szValue)
{
m_szValue = szValue;
}
public string Value
{
get
{
return m_szValue;
}
}
string m_szValue;
}
public class Tokenizer : IEnumerable
{
public Tokenizer(string szExpression)
: this(szExpression, ExpressionType.ET_ARITHMETIC |
ExpressionType.ET_COMPARISON |
ExpressionType.ET_LOGICAL)
{
}
public Tokenizer(string szExpression, ExpressionType exType)
{
m_szExpression = szExpression;
m_exType = exType;
m_RegEx = new Regex(OperatorHelper.GetOperatorsRegEx(m_exType));
m_strarrTokens = SplitExpression(szExpression);
}
public IEnumerator GetEnumerator()
{
return new TokenEnumerator(m_strarrTokens);
}
public string[] SplitExpression(string szExpression)
{
return m_RegEx.Split(szExpression);
}
ExpressionType m_exType;
string m_szExpression;
string[] m_strarrTokens;
Regex m_RegEx;
}
public class TokenEnumerator : IEnumerator
{
Token m_Token;
int m_nIdx;
string[] m_strarrTokens;
public TokenEnumerator(string[] strarrTokens)
{
m_strarrTokens = strarrTokens;
Reset();
}
public object Current
{
get
{
return m_Token;
}
}
public bool MoveNext()
{
if (m_nIdx >= m_strarrTokens.Length)
return false;
m_Token = new Token(m_strarrTokens[m_nIdx]);
m_nIdx++;
return true;
}
public void Reset()
{
m_nIdx = 0;
}
}
#region Exceptions
public class RPN_Exception : ApplicationException
{
public RPN_Exception()
{
}
public RPN_Exception(string szMessage)
: base(szMessage)
{
}
public RPN_Exception(string szMessage, Exception innerException)
: base(szMessage, innerException)
{
}
}
#endregion
#endregion
#region Interfaces
public interface IOperand { }
public interface IOperator
{
IOperand Eval(IOperand lhs, IOperand rhs);
IOperand Eval(IOperand lhs);
}
public interface IArithmeticOperations
{
IOperand Plus(IOperand rhs);
IOperand Minus(IOperand rhs);
IOperand Multiply(IOperand rhs);
IOperand Divide(IOperand rhs);
IOperand Modulo(IOperand rhs);
IOperand Not();
IOperand Negate();
}
public interface IComparisonOperations
{
IOperand EqualTo(IOperand rhs);
IOperand NotEqualTo(IOperand rhs);
IOperand LessThan(IOperand rhs);
IOperand LessThanOrEqualTo(IOperand rhs);
IOperand GreaterThan(IOperand rhs);
IOperand GreaterThanOrEqualTo(IOperand rhs);
}
public interface ILogicalOperations
{
IOperand OR(IOperand rhs);
IOperand AND(IOperand rhs);
}
#endregion
#region Operands
public abstract class Operand : IOperand
{
public Operand(string szVarName, object varValue)
{
m_szVarName = szVarName;
m_VarValue = varValue;
}
public Operand(string szVarName)
{
m_szVarName = szVarName;
}
public override string ToString()
{
return m_szVarName;
}
public abstract void ExtractAndSetValue(string szValue, bool bFormula);
public string Name
{
get
{
return m_szVarName;
}
set
{
m_szVarName = value;
}
}
public object Value
{
get
{
return m_VarValue;
}
set
{
m_VarValue = value;
}
}
protected string m_szVarName = "";
protected object m_VarValue = null;
}
public class LongOperand : Operand, IArithmeticOperations, IComparisonOperations
{
public LongOperand(string szVarName, object varValue)
: base(szVarName, varValue)
{
}
public LongOperand(string szVarName)
: base(szVarName)
{
}
public override string ToString()
{
return m_szVarName;
}
public override void ExtractAndSetValue(string szValue, bool bFormula)
{
switch (szValue)
{
case "true":
szValue = "1";
m_VarValue = !bFormula ? Convert.ToInt64(szValue) : 0;
break;
case "false":
szValue = "0";
m_VarValue = !bFormula ? Convert.ToInt64(szValue) : 0;
break;
default:
m_VarValue = !bFormula ? Convert.ToInt64(szValue) : 0;
break;
}
}
public IOperand Plus(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.Plus : rhs");
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));
oprResult.Value = (long)this.Value + (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Minus(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.Minus : rhs");
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));
oprResult.Value = (long)this.Value - (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Multiply(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new ArgumentException("Argument invalid in LongOperand.Multiply : rhs");
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));
oprResult.Value = (long)this.Value * (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Negate()
{
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));
oprResult.Value = (long)this.Value * -1;
return oprResult;
}
public IOperand Not()
{
BoolOperand oprResult = new BoolOperand("Result", Type.GetType("System.Boolean"));
switch (Convert.ToString(this.Value))
{
case "0":
oprResult.Value = !(false);
break;
case "1":
oprResult.Value = !(true);
break;
default:
break;
}
return oprResult;
}
public IOperand Divide(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.Divide : rhs");
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));
oprResult.Value = (long)this.Value / (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Modulo(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.Modulo : rhs");
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));
oprResult.Value = (long)this.Value % (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand EqualTo(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.== : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = (long)this.Value == (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand NotEqualTo(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.!= : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value != (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand LessThan(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.< : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value < (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand LessThanOrEqualTo(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.<= : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value <= (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand GreaterThan(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.> : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value > (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand GreaterThanOrEqualTo(IOperand rhs)
{
if (!(rhs is LongOperand))
throw new RPN_Exception("Argument invalid in LongOperand.>= : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value >= (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
}
public class BoolOperand : Operand, ILogicalOperations
{
public BoolOperand(string szVarName, object varValue)
: base(szVarName, varValue)
{
}
public BoolOperand(string szVarName)
: base(szVarName)
{
}
public override string ToString()
{
return this.Value.ToString();
}
public override void ExtractAndSetValue(string szValue, bool bFormula)
{
m_VarValue = !bFormula ? Convert.ToBoolean(szValue) : false;
}
public IOperand AND(IOperand rhs)
{
if (!(rhs is BoolOperand))
throw new RPN_Exception("Argument invalid in BoolOperand.&& : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((bool)this.Value && (bool)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand OR(IOperand rhs)
{
if (!(rhs is BoolOperand))
throw new RPN_Exception("Argument invalid in BoolOperand.|| : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((bool)this.Value || (bool)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand Negate()
{
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));
oprResult.Value = (long)this.Value * -1;
return oprResult;
}
public IOperand Not()
{
BoolOperand oprResult = new BoolOperand("Result", Type.GetType("System.Boolean"));
switch (Convert.ToString(this.Value))
{
case "False":
oprResult.Value = !(false);
break;
case "True":
oprResult.Value = !(true);
break;
default:
break;
}
return oprResult;
}
}
public class OperandHelper
{
static public Operand CreateOperand(string szVarName, Type varType, object varValue)
{
Operand oprResult = null;
bool IsBoolean;
if (Boolean.TryParse(szVarName, out IsBoolean))
{
oprResult = new BoolOperand(szVarName, varValue);
return oprResult;
}
else
{
switch (varType.ToString())
{
case "System.Int32":
case "System.Int64":
oprResult = new LongOperand(szVarName, varValue);
return oprResult;
case "System.String":
oprResult = new StringOperand(szVarName, varValue);
return oprResult;
}
}
throw new RPN_Exception("Unhandled type : " + varType.ToString());
}
static public Operand CreateOperand(string szVarName, Type varType)
{
return OperandHelper.CreateOperand(szVarName, varType, null);
}
}
public class StringOperand : Operand, IComparisonOperations
{
public StringOperand(string szVarName, object varValue)
: base(szVarName, varValue)
{
}
public StringOperand(string szVarName)
: base(szVarName)
{
}
public override string ToString()
{
return m_szVarName;
}
public override void ExtractAndSetValue(string szValue, bool bFormula)
{
m_VarValue = !bFormula ? Convert.ToString(szValue) : "";
}
public IOperand EqualTo(IOperand rhs)
{
if (!(rhs is StringOperand))
throw new RPN_Exception("Argument invalid in StringOperand.== : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = (string)this.Value == (string)((Operand)rhs).Value;
return oprResult;
}
public IOperand NotEqualTo(IOperand rhs)
{
if (!(rhs is StringOperand))
throw new RPN_Exception("Argument invalid in StringOperand.!= : rhs");
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((string)this.Value != (string)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand LessThan(IOperand rhs)
{
throw new RPN_Exception("LessThan operator is invalid for string");
}
public IOperand LessThanOrEqualTo(IOperand rhs)
{
throw new RPN_Exception("LessThanOrEqualTo operator is invalid for string");
}
public IOperand GreaterThan(IOperand rhs)
{
throw new RPN_Exception("GreaterThan operator is invalid for string");
}
public IOperand GreaterThanOrEqualTo(IOperand rhs)
{
throw new RPN_Exception("GreaterThanOrEqualTo operator is invalid for string");
}
}
#endregion
#region Operators
public abstract class Operator : IOperator
{
public Operator(char cOperator)
{
m_szOperator = new String(cOperator, 1);
}
public Operator(string szOperator)
{
m_szOperator = szOperator;
}
public override string ToString()
{
return m_szOperator;
}
public abstract IOperand Eval(IOperand lhs, IOperand rhs);
public abstract IOperand Eval(IOperand lhs);
public string Value
{
get
{
return m_szOperator;
}
set
{
m_szOperator = value;
}
}
protected string m_szOperator = "";
}
public class ArithmeticOperator : Operator
{
public ArithmeticOperator(char cOperator)
: base(cOperator)
{
}
public ArithmeticOperator(string szOperator)
: base(szOperator)
{
}
public override IOperand Eval(IOperand lhs, IOperand rhs)
{
if (!(lhs is IArithmeticOperations))
throw new RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs");
switch (m_szOperator)
{
case "+":
return ((IArithmeticOperations)lhs).Plus(rhs);
case "-":
return ((IArithmeticOperations)lhs).Minus(rhs);
case "*":
return ((IArithmeticOperations)lhs).Multiply(rhs);
case "/":
return ((IArithmeticOperations)lhs).Divide(rhs);
case "%":
return ((IArithmeticOperations)lhs).Modulo(rhs);
}
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator);
}
public override IOperand Eval(IOperand lhs)
{
if (lhs is IArithmeticOperations)
{
switch (m_szOperator)
{
case "~":
return ((IArithmeticOperations)lhs).Negate();
case "!":
return ((IArithmeticOperations)lhs).Not();
}
}
else if (lhs is BoolOperand)
{
switch (m_szOperator)
{
case "~":
return ((BoolOperand)lhs).Negate();
case "!":
return ((BoolOperand)lhs).Not();
}
}
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator);
}
}
public class ComparisonOperator : Operator
{
public ComparisonOperator(char cOperator)
: base(cOperator)
{
}
public ComparisonOperator(string szOperator)
: base(szOperator)
{
}
public override IOperand Eval(IOperand lhs) { return null; }
public override IOperand Eval(IOperand lhs, IOperand rhs)
{
if (!(lhs is IComparisonOperations))
throw new RPN_Exception("Argument invalid in ComparisonOperator.Eval - Invalid Expression : lhs");
switch (m_szOperator)
{
case "==":
return ((IComparisonOperations)lhs).EqualTo(rhs);
case "!=":
return ((IComparisonOperations)lhs).NotEqualTo(rhs);
case "<":
return ((IComparisonOperations)lhs).LessThan(rhs);
case "<=":
return ((IComparisonOperations)lhs).LessThanOrEqualTo(rhs);
case ">":
return ((IComparisonOperations)lhs).GreaterThan(rhs);
case ">=":
return ((IComparisonOperations)lhs).GreaterThanOrEqualTo(rhs);
}
throw new RPN_Exception("Unsupported Comparison operation " + m_szOperator);
}
}
public class LogicalOperator : Operator
{
public LogicalOperator(char cOperator)
: base(cOperator)
{
}
public LogicalOperator(string szOperator)
: base(szOperator)
{
}
public override IOperand Eval(IOperand lhs) { return null; }
public override IOperand Eval(IOperand lhs, IOperand rhs)
{
if (!(lhs is ILogicalOperations))
throw new RPN_Exception("Argument invalid in LogicalOperator.Eval - Invalid Expression : lhs");
switch (m_szOperator)
{
case "&&":
return ((ILogicalOperations)lhs).AND(rhs);
case "||":
return ((ILogicalOperations)lhs).OR(rhs);
}
throw new RPN_Exception("Unsupported Logical operation " + m_szOperator);
}
}
public class OperatorHelper
{
static public IOperator CreateOperator(string szOperator)
{
IOperator oprtr = null;
if (OperatorHelper.IsArithmeticOperator(szOperator))
{
oprtr = new ArithmeticOperator(szOperator);
return oprtr;
}
if (OperatorHelper.IsComparisonOperator(szOperator))
{
oprtr = new ComparisonOperator(szOperator);
return oprtr;
}
if (OperatorHelper.IsLogicalOperator(szOperator))
{
oprtr = new LogicalOperator(szOperator);
return oprtr;
}
throw new RPN_Exception("Unhandled Operator : " + szOperator);
}
static public IOperator CreateOperator(char cOperator)
{
return CreateOperator(new string(cOperator, 1));
}
public static bool IsOperator(string currentOp)
{
int nPos = Array.IndexOf(m_AllOps, currentOp.Trim());
if (nPos != -1)
return true;
else
return false;
}
public static bool IsUnaryOperator(string currentOp)
{
int nPos = Array.IndexOf(m_AllUnaryOps, currentOp.Trim());
if (nPos != -1)
return true;
else
return false;
}
public static bool IsArithmeticOperator(string currentOp)
{
int nPos = Array.IndexOf(m_AllArithmeticOps, currentOp);
if (nPos != -1)
return true;
else
return false;
}
public static bool IsComparisonOperator(string currentOp)
{
int nPos = Array.IndexOf(m_AllComparisonOps, currentOp);
if (nPos != -1)
return true;
else
return false;
}
public static bool IsLogicalOperator(string currentOp)
{
int nPos = Array.IndexOf(m_AllLogicalOps, currentOp);
if (nPos != -1)
return true;
else
return false;
}
#region Precedence
public static bool IsLowerPrecOperator(string currentOp, string prevOp)
{
int nCurrIdx;
int nPrevIdx;
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx);
if (nCurrIdx < nPrevIdx)
{
return true;
}
return false;
}
public static bool IsHigherPrecOperator(string currentOp, string prevOp)
{
int nCurrIdx;
int nPrevIdx;
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx);
if (nCurrIdx > nPrevIdx)
{
return true;
}
return false;
}
public static bool IsEqualPrecOperator(string currentOp, string prevOp)
{
int nCurrIdx;
int nPrevIdx;
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx);
if (nCurrIdx == nPrevIdx)
{
return true;
}
return false;
}
private static void GetCurrentAndPreviousIndex(string[] allOps, string currentOp, string prevOp,
out int nCurrIdx, out int nPrevIdx)
{
nCurrIdx = -1;
nPrevIdx = -1;
for (int nIdx = 0; nIdx < allOps.Length; nIdx++)
{
if (allOps[nIdx] == currentOp)
{
nCurrIdx = nIdx;
}
if (allOps[nIdx] == prevOp)
{
nPrevIdx = nIdx;
}
if (nPrevIdx != -1 && nCurrIdx != -1)
{
break;
}
}
if (nCurrIdx == -1)
{
throw new RPN_Exception("Unknown operator - " + currentOp);
}
if (nPrevIdx == -1)
{
throw new RPN_Exception("Unknown operator - " + prevOp);
}
}
#endregion
#region RegEx
static public string GetOperatorsRegEx(ExpressionType exType)
{
StringBuilder strRegex = new StringBuilder();
if ((exType & ExpressionType.ET_ARITHMETIC).Equals(ExpressionType.ET_ARITHMETIC))
{
if (strRegex.Length == 0)
{
strRegex.Append(m_szArthmtcRegEx);
}
else
{
strRegex.Append("|" + m_szArthmtcRegEx);
}
}
if ((exType & ExpressionType.ET_COMPARISON).Equals(ExpressionType.ET_COMPARISON))
{
if (strRegex.Length == 0)
{
strRegex.Append(m_szCmprsnRegEx);
}
else
{
strRegex.Append("|" + m_szCmprsnRegEx);
}
}
if ((exType & ExpressionType.ET_LOGICAL).Equals(ExpressionType.ET_LOGICAL))
{
if (strRegex.Length == 0)
{
strRegex.Append(m_szLgclRegEx);
}
else
{
strRegex.Append("|" + m_szLgclRegEx);
}
}
if (strRegex.Length == 0)
throw new RPN_Exception("Invalid combination of ExpressionType value");
return "(" + strRegex.ToString() + ")";
}
static string m_szArthmtcRegEx = @"[+\-*/%()]{1}";
static string m_szCmprsnRegEx = @"[=<>!]{1,2}";
static string m_szLgclRegEx = @"[&|]{2}";
#endregion
public static string[] AllOperators
{
get
{
return m_AllOps;
}
}
static string[] m_AllOps = { "||", "&&", "|", "^", "&", "==", "!=",
"<", "<=", ">", ">=", "+", "-", "*", "/", "~", "%", "(", ")","!" };
static string[] m_AllArithmeticOps = { "+", "-", "~", "*", "/", "%", "!" };
static string[] m_AllComparisonOps = { "==", "!=", "<", "<=", ">", ">=" };
static string[] m_AllLogicalOps = { "&&", "||" };
static string[] m_AllUnaryOps = { "~", "!" };
}
#endregion
#region TODO List
Here is the example expressions which the above code supports.
"(25 == 25 && (10 == 10 || (10 == 10 || 4 == 4))) && (25 == 25 && (10 == 10 || (10 == 10 || 4 == 4)))";
"(10 == 10|| 4 == 4)";
"true";
"true && true";
"(true && true) && (25 == 25 && (10 == 10 || (10 == 10 || 4 == 4)))";
"~(5)";
"!(false)";
"!(true) || !(false)";
string str="('aaa'=='aaa' && 'bbb'=='bbb')";
str.Replace("'", @"""""");
Kanna
modified on Wednesday, December 22, 2010 5:30 AM
|
|
|
|
|
programming is the art
|
|
|
|
|
Hi deepeddie, Is there any restriction to use this code in my application?
Thank you
|
|
|
|
|
Hi deepeddie,
I have the same question. Is there any restriction / license to use this code?
Best regards,
Jerome
|
|
|
|
|
I tried adding exponent"^" operator but it not working. Please suggest me how to modify the code for the same.
|
|
|
|
|
Got crush when I test expression like (2.5/2) == 1.25
|
|
|
|
|
i found your work very useful.thank you.
but in file: MathParser.cs in line 213,i think it should be like as follows:
if (IsLogicalOperator(token)) {
newOp.OpGroup = OperatorGroup.Logical;
//modified :if is a logical oper such as "&&" "||",its value is 128 + '&' or 128+ '|'
newOp.OpType = (OperatorType)(128 + (int)token.StrValue[0]);
am i right?
|
|
|
|
|
A - C + B evaluates out to be A - C, then Result + B --> AC-B+
When I checked in the Operator (Precendence) array, I see that + actually has a lower index than -. So technically, + should be evaluated before -. The parser does this correctly by treating - and + equally.
I want to add two operators of equal precedence, lets say $ and ~. Both were added to the operator array in that order. What else should I do to make sure that they can be treated as equal precedence? Here is an example of what I am trying to do:
example 1
A ~ B $ C --> evaluates out to ABC$~
but the desired behavor is --> AB~C$
Any suggestions?
Thanks.
|
|
|
|
|
Thanks to the work done by stuallenii and reuralc I mixed their code to add the following feature in one code : minus unary operator + string comparison
So here is the kind of thing you can do :
("aaa" == "bbb" && -1<0) || ("aa" == "aa" && 5*20%4 > 1) => return true
//Another feature is fix : comparison string with operator inside the string : ex. "A+" == "B-" work and will return false...
<br />
using System;<br />
using System.Collections;<br />
using System.Text;<br />
using System.Text.RegularExpressions;<br />
<br />
namespace cfring.util<br />
{<br />
#region RPN<br />
public class RPNParser<br />
{<br />
public RPNParser()<br />
{<br />
}<br />
public object EvaluateExpression( string szExpr, Type varType, bool bFormula, Hashtable htValues )<br />
{<br />
ArrayList arrExpr = GetPostFixNotation( szExpr, varType, bFormula );<br />
return EvaluateRPN(arrExpr, varType, htValues );<br />
}<br />
<br />
public object EvaluateExpression( string szExpr )<br />
{<br />
long myType = 0;<br />
ArrayList arrExpr = GetPostFixNotation( szExpr, myType.GetType(),false);<br />
return EvaluateRPN(arrExpr, myType.GetType(), null );<br />
}<br />
<br />
#region replacement for string<br />
public string replacementToRPN(string expression)<br />
{<br />
while (Regex.IsMatch(expression,"\"[^\"]*\""))<br />
{<br />
string myString = Regex.Match(expression,"\"[^\"]*\"").Value.ToString();<br />
string stringAdapted = myString.Replace("\"","@@@");<br />
stringAdapted = stringAdapted.Replace("+","µ#1");<br />
stringAdapted = stringAdapted.Replace("-","µ#2");<br />
stringAdapted = stringAdapted.Replace("/","µ#3");<br />
stringAdapted = stringAdapted.Replace("*","µ#4");<br />
stringAdapted = stringAdapted.Replace(")","µ#5");<br />
stringAdapted = stringAdapted.Replace("(","µ#6");<br />
stringAdapted = stringAdapted.Replace("%","µ#7");<br />
stringAdapted = stringAdapted.Replace("~","µ#8");<br />
stringAdapted = stringAdapted.Replace("=","µ#9");<br />
stringAdapted = stringAdapted.Replace("<","µ#10");<br />
stringAdapted = stringAdapted.Replace(">","µ#11");<br />
stringAdapted = stringAdapted.Replace("|","µ#12");<br />
stringAdapted = stringAdapted.Replace("&","µ#13");<br />
expression = expression.Replace(myString,stringAdapted);<br />
}<br />
expression = expression.Replace("@@@","\"");<br />
return expression;<br />
}<br />
<br />
#endregion<br />
<br />
#region RPN_Parser<br />
public ArrayList GetPostFixNotation( string szExpr, Type varType, bool bFormula )<br />
{<br />
szExpr = this.replacementToRPN(szExpr);<br />
Stack stkOp = new Stack();<br />
ArrayList arrFinalExpr = new ArrayList();<br />
string szResult = "";<br />
string szLastItem = "";<br />
bool bApplyNegative = false;<br />
<br />
Tokenizer tknzr = null;<br />
switch(varType.ToString())<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
tknzr = new Tokenizer( szExpr,ExpressionType.ET_ARITHMETIC|<br />
ExpressionType.ET_COMPARISON|<br />
ExpressionType.ET_LOGICAL );<br />
break;<br />
case "System.String":<br />
tknzr = new Tokenizer( szExpr, ExpressionType.ET_COMPARISON);<br />
break;<br />
}<br />
<br />
<br />
<br />
foreach(Token token in tknzr)<br />
{<br />
string szToken = token.Value.Trim();<br />
if( szToken.Length == 0 )<br />
continue;<br />
switch(varType.ToString())<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
if( !OperatorHelper.IsOperator(szToken) )<br />
{<br />
Operand oprnd;<br />
if (szToken.IndexOf("\"") != -1)<br />
{<br />
string myStringType = "";<br />
oprnd = OperandHelper.CreateOperand( szToken, myStringType.GetType() );<br />
}<br />
else oprnd = OperandHelper.CreateOperand( szToken, varType );<br />
oprnd.ExtractAndSetValue( szToken, bFormula );<br />
arrFinalExpr.Add( oprnd );<br />
<br />
szResult += szToken;<br />
szLastItem = szToken;<br />
continue;<br />
}<br />
break;<br />
case "System.String":<br />
if( !OperatorHelper.IsComparisonOperator(szToken) )<br />
{<br />
Operand oprnd = OperandHelper.CreateOperand( szToken, varType );<br />
oprnd.ExtractAndSetValue( szToken, bFormula );<br />
arrFinalExpr.Add( oprnd );<br />
<br />
szResult += szToken;<br />
szLastItem = szToken;<br />
continue;<br />
}<br />
<br />
break;<br />
}<br />
<br />
string szOp = szToken;<br />
if( szOp == "(" )<br />
{<br />
stkOp.Push( szOp );<br />
}<br />
else if( szOp == ")" )<br />
{<br />
string szTop;<br />
while( (szTop = (string)stkOp.Pop()) != "(")<br />
{<br />
IOperator oprtr = OperatorHelper.CreateOperator( szTop );<br />
arrFinalExpr.Add( oprtr );<br />
<br />
szResult += szTop;<br />
<br />
if( stkOp.Count == 0 )<br />
throw new RPN_Exception( "Unmatched braces!" );<br />
}<br />
}<br />
else<br />
{<br />
if (szOp == "-" && (!StringContentCheck.IsAlphaNumeric(szLastItem) || szLastItem==""))<br />
{<br />
bApplyNegative = true;<br />
<br />
stkOp.Push("~");<br />
<br />
<br />
}<br />
else<br />
{<br />
if (stkOp.Count == 0 || (string)stkOp.Peek() == "("<br />
|| OperatorHelper.IsHigherPrecOperator(szOp, (string)stkOp.Peek()))<br />
{<br />
stkOp.Push(szOp);<br />
}<br />
else<br />
{<br />
while (stkOp.Count != 0)<br />
{<br />
if (OperatorHelper.IsLowerPrecOperator(szOp, (string)stkOp.Peek())<br />
|| OperatorHelper.IsEqualPrecOperator(szOp, (string)stkOp.Peek()))<br />
{<br />
string szTop = (string)stkOp.Peek();<br />
if (szTop == "(")<br />
break;<br />
szTop = (string)stkOp.Pop();<br />
<br />
IOperator oprtr = OperatorHelper.CreateOperator(szTop);<br />
arrFinalExpr.Add(oprtr);<br />
<br />
szResult += szTop;<br />
}<br />
else<br />
break;<br />
}<br />
stkOp.Push( szOp );<br />
}<br />
}<br />
}<br />
szLastItem = szToken;<br />
}<br />
while (stkOp.Count != 0)<br />
{<br />
string szTop = (string)stkOp.Pop();<br />
if( szTop == "(" )<br />
throw new RPN_Exception("Unmatched braces");<br />
<br />
IOperator oprtr = OperatorHelper.CreateOperator( szTop );<br />
arrFinalExpr.Add( oprtr );<br />
<br />
szResult += szTop;<br />
}<br />
return arrFinalExpr;<br />
}<br />
<br />
#endregion<br />
<br />
public string Convert2String( ArrayList arrExpr )<br />
{<br />
string szResult = "";<br />
foreach( object obj in arrExpr )<br />
{<br />
szResult += obj.ToString();<br />
}<br />
return szResult;<br />
}<br />
<br />
<br />
#region RPN_Evaluator<br />
<br />
public object EvaluateRPN( ArrayList arrExpr, Type varType, Hashtable htValues )<br />
{<br />
Stack stPad = new Stack();<br />
foreach( object var in arrExpr )<br />
{<br />
Operand op1 = null;<br />
Operand op2 = null;<br />
IOperator oprtr = null;<br />
if( var is IOperand )<br />
{<br />
stPad.Push( var );<br />
}<br />
else if( var is IOperator )<br />
{<br />
if (OperatorHelper.IsUnaryOperator(((Operator)var).ToString()))<br />
{<br />
op1 = (Operand)stPad.Pop();<br />
if (htValues != null)<br />
{<br />
op1.Value = htValues[op1.Name];<br />
}<br />
oprtr = (IOperator)var;<br />
IOperand opRes = oprtr.Eval(op1);<br />
stPad.Push(opRes);<br />
}<br />
else<br />
{<br />
op2 = (Operand)stPad.Pop();<br />
if (htValues != null)<br />
{<br />
op2.Value = htValues[op2.Name];<br />
}<br />
op1 = (Operand)stPad.Pop();<br />
if (htValues != null)<br />
{<br />
op1.Value = htValues[op1.Name];<br />
}<br />
oprtr = (IOperator)var;<br />
IOperand opRes = oprtr.Eval(op1, op2);<br />
stPad.Push(opRes);<br />
}<br />
}<br />
}<br />
return ((Operand)stPad.Pop()).Value;<br />
}<br />
#endregion<br />
}<br />
#endregion<br />
<br />
#region UtilClasses<br />
<br />
[Flags]<br />
public enum ExpressionType<br />
{<br />
ET_ARITHMETIC = 0x0001,<br />
ET_COMPARISON = 0x0002,<br />
ET_LOGICAL = 0x0004<br />
}<br />
public enum TokenType<br />
{<br />
TT_OPERATOR,<br />
TT_OPERAND<br />
}<br />
public class Token<br />
{<br />
public Token( string szValue )<br />
{<br />
m_szValue = szValue;<br />
}<br />
public string Value<br />
{<br />
get<br />
{<br />
return m_szValue;<br />
}<br />
}<br />
string m_szValue;<br />
}<br />
public class Tokenizer : IEnumerable<br />
{<br />
public Tokenizer( string szExpression ):this(szExpression, ExpressionType.ET_ARITHMETIC|<br />
ExpressionType.ET_COMPARISON|<br />
ExpressionType.ET_LOGICAL)<br />
{<br />
}<br />
public Tokenizer( string szExpression, ExpressionType exType )<br />
{<br />
m_szExpression = szExpression;<br />
m_exType = exType;<br />
m_RegEx = new Regex(OperatorHelper.GetOperatorsRegEx( m_exType ));<br />
m_strarrTokens = SplitExpression( szExpression );<br />
}<br />
public IEnumerator GetEnumerator()<br />
{<br />
return new TokenEnumerator( m_strarrTokens );<br />
}<br />
public string[] SplitExpression( string szExpression )<br />
{<br />
return m_RegEx.Split( szExpression );<br />
}<br />
ExpressionType m_exType;<br />
string m_szExpression;<br />
string[] m_strarrTokens;<br />
Regex m_RegEx;<br />
}<br />
<br />
public class TokenEnumerator : IEnumerator<br />
{<br />
Token m_Token;<br />
int m_nIdx;<br />
string[] m_strarrTokens;<br />
<br />
public TokenEnumerator( string[] strarrTokens )<br />
{<br />
m_strarrTokens = strarrTokens;<br />
Reset();<br />
}<br />
public object Current<br />
{<br />
get<br />
{<br />
return m_Token;<br />
}<br />
}<br />
public bool MoveNext()<br />
{<br />
if( m_nIdx >= m_strarrTokens.Length )<br />
return false;<br />
<br />
m_Token = new Token( m_strarrTokens[m_nIdx]);<br />
m_nIdx++;<br />
return true;<br />
}<br />
public void Reset()<br />
{<br />
m_nIdx = 0;<br />
}<br />
}<br />
#region Exceptions<br />
public class RPN_Exception : ApplicationException<br />
{<br />
public RPN_Exception()<br />
{<br />
}<br />
public RPN_Exception( string szMessage):base( szMessage)<br />
{<br />
}<br />
public RPN_Exception( string szMessage, Exception innerException ):base( szMessage, innerException)<br />
{<br />
}<br />
}<br />
#endregion<br />
#endregion<br />
<br />
#region Interfaces<br />
public interface IOperand{}<br />
public interface IOperator<br />
{<br />
IOperand Eval( IOperand lhs, IOperand rhs );<br />
IOperand Eval(IOperand lhs);<br />
}<br />
<br />
public interface IArithmeticOperations<br />
{<br />
IOperand Plus(IOperand rhs);<br />
IOperand Minus(IOperand rhs);<br />
IOperand Negate();<br />
IOperand Multiply(IOperand rhs);<br />
IOperand Divide(IOperand rhs);<br />
IOperand Modulo(IOperand rhs);<br />
}<br />
public interface IComparisonOperations<br />
{<br />
IOperand EqualTo( IOperand rhs);<br />
IOperand NotEqualTo( IOperand rhs);<br />
IOperand LessThan( IOperand rhs);<br />
IOperand LessThanOrEqualTo( IOperand rhs);<br />
IOperand GreaterThan( IOperand rhs);<br />
IOperand GreaterThanOrEqualTo( IOperand rhs);<br />
}<br />
public interface ILogicalOperations<br />
{<br />
IOperand OR( IOperand rhs);<br />
IOperand AND( IOperand rhs);<br />
}<br />
#endregion<br />
<br />
#region Operands<br />
public abstract class Operand : IOperand<br />
{<br />
public Operand( string szVarName, object varValue )<br />
{<br />
m_szVarName = szVarName;<br />
m_VarValue = varValue;<br />
}<br />
public Operand( string szVarName )<br />
{<br />
m_szVarName = szVarName;<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public abstract void ExtractAndSetValue( string szValue, bool bFormula );<br />
public string Name<br />
{<br />
get<br />
{<br />
return m_szVarName;<br />
}<br />
set<br />
{<br />
m_szVarName = value;<br />
}<br />
}<br />
public object Value<br />
{<br />
get<br />
{<br />
return m_VarValue;<br />
}<br />
set<br />
{<br />
m_VarValue = value;<br />
}<br />
}<br />
protected string m_szVarName = "";<br />
protected object m_VarValue = null;<br />
}<br />
public class LongOperand : Operand, IArithmeticOperations, IComparisonOperations<br />
{<br />
public LongOperand( string szVarName, object varValue ):base(szVarName, varValue)<br />
{<br />
}<br />
public LongOperand( string szVarName ):base( szVarName )<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public override void ExtractAndSetValue( string szValue, bool bFormula )<br />
{<br />
m_VarValue = !bFormula ?Convert.ToInt64(szValue):0;<br />
}<br />
public IOperand Plus( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Plus : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value + (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Minus( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Minus : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value - (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Negate()<br />
{<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));<br />
oprResult.Value = (long)this.Value * -1;<br />
return oprResult;<br />
}<br />
public IOperand Multiply( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new ArgumentException("Argument invalid in LongOperand.Multiply : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value * (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Divide( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Divide : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value / (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Modulo( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Modulo : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value % (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
<br />
public IOperand EqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.== : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result" );<br />
oprResult.Value = (long)this.Value == (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand NotEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.!= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value != (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThan( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.< : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value < (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThanOrEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.<= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value <= (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThan( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.> : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value > (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThanOrEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.>= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value >= (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
}<br />
public class BoolOperand : Operand, ILogicalOperations<br />
{<br />
public BoolOperand( string szVarName, object varValue ):base(szVarName, varValue)<br />
{<br />
}<br />
public BoolOperand( string szVarName ):base( szVarName )<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return this.Value.ToString();<br />
}<br />
public override void ExtractAndSetValue( string szValue, bool bFormula )<br />
{<br />
m_VarValue = !bFormula ?Convert.ToBoolean(szValue):false;<br />
}<br />
public IOperand AND( IOperand rhs)<br />
{<br />
if( !(rhs is BoolOperand) )<br />
throw new RPN_Exception("Argument invalid in BoolOperand.&& : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((bool)this.Value && (bool)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand OR( IOperand rhs)<br />
{<br />
if( !(rhs is BoolOperand) )<br />
throw new RPN_Exception("Argument invalid in BoolOperand.|| : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((bool)this.Value || (bool)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
}<br />
<br />
public class OperandHelper<br />
{<br />
static public Operand CreateOperand( string szVarName, Type varType, object varValue )<br />
{<br />
Operand oprResult = null;<br />
switch( varType.ToString() )<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
oprResult = new LongOperand( szVarName, varValue );<br />
return oprResult;<br />
case "System.String":<br />
oprResult = new StringOperand( szVarName, varValue );<br />
return oprResult;<br />
<br />
<br />
<br />
<br />
}<br />
throw new RPN_Exception("Unhandled type : " + varType.ToString());<br />
}<br />
static public Operand CreateOperand( string szVarName, Type varType )<br />
{<br />
return OperandHelper.CreateOperand( szVarName, varType, null);<br />
}<br />
}<br />
public class StringOperand : Operand, IComparisonOperations<br />
{<br />
public StringOperand( string szVarName, object varValue ):base(szVarName, varValue)<br />
{<br />
}<br />
public StringOperand( string szVarName ):base( szVarName )<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public override void ExtractAndSetValue( string szValue, bool bFormula )<br />
{<br />
m_VarValue = !bFormula ?Convert.ToString(szValue):"";<br />
}<br />
public IOperand EqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is StringOperand) )<br />
throw new RPN_Exception("Argument invalid in StringOperand.== : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = (string)this.Value == (string)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand NotEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is StringOperand) )<br />
throw new RPN_Exception("Argument invalid in StringOperand.!= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((string)this.Value != (string)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThan( IOperand rhs)<br />
{<br />
throw new RPN_Exception("LessThan operator is invalid for string" );<br />
}<br />
public IOperand LessThanOrEqualTo( IOperand rhs)<br />
{<br />
throw new RPN_Exception("LessThanOrEqualTo operator is invalid for string" );<br />
}<br />
public IOperand GreaterThan( IOperand rhs)<br />
{<br />
throw new RPN_Exception("GreaterThan operator is invalid for string" );<br />
}<br />
public IOperand GreaterThanOrEqualTo( IOperand rhs)<br />
{<br />
throw new RPN_Exception("GreaterThanOrEqualTo operator is invalid for string" );<br />
}<br />
}<br />
#endregion<br />
<br />
#region Operators<br />
public abstract class Operator : IOperator<br />
{<br />
public Operator( char cOperator )<br />
{<br />
m_szOperator = new String(cOperator, 1);<br />
}<br />
public Operator( string szOperator )<br />
{<br />
m_szOperator = szOperator;<br />
}<br />
public override string ToString()<br />
{<br />
return m_szOperator;<br />
}<br />
public abstract IOperand Eval( IOperand lhs, IOperand rhs );<br />
public abstract IOperand Eval(IOperand lhs);<br />
public string Value<br />
{<br />
get<br />
{<br />
return m_szOperator;<br />
}<br />
set<br />
{<br />
m_szOperator = value;<br />
}<br />
}<br />
protected string m_szOperator = "";<br />
}<br />
public class ArithmeticOperator : Operator<br />
{<br />
public ArithmeticOperator( char cOperator ):base( cOperator )<br />
{<br />
}<br />
public ArithmeticOperator( string szOperator ):base( szOperator )<br />
{<br />
}<br />
<br />
public override IOperand Eval( IOperand lhs, IOperand rhs )<br />
{<br />
if( !(lhs is IArithmeticOperations) )<br />
throw new RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs" );<br />
switch( m_szOperator )<br />
{<br />
case "+":<br />
return ((IArithmeticOperations)lhs).Plus( rhs );<br />
case "-":<br />
return ((IArithmeticOperations)lhs).Minus( rhs );<br />
case "*":<br />
return ((IArithmeticOperations)lhs).Multiply( rhs );<br />
case "/":<br />
return ((IArithmeticOperations)lhs).Divide( rhs );<br />
case "%":<br />
return ((IArithmeticOperations)lhs).Modulo( rhs );<br />
}<br />
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator );<br />
}<br />
<br />
public override IOperand Eval(IOperand lhs)<br />
{<br />
if (!(lhs is IArithmeticOperations))<br />
throw new RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs");<br />
switch (m_szOperator)<br />
{<br />
case "~":<br />
return ((IArithmeticOperations)lhs).Negate();<br />
}<br />
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator);<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
public class ComparisonOperator : Operator<br />
{<br />
public ComparisonOperator( char cOperator ):base( cOperator )<br />
{<br />
}<br />
public ComparisonOperator( string szOperator ):base( szOperator )<br />
{<br />
}<br />
public override IOperand Eval(IOperand lhs) { return null; }<br />
<br />
public override IOperand Eval( IOperand lhs, IOperand rhs )<br />
{<br />
if( !(lhs is IComparisonOperations) )<br />
throw new RPN_Exception("Argument invalid in ComparisonOperator.Eval - Invalid Expression : lhs" );<br />
switch( m_szOperator )<br />
{<br />
case "==":<br />
return ((IComparisonOperations)lhs).EqualTo( rhs );<br />
case "!=":<br />
return ((IComparisonOperations)lhs).NotEqualTo( rhs );<br />
case "<":<br />
return ((IComparisonOperations)lhs).LessThan( rhs );<br />
case "<=":<br />
return ((IComparisonOperations)lhs).LessThanOrEqualTo( rhs );<br />
case ">":<br />
return ((IComparisonOperations)lhs).GreaterThan( rhs );<br />
case ">=":<br />
return ((IComparisonOperations)lhs).GreaterThanOrEqualTo( rhs );<br />
}<br />
throw new RPN_Exception("Unsupported Comparison operation " + m_szOperator );<br />
}<br />
}<br />
<br />
public class LogicalOperator : Operator<br />
{<br />
public LogicalOperator( char cOperator ):base( cOperator )<br />
{<br />
}<br />
public LogicalOperator( string szOperator ):base( szOperator )<br />
{<br />
}<br />
<br />
public override IOperand Eval(IOperand lhs) { return null; }<br />
<br />
public override IOperand Eval( IOperand lhs, IOperand rhs )<br />
{<br />
if( !(lhs is ILogicalOperations) )<br />
throw new RPN_Exception("Argument invalid in LogicalOperator.Eval - Invalid Expression : lhs" );<br />
switch( m_szOperator )<br />
{<br />
case "&&":<br />
return ((ILogicalOperations)lhs).AND( rhs );<br />
case "||":<br />
return ((ILogicalOperations)lhs).OR( rhs );<br />
}<br />
throw new RPN_Exception("Unsupported Logical operation " + m_szOperator );<br />
}<br />
}<br />
<br />
public class OperatorHelper<br />
{<br />
static public IOperator CreateOperator( string szOperator )<br />
{<br />
IOperator oprtr = null;<br />
if( OperatorHelper.IsArithmeticOperator( szOperator ) )<br />
{<br />
oprtr = new ArithmeticOperator( szOperator );<br />
return oprtr;<br />
}<br />
if( OperatorHelper.IsComparisonOperator( szOperator ) )<br />
{<br />
oprtr = new ComparisonOperator( szOperator );<br />
return oprtr;<br />
}<br />
if( OperatorHelper.IsLogicalOperator( szOperator ) )<br />
{<br />
oprtr = new LogicalOperator( szOperator );<br />
return oprtr;<br />
}<br />
throw new RPN_Exception("Unhandled Operator : " + szOperator );<br />
}<br />
static public IOperator CreateOperator( char cOperator )<br />
{<br />
return CreateOperator( new string( cOperator, 1 ) );<br />
}<br />
public static bool IsOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllOps, currentOp.Trim() );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsUnaryOperator(string currentOp)<br />
{<br />
int nPos = Array.IndexOf(m_AllUnaryOps, currentOp.Trim());<br />
if (nPos != -1)<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsArithmeticOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllArithmeticOps, currentOp );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsComparisonOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllComparisonOps, currentOp );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsLogicalOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllLogicalOps, currentOp );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
#region Precedence<br />
<br />
public static bool IsLowerPrecOperator( string currentOp, string prevOp )<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );<br />
if( nCurrIdx < nPrevIdx )<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
<br />
public static bool IsHigherPrecOperator( string currentOp, string prevOp )<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );<br />
if( nCurrIdx > nPrevIdx )<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
<br />
public static bool IsEqualPrecOperator( string currentOp, string prevOp )<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );<br />
if( nCurrIdx == nPrevIdx )<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
private static void GetCurrentAndPreviousIndex( string[] allOps, string currentOp, string prevOp,<br />
out int nCurrIdx, out int nPrevIdx )<br />
{<br />
nCurrIdx = -1;<br />
nPrevIdx = -1;<br />
for( int nIdx = 0; nIdx < allOps.Length; nIdx++ )<br />
{<br />
if( allOps[nIdx] == currentOp )<br />
{<br />
nCurrIdx = nIdx;<br />
}<br />
if( allOps[nIdx] == prevOp )<br />
{<br />
nPrevIdx = nIdx;<br />
}<br />
if( nPrevIdx != -1 && nCurrIdx != -1 )<br />
{<br />
break;<br />
}<br />
}<br />
if( nCurrIdx == -1 )<br />
{<br />
throw new RPN_Exception("Unknown operator - " + currentOp );<br />
}<br />
if( nPrevIdx == -1 )<br />
{<br />
throw new RPN_Exception("Unknown operator - " + prevOp );<br />
}<br />
<br />
}<br />
#endregion<br />
#region RegEx<br />
static public string GetOperatorsRegEx( ExpressionType exType )<br />
{<br />
StringBuilder strRegex = new StringBuilder();<br />
if( (exType & ExpressionType.ET_ARITHMETIC).Equals(ExpressionType.ET_ARITHMETIC) )<br />
{<br />
if( strRegex.Length == 0 )<br />
{<br />
strRegex.Append( m_szArthmtcRegEx );<br />
}<br />
else<br />
{<br />
strRegex.Append( "|" + m_szArthmtcRegEx );<br />
}<br />
}<br />
if( (exType & ExpressionType.ET_COMPARISON).Equals(ExpressionType.ET_COMPARISON) )<br />
{<br />
if( strRegex.Length == 0 )<br />
{<br />
strRegex.Append( m_szCmprsnRegEx );<br />
}<br />
else<br />
{<br />
strRegex.Append( "|" + m_szCmprsnRegEx );<br />
}<br />
}<br />
if( (exType & ExpressionType.ET_LOGICAL).Equals(ExpressionType.ET_LOGICAL) )<br />
{<br />
if( strRegex.Length == 0 )<br />
{<br />
strRegex.Append( m_szLgclRegEx );<br />
}<br />
else<br />
{<br />
strRegex.Append( "|" + m_szLgclRegEx );<br />
}<br />
}<br />
if( strRegex.Length == 0 )<br />
throw new RPN_Exception("Invalid combination of ExpressionType value");<br />
return "(" + strRegex.ToString() + ")";<br />
}<br />
static string m_szArthmtcRegEx = @"[+\-*/%()]{1}";<br />
static string m_szCmprsnRegEx = @"[=<>!]{1,2}";<br />
static string m_szLgclRegEx = @"[&|]{2}";<br />
static string m_szUnaryRegEx = @"[~]{1}";<br />
#endregion<br />
<br />
public static string[] AllOperators<br />
{<br />
get<br />
{<br />
return m_AllOps;<br />
}<br />
}<br />
<br />
static string[] m_AllOps = { "||", "&&", "|", "^", "&", "==", "!=",<br />
"<", "<=", ">", ">=", "+", "-", "*", "/","~", "%", "(", ")" };<br />
static string[] m_AllArithmeticOps = { "+", "-","~", "*", "/", "%" };<br />
static string[] m_AllComparisonOps = { "==", "!=","<", "<=", ">", ">=" };<br />
static string[] m_AllLogicalOps = { "&&", "||" };<br />
static string[] m_AllUnaryOps = { "~" };<br />
}<br />
<br />
#endregion<br />
<br />
#region TODO List<br />
#endregion<br />
#region Content check<br />
public class StringContentCheck<br />
{<br />
static public bool IsNaturalNumber(String strNumber)<br />
{<br />
Regex objNotNaturalPattern=new Regex("[^0-9]");<br />
Regex objNaturalPattern=new Regex("0*[1-9][0-9]*");<br />
return !objNotNaturalPattern.IsMatch(strNumber) &&<br />
objNaturalPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsWholeNumber(String strNumber)<br />
{<br />
Regex objNotWholePattern=new Regex("[^0-9]");<br />
return !objNotWholePattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsInteger(String strNumber)<br />
{<br />
Regex objNotIntPattern=new Regex("[^0-9-]");<br />
Regex objIntPattern=new Regex("^-[0-9]+$|^[0-9]+$");<br />
return !objNotIntPattern.IsMatch(strNumber) && objIntPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsPositiveNumber(String strNumber)<br />
{<br />
Regex objNotPositivePattern=new Regex("[^0-9.]");<br />
Regex objPositivePattern=new Regex("^[.][0-9]+$|[0-9]*[.]*[0-9]+$");<br />
Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");<br />
return !objNotPositivePattern.IsMatch(strNumber) &&<br />
objPositivePattern.IsMatch(strNumber) &&<br />
!objTwoDotPattern.IsMatch(strNumber);<br />
}<br />
<br />
static public bool IsNumber(String strNumber)<br />
{<br />
Regex objNotNumberPattern=new Regex("[^0-9.-]");<br />
Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");<br />
Regex objTwoMinusPattern=new Regex("[0-9]*[-][0-9]*[-][0-9]*");<br />
String strValidRealPattern="^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$";<br />
String strValidIntegerPattern="^([-]|[0-9])[0-9]*$";<br />
Regex objNumberPattern =new Regex("(" + strValidRealPattern +")|(" + strValidIntegerPattern + ")");<br />
return !objNotNumberPattern.IsMatch(strNumber) &&<br />
!objTwoDotPattern.IsMatch(strNumber) &&<br />
!objTwoMinusPattern.IsMatch(strNumber) &&<br />
objNumberPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsAlpha(String strToCheck)<br />
{<br />
Regex objAlphaPattern=new Regex("[^a-zA-Z ]");<br />
return !objAlphaPattern.IsMatch(strToCheck);<br />
}<br />
static public bool IsAlphaNumeric(String strToCheck)<br />
{<br />
Regex objAlphaNumericPattern=new Regex("[^a-zA-Z0-9 ]");<br />
return !objAlphaNumericPattern.IsMatch(strToCheck);<br />
}<br />
}<br />
#endregion<br />
<br />
}<br />
-- modified at 10:31 Thursday 22nd June, 2006
|
|
|
|
|
I've added support for the negation operator (-). It gets converted into a (~) and placed in the RPN expression as such. Some tweaking was done to the evaluator to look for unary and handle that situation.
thanks for this code, helped me out in a big way, hope someone finds the unary support worthwhile and decides to add upon it.
using System;<br />
using System.Collections;<br />
using System.Text;<br />
using System.Text.RegularExpressions;<br />
<br />
#region RPN<br />
public class RPNParser<br />
{<br />
public RPNParser()<br />
{<br />
}<br />
public object SetupExpression(string szExpr, Type varType, bool bFormula, Hashtable htValues)<br />
{<br />
ArrayList arrExpr = GetPostFixNotation(szExpr, varType, bFormula);<br />
return Convert2String(arrExpr);<br />
}<br />
public object EvaluateExpression(string szExpr, Type varType, bool bFormula, Hashtable htValues)<br />
{<br />
ArrayList arrExpr = GetPostFixNotation(szExpr, varType, bFormula);<br />
return EvaluateRPN(arrExpr, varType, htValues);<br />
}<br />
<br />
#region RPN_Parser<br />
public ArrayList GetPostFixNotation(string szExpr, Type varType, bool bFormula)<br />
{<br />
Stack stkOp = new Stack();<br />
ArrayList arrFinalExpr = new ArrayList();<br />
string szResult = "";<br />
string szLastItem = "";<br />
bool bApplyNegative = false;<br />
<br />
Tokenizer tknzr = null;<br />
switch (varType.ToString())<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
tknzr = new Tokenizer(szExpr, ExpressionType.ET_ARITHMETIC |<br />
ExpressionType.ET_COMPARISON |<br />
ExpressionType.ET_LOGICAL);<br />
break;<br />
case "System.String":<br />
tknzr = new Tokenizer(szExpr, ExpressionType.ET_COMPARISON);<br />
break;<br />
}<br />
<br />
<br />
<br />
foreach (Token token in tknzr)<br />
{<br />
string szToken = token.Value.Trim();<br />
if (szToken.Length == 0)<br />
continue;<br />
switch (varType.ToString())<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
if (!OperatorHelper.IsOperator(szToken))<br />
{<br />
Operand oprnd = OperandHelper.CreateOperand(szToken, varType);<br />
oprnd.ExtractAndSetValue(szToken, bFormula);<br />
arrFinalExpr.Add(oprnd);<br />
<br />
szResult += szToken;<br />
szLastItem = szToken;<br />
continue;<br />
}<br />
break;<br />
case "System.String":<br />
if (!OperatorHelper.IsComparisonOperator(szToken))<br />
{<br />
Operand oprnd = OperandHelper.CreateOperand(szToken, varType);<br />
oprnd.ExtractAndSetValue(szToken, bFormula);<br />
arrFinalExpr.Add(oprnd);<br />
<br />
szResult += szToken;<br />
szLastItem = szToken;<br />
continue;<br />
}<br />
<br />
break;<br />
}<br />
<br />
string szOp = szToken;<br />
if (szOp == "(")<br />
{<br />
stkOp.Push(szOp);<br />
}<br />
else if (szOp == ")")<br />
{<br />
string szTop;<br />
while ((szTop = (string)stkOp.Pop()) != "(")<br />
{<br />
IOperator oprtr = OperatorHelper.CreateOperator(szTop);<br />
arrFinalExpr.Add(oprtr);<br />
<br />
szResult += szTop;<br />
<br />
if (stkOp.Count == 0)<br />
throw new RPN_Exception("Unmatched braces!");<br />
}<br />
}<br />
else<br />
{<br />
if (szOp == "-" && (!StringContentCheck.IsAlphaNumeric(szLastItem) || szLastItem==""))<br />
{<br />
bApplyNegative = true;<br />
<br />
stkOp.Push("~");<br />
<br />
<br />
}<br />
else<br />
{<br />
if (stkOp.Count == 0 || (string)stkOp.Peek() == "("<br />
|| OperatorHelper.IsHigherPrecOperator(szOp, (string)stkOp.Peek()))<br />
{<br />
stkOp.Push(szOp);<br />
}<br />
else<br />
{<br />
while (stkOp.Count != 0)<br />
{<br />
if (OperatorHelper.IsLowerPrecOperator(szOp, (string)stkOp.Peek())<br />
|| OperatorHelper.IsEqualPrecOperator(szOp, (string)stkOp.Peek()))<br />
{<br />
string szTop = (string)stkOp.Peek();<br />
if (szTop == "(")<br />
break;<br />
szTop = (string)stkOp.Pop();<br />
<br />
IOperator oprtr = OperatorHelper.CreateOperator(szTop);<br />
arrFinalExpr.Add(oprtr);<br />
<br />
szResult += szTop;<br />
}<br />
else<br />
break;<br />
}<br />
stkOp.Push(szOp);<br />
}<br />
}<br />
}<br />
szLastItem = szToken;<br />
}<br />
while (stkOp.Count != 0)<br />
{<br />
string szTop = (string)stkOp.Pop();<br />
if (szTop == "(")<br />
throw new RPN_Exception("Unmatched braces");<br />
<br />
IOperator oprtr = OperatorHelper.CreateOperator(szTop);<br />
arrFinalExpr.Add(oprtr);<br />
<br />
szResult += szTop;<br />
}<br />
return arrFinalExpr;<br />
}<br />
<br />
#endregion<br />
<br />
public string Convert2String(ArrayList arrExpr)<br />
{<br />
string szResult = "";<br />
foreach (object obj in arrExpr)<br />
{<br />
szResult += obj.ToString() + " ";<br />
}<br />
return szResult;<br />
}<br />
<br />
<br />
#region RPN_Evaluator<br />
<br />
public object EvaluateRPN(ArrayList arrExpr, Type varType, Hashtable htValues)<br />
{<br />
Stack stPad = new Stack();<br />
foreach (object var in arrExpr)<br />
{<br />
Operand op1 = null;<br />
Operand op2 = null;<br />
IOperator oprtr = null;<br />
if (var is IOperand)<br />
{<br />
stPad.Push(var);<br />
}<br />
else if (var is IOperator)<br />
{<br />
if (OperatorHelper.IsUnaryOperator(((Operator)var).ToString()))<br />
{<br />
op1 = (Operand)stPad.Pop();<br />
if (htValues != null)<br />
{<br />
op1.Value = htValues[op1.Name];<br />
}<br />
oprtr = (IOperator)var;<br />
IOperand opRes = oprtr.Eval(op1);<br />
stPad.Push(opRes);<br />
}<br />
else<br />
{<br />
op2 = (Operand)stPad.Pop();<br />
if (htValues != null)<br />
{<br />
op2.Value = htValues[op2.Name];<br />
}<br />
op1 = (Operand)stPad.Pop();<br />
if (htValues != null)<br />
{<br />
op1.Value = htValues[op1.Name];<br />
}<br />
oprtr = (IOperator)var;<br />
IOperand opRes = oprtr.Eval(op1, op2);<br />
stPad.Push(opRes);<br />
}<br />
}<br />
}<br />
return ((Operand)stPad.Pop()).Value;<br />
}<br />
#endregion<br />
}<br />
#endregion<br />
<br />
#region UtilClasses<br />
<br />
[Flags]<br />
public enum ExpressionType<br />
{<br />
ET_ARITHMETIC = 0x0001,<br />
ET_COMPARISON = 0x0002,<br />
ET_LOGICAL = 0x0004<br />
}<br />
public enum TokenType<br />
{<br />
TT_OPERATOR,<br />
TT_OPERAND<br />
}<br />
public class Token<br />
{<br />
public Token(string szValue)<br />
{<br />
m_szValue = szValue;<br />
}<br />
public string Value<br />
{<br />
get<br />
{<br />
return m_szValue;<br />
}<br />
}<br />
string m_szValue;<br />
}<br />
public class Tokenizer : IEnumerable<br />
{<br />
public Tokenizer(string szExpression)<br />
: this(szExpression, ExpressionType.ET_ARITHMETIC |<br />
ExpressionType.ET_COMPARISON |<br />
ExpressionType.ET_LOGICAL)<br />
{<br />
}<br />
public Tokenizer(string szExpression, ExpressionType exType)<br />
{<br />
m_szExpression = szExpression;<br />
m_exType = exType;<br />
m_RegEx = new Regex(OperatorHelper.GetOperatorsRegEx(m_exType));<br />
m_strarrTokens = SplitExpression(szExpression);<br />
}<br />
public IEnumerator GetEnumerator()<br />
{<br />
return new TokenEnumerator(m_strarrTokens);<br />
}<br />
public string[] SplitExpression(string szExpression)<br />
{<br />
return m_RegEx.Split(szExpression);<br />
}<br />
ExpressionType m_exType;<br />
string m_szExpression;<br />
string[] m_strarrTokens;<br />
Regex m_RegEx;<br />
}<br />
<br />
public class TokenEnumerator : IEnumerator<br />
{<br />
Token m_Token;<br />
int m_nIdx;<br />
string[] m_strarrTokens;<br />
<br />
public TokenEnumerator(string[] strarrTokens)<br />
{<br />
m_strarrTokens = strarrTokens;<br />
Reset();<br />
}<br />
public object Current<br />
{<br />
get<br />
{<br />
return m_Token;<br />
}<br />
}<br />
public bool MoveNext()<br />
{<br />
if (m_nIdx >= m_strarrTokens.Length)<br />
return false;<br />
<br />
m_Token = new Token(m_strarrTokens[m_nIdx]);<br />
m_nIdx++;<br />
return true;<br />
}<br />
public void Reset()<br />
{<br />
m_nIdx = 0;<br />
}<br />
}<br />
#region Exceptions<br />
public class RPN_Exception : ApplicationException<br />
{<br />
public RPN_Exception()<br />
{<br />
}<br />
public RPN_Exception(string szMessage)<br />
: base(szMessage)<br />
{<br />
}<br />
public RPN_Exception(string szMessage, Exception innerException)<br />
: base(szMessage, innerException)<br />
{<br />
}<br />
}<br />
#endregion<br />
#endregion<br />
<br />
#region Interfaces<br />
public interface IOperand { }<br />
public interface IOperator<br />
{<br />
IOperand Eval(IOperand lhs, IOperand rhs);<br />
IOperand Eval(IOperand lhs);<br />
}<br />
<br />
public interface IArithmeticOperations<br />
{<br />
IOperand Plus(IOperand rhs);<br />
IOperand Minus(IOperand rhs);<br />
IOperand Negate();<br />
IOperand Multiply(IOperand rhs);<br />
IOperand Divide(IOperand rhs);<br />
IOperand Modulo(IOperand rhs);<br />
}<br />
public interface IComparisonOperations<br />
{<br />
IOperand EqualTo(IOperand rhs);<br />
IOperand NotEqualTo(IOperand rhs);<br />
IOperand LessThan(IOperand rhs);<br />
IOperand LessThanOrEqualTo(IOperand rhs);<br />
IOperand GreaterThan(IOperand rhs);<br />
IOperand GreaterThanOrEqualTo(IOperand rhs);<br />
}<br />
public interface ILogicalOperations<br />
{<br />
IOperand OR(IOperand rhs);<br />
IOperand AND(IOperand rhs);<br />
}<br />
#endregion<br />
<br />
#region Operands<br />
public abstract class Operand : IOperand<br />
{<br />
public Operand(string szVarName, object varValue)<br />
{<br />
m_szVarName = szVarName;<br />
m_VarValue = varValue;<br />
}<br />
public Operand(string szVarName)<br />
{<br />
m_szVarName = szVarName;<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public abstract void ExtractAndSetValue(string szValue, bool bFormula);<br />
public string Name<br />
{<br />
get<br />
{<br />
return m_szVarName;<br />
}<br />
set<br />
{<br />
m_szVarName = value;<br />
}<br />
}<br />
public object Value<br />
{<br />
get<br />
{<br />
return m_VarValue;<br />
}<br />
set<br />
{<br />
m_VarValue = value;<br />
}<br />
}<br />
protected string m_szVarName = "";<br />
protected object m_VarValue = null;<br />
}<br />
public class LongOperand : Operand, IArithmeticOperations, IComparisonOperations<br />
{<br />
public LongOperand(string szVarName, object varValue)<br />
: base(szVarName, varValue)<br />
{<br />
}<br />
public LongOperand(string szVarName)<br />
: base(szVarName)<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public override void ExtractAndSetValue(string szValue, bool bFormula)<br />
{<br />
m_VarValue = !bFormula ? Convert.ToInt64(szValue) : 0;<br />
}<br />
public IOperand Plus(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.Plus : rhs");<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));<br />
oprResult.Value = (long)this.Value + (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Minus(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.Minus : rhs");<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));<br />
oprResult.Value = (long)this.Value - (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Negate()<br />
{<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));<br />
oprResult.Value = (long)this.Value * -1;<br />
return oprResult;<br />
}<br />
public IOperand Multiply(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new ArgumentException("Argument invalid in LongOperand.Multiply : rhs");<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));<br />
oprResult.Value = (long)this.Value * (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Divide(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.Divide : rhs");<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));<br />
oprResult.Value = (long)this.Value / (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Modulo(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.Modulo : rhs");<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64"));<br />
oprResult.Value = (long)this.Value % (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
<br />
public IOperand EqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.== : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = (long)this.Value == (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand NotEqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.!= : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value != (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThan(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.< : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value < (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThanOrEqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.<= : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value <= (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThan(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.> : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value > (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThanOrEqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is LongOperand))<br />
throw new RPN_Exception("Argument invalid in LongOperand.>= : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value >= (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
}<br />
public class BoolOperand : Operand, ILogicalOperations<br />
{<br />
public BoolOperand(string szVarName, object varValue)<br />
: base(szVarName, varValue)<br />
{<br />
}<br />
public BoolOperand(string szVarName)<br />
: base(szVarName)<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return this.Value.ToString();<br />
}<br />
public override void ExtractAndSetValue(string szValue, bool bFormula)<br />
{<br />
m_VarValue = !bFormula ? Convert.ToBoolean(szValue) : false;<br />
}<br />
public IOperand AND(IOperand rhs)<br />
{<br />
if (!(rhs is BoolOperand))<br />
throw new RPN_Exception("Argument invalid in BoolOperand.&& : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((bool)this.Value && (bool)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand OR(IOperand rhs)<br />
{<br />
if (!(rhs is BoolOperand))<br />
throw new RPN_Exception("Argument invalid in BoolOperand.|| : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((bool)this.Value || (bool)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
}<br />
<br />
public class OperandHelper<br />
{<br />
static public Operand CreateOperand(string szVarName, Type varType, object varValue)<br />
{<br />
Operand oprResult = null;<br />
switch (varType.ToString())<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
oprResult = new LongOperand(szVarName, varValue);<br />
return oprResult;<br />
case "System.String":<br />
oprResult = new StringOperand(szVarName, varValue);<br />
return oprResult;<br />
<br />
<br />
<br />
<br />
}<br />
throw new RPN_Exception("Unhandled type : " + varType.ToString());<br />
}<br />
static public Operand CreateOperand(string szVarName, Type varType)<br />
{<br />
return OperandHelper.CreateOperand(szVarName, varType, null);<br />
}<br />
}<br />
public class StringOperand : Operand, IComparisonOperations<br />
{<br />
public StringOperand(string szVarName, object varValue)<br />
: base(szVarName, varValue)<br />
{<br />
}<br />
public StringOperand(string szVarName)<br />
: base(szVarName)<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public override void ExtractAndSetValue(string szValue, bool bFormula)<br />
{<br />
m_VarValue = !bFormula ? Convert.ToString(szValue) : "";<br />
}<br />
public IOperand EqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is StringOperand))<br />
throw new RPN_Exception("Argument invalid in StringOperand.== : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = (string)this.Value == (string)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand NotEqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is StringOperand))<br />
throw new RPN_Exception("Argument invalid in StringOperand.!= : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((string)this.Value != (string)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThan(IOperand rhs)<br />
{<br />
throw new RPN_Exception("LessThan operator is invalid for string");<br />
}<br />
public IOperand LessThanOrEqualTo(IOperand rhs)<br />
{<br />
throw new RPN_Exception("LessThanOrEqualTo operator is invalid for string");<br />
}<br />
public IOperand GreaterThan(IOperand rhs)<br />
{<br />
throw new RPN_Exception("GreaterThan operator is invalid for string");<br />
}<br />
public IOperand GreaterThanOrEqualTo(IOperand rhs)<br />
{<br />
throw new RPN_Exception("GreaterThanOrEqualTo operator is invalid for string");<br />
}<br />
}<br />
#endregion<br />
<br />
#region Operators<br />
public abstract class Operator : IOperator<br />
{<br />
public Operator(char cOperator)<br />
{<br />
m_szOperator = new String(cOperator, 1);<br />
}<br />
public Operator(string szOperator)<br />
{<br />
m_szOperator = szOperator;<br />
}<br />
public override string ToString()<br />
{<br />
return m_szOperator;<br />
}<br />
public abstract IOperand Eval(IOperand lhs, IOperand rhs);<br />
public abstract IOperand Eval(IOperand lhs);<br />
public string Value<br />
{<br />
get<br />
{<br />
return m_szOperator;<br />
}<br />
set<br />
{<br />
m_szOperator = value;<br />
}<br />
}<br />
protected string m_szOperator = "";<br />
}<br />
public class ArithmeticOperator : Operator<br />
{<br />
public ArithmeticOperator(char cOperator)<br />
: base(cOperator)<br />
{<br />
}<br />
public ArithmeticOperator(string szOperator)<br />
: base(szOperator)<br />
{<br />
}<br />
<br />
public override IOperand Eval(IOperand lhs, IOperand rhs)<br />
{<br />
if (!(lhs is IArithmeticOperations))<br />
throw new RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs");<br />
switch (m_szOperator)<br />
{<br />
case "+":<br />
return ((IArithmeticOperations)lhs).Plus(rhs);<br />
case "-":<br />
return ((IArithmeticOperations)lhs).Minus(rhs);<br />
case "*":<br />
return ((IArithmeticOperations)lhs).Multiply(rhs);<br />
case "/":<br />
return ((IArithmeticOperations)lhs).Divide(rhs);<br />
case "%":<br />
return ((IArithmeticOperations)lhs).Modulo(rhs);<br />
}<br />
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator);<br />
}<br />
<br />
public override IOperand Eval(IOperand lhs)<br />
{<br />
if (!(lhs is IArithmeticOperations))<br />
throw new RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs");<br />
switch (m_szOperator)<br />
{<br />
case "~":<br />
return ((IArithmeticOperations)lhs).Negate();<br />
}<br />
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator);<br />
}<br />
}<br />
public class ComparisonOperator : Operator<br />
{<br />
public ComparisonOperator(char cOperator)<br />
: base(cOperator)<br />
{<br />
}<br />
public ComparisonOperator(string szOperator)<br />
: base(szOperator)<br />
{<br />
}<br />
<br />
public override IOperand Eval(IOperand lhs) { return null; }<br />
<br />
public override IOperand Eval(IOperand lhs, IOperand rhs)<br />
{<br />
if (!(lhs is IComparisonOperations))<br />
throw new RPN_Exception("Argument invalid in ComparisonOperator.Eval - Invalid Expression : lhs");<br />
switch (m_szOperator)<br />
{<br />
case "==":<br />
return ((IComparisonOperations)lhs).EqualTo(rhs);<br />
case "!=":<br />
return ((IComparisonOperations)lhs).NotEqualTo(rhs);<br />
case "<":<br />
return ((IComparisonOperations)lhs).LessThan(rhs);<br />
case "<=":<br />
return ((IComparisonOperations)lhs).LessThanOrEqualTo(rhs);<br />
case ">":<br />
return ((IComparisonOperations)lhs).GreaterThan(rhs);<br />
case ">=":<br />
return ((IComparisonOperations)lhs).GreaterThanOrEqualTo(rhs);<br />
}<br />
throw new RPN_Exception("Unsupported Comparison operation " + m_szOperator);<br />
}<br />
}<br />
<br />
public class LogicalOperator : Operator<br />
{<br />
public LogicalOperator(char cOperator)<br />
: base(cOperator)<br />
{<br />
}<br />
public LogicalOperator(string szOperator)<br />
: base(szOperator)<br />
{<br />
}<br />
<br />
public override IOperand Eval(IOperand lhs) { return null; }<br />
<br />
public override IOperand Eval(IOperand lhs, IOperand rhs)<br />
{<br />
if (!(lhs is ILogicalOperations))<br />
throw new RPN_Exception("Argument invalid in LogicalOperator.Eval - Invalid Expression : lhs");<br />
switch (m_szOperator)<br />
{<br />
case "&&":<br />
return ((ILogicalOperations)lhs).AND(rhs);<br />
case "||":<br />
return ((ILogicalOperations)lhs).OR(rhs);<br />
}<br />
throw new RPN_Exception("Unsupported Logical operation " + m_szOperator);<br />
}<br />
}<br />
<br />
public class OperatorHelper<br />
{<br />
static public IOperator CreateOperator(string szOperator)<br />
{<br />
IOperator oprtr = null;<br />
if (OperatorHelper.IsArithmeticOperator(szOperator))<br />
{<br />
oprtr = new ArithmeticOperator(szOperator);<br />
return oprtr;<br />
}<br />
if (OperatorHelper.IsComparisonOperator(szOperator))<br />
{<br />
oprtr = new ComparisonOperator(szOperator);<br />
return oprtr;<br />
}<br />
if (OperatorHelper.IsLogicalOperator(szOperator))<br />
{<br />
oprtr = new LogicalOperator(szOperator);<br />
return oprtr;<br />
}<br />
throw new RPN_Exception("Unhandled Operator : " + szOperator);<br />
}<br />
static public IOperator CreateOperator(char cOperator)<br />
{<br />
return CreateOperator(new string(cOperator, 1));<br />
}<br />
public static bool IsOperator(string currentOp)<br />
{<br />
int nPos = Array.IndexOf(m_AllOps, currentOp.Trim());<br />
if (nPos != -1)<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsUnaryOperator(string currentOp)<br />
{<br />
int nPos = Array.IndexOf(m_AllUnaryOps, currentOp.Trim());<br />
if (nPos != -1)<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsArithmeticOperator(string currentOp)<br />
{<br />
int nPos = Array.IndexOf(m_AllArithmeticOps, currentOp);<br />
if (nPos != -1)<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsComparisonOperator(string currentOp)<br />
{<br />
int nPos = Array.IndexOf(m_AllComparisonOps, currentOp);<br />
if (nPos != -1)<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsLogicalOperator(string currentOp)<br />
{<br />
int nPos = Array.IndexOf(m_AllLogicalOps, currentOp);<br />
if (nPos != -1)<br />
return true;<br />
else<br />
return false;<br />
}<br />
#region Precedence<br />
<br />
public static bool IsLowerPrecOperator(string currentOp, string prevOp)<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx);<br />
if (nCurrIdx < nPrevIdx)<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
<br />
public static bool IsHigherPrecOperator(string currentOp, string prevOp)<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx);<br />
if (nCurrIdx > nPrevIdx)<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
<br />
public static bool IsEqualPrecOperator(string currentOp, string prevOp)<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex(m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx);<br />
if (nCurrIdx == nPrevIdx)<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
private static void GetCurrentAndPreviousIndex(string[] allOps, string currentOp, string prevOp,<br />
out int nCurrIdx, out int nPrevIdx)<br />
{<br />
nCurrIdx = -1;<br />
nPrevIdx = -1;<br />
for (int nIdx = 0; nIdx < allOps.Length; nIdx++)<br />
{<br />
if (allOps[nIdx] == currentOp)<br />
{<br />
nCurrIdx = nIdx;<br />
}<br />
if (allOps[nIdx] == prevOp)<br />
{<br />
nPrevIdx = nIdx;<br />
}<br />
if (nPrevIdx != -1 && nCurrIdx != -1)<br />
{<br />
break;<br />
}<br />
}<br />
if (nCurrIdx == -1)<br />
{<br />
throw new RPN_Exception("Unknown operator - " + currentOp);<br />
}<br />
if (nPrevIdx == -1)<br />
{<br />
throw new RPN_Exception("Unknown operator - " + prevOp);<br />
}<br />
<br />
}<br />
#endregion<br />
#region RegEx<br />
static public string GetOperatorsRegEx(ExpressionType exType)<br />
{<br />
StringBuilder strRegex = new StringBuilder();<br />
if ((exType & ExpressionType.ET_ARITHMETIC).Equals(ExpressionType.ET_ARITHMETIC))<br />
{<br />
if (strRegex.Length == 0)<br />
{<br />
strRegex.Append(m_szArthmtcRegEx);<br />
}<br />
else<br />
{<br />
strRegex.Append("|" + m_szArthmtcRegEx);<br />
}<br />
}<br />
if ((exType & ExpressionType.ET_COMPARISON).Equals(ExpressionType.ET_COMPARISON))<br />
{<br />
if (strRegex.Length == 0)<br />
{<br />
strRegex.Append(m_szCmprsnRegEx);<br />
}<br />
else<br />
{<br />
strRegex.Append("|" + m_szCmprsnRegEx);<br />
}<br />
}<br />
if ((exType & ExpressionType.ET_LOGICAL).Equals(ExpressionType.ET_LOGICAL))<br />
{<br />
if (strRegex.Length == 0)<br />
{<br />
strRegex.Append(m_szLgclRegEx);<br />
}<br />
else<br />
{<br />
strRegex.Append("|" + m_szLgclRegEx);<br />
}<br />
}<br />
if (strRegex.Length == 0)<br />
throw new RPN_Exception("Invalid combination of ExpressionType value");<br />
return "(" + strRegex.ToString() + ")";<br />
}<br />
static string m_szArthmtcRegEx = @"[+\-*/%()]{1}";<br />
static string m_szCmprsnRegEx = @"[=<>!]{1,2}";<br />
static string m_szLgclRegEx = @"[&|]{2}";<br />
static string m_szUnaryRegEx = @"[~]{1}";<br />
#endregion<br />
<br />
public static string[] AllOperators<br />
{<br />
get<br />
{<br />
return m_AllOps;<br />
}<br />
}<br />
<br />
static string[] m_AllOps = { "||", "&&", "|", "^", "&", "==", "!=",<br />
"<", "<=", ">", ">=", "+", "-", "*", "/", "~", "%", "(", ")" };<br />
static string[] m_AllArithmeticOps = { "+", "-", "~", "*", "/", "%" };<br />
static string[] m_AllComparisonOps = { "==", "!=", "<", "<=", ">", ">=" };<br />
static string[] m_AllLogicalOps = { "&&", "||" };<br />
static string[] m_AllUnaryOps = { "~" };<br />
}<br />
<br />
#endregion<br />
<br />
#region TODO List<br />
#endregion<br />
#region Content check<br />
public class StringContentCheck<br />
{<br />
static public bool IsNaturalNumber(String strNumber)<br />
{<br />
Regex objNotNaturalPattern = new Regex("[^0-9]");<br />
Regex objNaturalPattern = new Regex("0*[1-9][0-9]*");<br />
return !objNotNaturalPattern.IsMatch(strNumber) &&<br />
objNaturalPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsWholeNumber(String strNumber)<br />
{<br />
Regex objNotWholePattern = new Regex("[^0-9]");<br />
return !objNotWholePattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsInteger(String strNumber)<br />
{<br />
Regex objNotIntPattern = new Regex("[^0-9-]");<br />
Regex objIntPattern = new Regex("^-[0-9]+$|^[0-9]+$");<br />
return !objNotIntPattern.IsMatch(strNumber) && objIntPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsPositiveNumber(String strNumber)<br />
{<br />
Regex objNotPositivePattern = new Regex("[^0-9.]");<br />
Regex objPositivePattern = new Regex("^[.][0-9]+$|[0-9]*[.]*[0-9]+$");<br />
Regex objTwoDotPattern = new Regex("[0-9]*[.][0-9]*[.][0-9]*");<br />
return !objNotPositivePattern.IsMatch(strNumber) &&<br />
objPositivePattern.IsMatch(strNumber) &&<br />
!objTwoDotPattern.IsMatch(strNumber);<br />
}<br />
<br />
static public bool IsNumber(String strNumber)<br />
{<br />
Regex objNotNumberPattern = new Regex("[^0-9.-]");<br />
Regex objTwoDotPattern = new Regex("[0-9]*[.][0-9]*[.][0-9]*");<br />
Regex objTwoMinusPattern = new Regex("[0-9]*[-][0-9]*[-][0-9]*");<br />
String strValidRealPattern = "^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$";<br />
String strValidIntegerPattern = "^([-]|[0-9])[0-9]*$";<br />
Regex objNumberPattern = new Regex("(" + strValidRealPattern + ")|(" + strValidIntegerPattern + ")");<br />
return !objNotNumberPattern.IsMatch(strNumber) &&<br />
!objTwoDotPattern.IsMatch(strNumber) &&<br />
!objTwoMinusPattern.IsMatch(strNumber) &&<br />
objNumberPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsAlpha(String strToCheck)<br />
{<br />
Regex objAlphaPattern = new Regex("[^a-zA-Z ]");<br />
return !objAlphaPattern.IsMatch(strToCheck);<br />
}<br />
static public bool IsAlphaNumeric(String strToCheck)<br />
{<br />
Regex objAlphaNumericPattern = new Regex("[^a-zA-Z0-9 ]");<br />
return !objAlphaNumericPattern.IsMatch(strToCheck);<br />
}<br />
}<br />
#endregion
|
|
|
|
|
Enter expression
-2+3
and see what happens.
|
|
|
|
|
This is not a bug, he specifically mentioned there was no support for unary operators yet, but I have just given this code support for unary operators, so far only negation is supported. Will post in new thread.
|
|
|
|
|
Hi all,
I have made some changes to achieve string comparators.
The major changes are:
- in GetPostFixNotation the for each token are checked if it is an operand but without checking the operators supported by the variable type (Int32, Int64, String), the change made checks the variable type and only check the supported operations (IComparisonOperations for String type)
- in Tokenizer, the same problem arrives, I’ve added a variable type check, and token’s are only obtained for valid operations.
Hope Helps,
NeuralC
Code:
using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
namespace cfring.util
{
#region RPN
///
/// Summary description for RPNParser.
///
public class RPNParser
{
public RPNParser()
{
}
public object EvaluateExpression( string szExpr, Type varType, bool bFormula, Hashtable htValues )
{
ArrayList arrExpr = GetPostFixNotation( szExpr, varType, bFormula );
return EvaluateRPN(arrExpr, varType, htValues );
}
#region RPN_Parser
///
/// Algo of GetPostFixNotation (source : Expression Evaluator : using RPN by lallous
/// in the C++/MFC section of www.CodeProject.com.
/// 1. Initialize an empty stack (string stack), prepare input infix expression and clear RPN string
/// 2. Repeat until we reach end of infix expression
/// I. Get token (operand or operator); skip white spaces
/// II. If token is:
/// a. Left parenthesis: Push it into stack
/// b. Right parenthesis: Keep popping from the stack and appending to
/// RPN string until we reach the left parenthesis.
/// If stack becomes empty and we didn't reach the left parenthesis
/// then break out with error "Unbalanced parenthesis"
/// c. Operator: If stack is empty or operator has a higher precedence than
/// the top of the stack then push operator into stack.
/// Else if operator has lower precedence then we keep popping and
/// appending to RPN string, this is repeated until operator in stack
/// has lower precedence than the current operator.
/// d. An operand: we simply append it to RPN string.
/// III. When the infix expression is finished, we start popping off the stack and
/// appending to RPN string till stack becomes empty.
///
///
/// <param name="szExpr" />
///
public ArrayList GetPostFixNotation( string szExpr, Type varType, bool bFormula )
{
Stack stkOp = new Stack();
ArrayList arrFinalExpr = new ArrayList();
string szResult = "";
Tokenizer tknzr = null;
switch(varType.ToString())
{
case "System.Int32":
case "System.Int64":
tknzr = new Tokenizer( szExpr,ExpressionType.ET_ARITHMETIC|
ExpressionType.ET_COMPARISON|
ExpressionType.ET_LOGICAL );
break;
case "System.String":
tknzr = new Tokenizer( szExpr, ExpressionType.ET_COMPARISON);
break;
}
foreach(Token token in tknzr)
{
string szToken = token.Value.Trim();
if( szToken.Length == 0 )
continue;
switch(varType.ToString())
{
case "System.Int32":
case "System.Int64":
if( !OperatorHelper.IsOperator(szToken) )
{
Operand oprnd = OperandHelper.CreateOperand( szToken, varType );
oprnd.ExtractAndSetValue( szToken, bFormula );
arrFinalExpr.Add( oprnd );
szResult += szToken;
continue;
}
break;
case "System.String":
if( !OperatorHelper.IsComparisonOperator(szToken) )
{
Operand oprnd = OperandHelper.CreateOperand( szToken, varType );
oprnd.ExtractAndSetValue( szToken, bFormula );
arrFinalExpr.Add( oprnd );
szResult += szToken;
continue;
}
break;
}
string szOp = szToken;
if( szOp == "(" )
{
stkOp.Push( szOp );
}
else if( szOp == ")" )
{
string szTop;
while( (szTop = (string)stkOp.Pop()) != "(")
{
IOperator oprtr = OperatorHelper.CreateOperator( szTop );
arrFinalExpr.Add( oprtr );
szResult += szTop;
if( stkOp.Count == 0 )
throw new RPN_Exception( "Unmatched braces!" );
}
}
else
{
if( stkOp.Count == 0 || (string)stkOp.Peek() == "("
|| OperatorHelper.IsHigherPrecOperator( szOp, (string)stkOp.Peek()) )
{
stkOp.Push( szOp );
}
else
{
while( stkOp.Count != 0 )
{
if( OperatorHelper.IsLowerPrecOperator( szOp, (string)stkOp.Peek())
|| OperatorHelper.IsEqualPrecOperator( szOp, (string)stkOp.Peek()) )
{
string szTop = (string)stkOp.Peek();
if( szTop == "(" )
break;
szTop = (string)stkOp.Pop();
IOperator oprtr = OperatorHelper.CreateOperator( szTop );
arrFinalExpr.Add( oprtr );
szResult += szTop;
}
else
break;
}
stkOp.Push( szOp );
}
}
}
while( stkOp.Count != 0 )
{
string szTop = (string)stkOp.Pop();
if( szTop == "(" )
throw new RPN_Exception("Unmatched braces");
IOperator oprtr = OperatorHelper.CreateOperator( szTop );
arrFinalExpr.Add( oprtr );
szResult += szTop;
}
return arrFinalExpr;
}
#endregion
public string Convert2String( ArrayList arrExpr )
{
string szResult = "";
foreach( object obj in arrExpr )
{
szResult += obj.ToString();
}
return szResult;
}
#region RPN_Evaluator
///
/// Algo of EvaluateRPN (source : Expression Evaluator : using RPN by lallous
/// in the C++/MFC section of www.CodeProject.com.
/// 1. Initialize stack for storing results, prepare input postfix (or RPN) expression.
/// 2. Start scanning from left to right till we reach end of RPN expression
/// 3. Get token, if token is:
/// I. An operator:
/// a. Get top of stack and store into variable op2; Pop the stack
/// b. Get top of stack and store into variable op1; Pop the stack
/// c. Do the operation expression in operator on both op1 and op2
/// d. Push the result into the stack
/// II. An operand: stack its numerical representation into our numerical stack.
/// 4. At the end of the RPN expression, the stack should only have one value and
/// that should be the result and can be retrieved from the top of the stack.
///
/// <param name="szExpr" />Expression to be evaluated in RPNotation with
/// single character variables
/// <param name="htValues" />Values for each of the variables in the expression
///
public object EvaluateRPN( ArrayList arrExpr, Type varType, Hashtable htValues )
{
// initialize stack (integer stack) for results
Stack stPad = new Stack();
// begin loop : scan from left to right till end of RPN expression
foreach( object var in arrExpr )
{
Operand op1 = null;
Operand op2 = null;
IOperator oprtr = null;
// Get token
// if token is
if( var is IOperand )
{
// Operand : push onto top of numerical stack
stPad.Push( var );
}
else if( var is IOperator )
{
// Operator :
// Pop top of stack into var 1 - op2 first as top of stack is rhs
op2 = (Operand)stPad.Pop();
if( htValues != null )
{
op2.Value = htValues[op2.Name];
}
// Pop top of stack into var 2
op1 = (Operand)stPad.Pop();
if( htValues != null )
{
op1.Value = htValues[op1.Name];
}
// Do operation exp for 'this' operator on var1 and var2
oprtr = (IOperator)var;
IOperand opRes = oprtr.Eval( op1, op2 );
// Push results onto stack
stPad.Push( opRes );
}
}
// end loop
// stack ends up with single value with final result
return ((Operand)stPad.Pop()).Value;
}
#endregion
}
#endregion
#region UtilClasses
///
/// The given expression can be parsed as either Arithmetic or Logical or
/// Comparison ExpressionTypes. This is controlled by the enums
/// ExpressionType::ET_ARITHMETIC, ExpressionType::ET_COMPARISON and
/// ExpressionType::ET_LOGICAL. A combination of these enum types can also be given.
/// E.g. To parse the expression as all of these, pass
/// ExpressionType.ET_ARITHMETIC|ExpressionType.ET_COMPARISON|ExpressionType.ET_LOGICAL
/// to the Tokenizer c'tor.
///
[Flags]
public enum ExpressionType
{
ET_ARITHMETIC = 0x0001,
ET_COMPARISON = 0x0002,
ET_LOGICAL = 0x0004
}
///
/// Currently not used.
///
public enum TokenType
{
TT_OPERATOR,
TT_OPERAND
}
///
/// Represents each token in the expression
///
public class Token
{
public Token( string szValue )
{
m_szValue = szValue;
}
public string Value
{
get
{
return m_szValue;
}
}
string m_szValue;
}
///
/// Is the tokenizer which does the actual parsing of the expression.
///
public class Tokenizer : IEnumerable
{
public Tokenizer( string szExpression ):this(szExpression, ExpressionType.ET_ARITHMETIC|
ExpressionType.ET_COMPARISON|
ExpressionType.ET_LOGICAL)
{
}
public Tokenizer( string szExpression, ExpressionType exType )
{
m_szExpression = szExpression;
m_exType = exType;
m_RegEx = new Regex(OperatorHelper.GetOperatorsRegEx( m_exType ));
m_strarrTokens = SplitExpression( szExpression );
}
public IEnumerator GetEnumerator()
{
return new TokenEnumerator( m_strarrTokens );
}
public string[] SplitExpression( string szExpression )
{
return m_RegEx.Split( szExpression );
}
ExpressionType m_exType;
string m_szExpression;
string[] m_strarrTokens;
Regex m_RegEx;
}
///
/// Enumerator to enumerate over the tokens.
///
public class TokenEnumerator : IEnumerator
{
Token m_Token;
int m_nIdx;
string[] m_strarrTokens;
public TokenEnumerator( string[] strarrTokens )
{
m_strarrTokens = strarrTokens;
Reset();
}
public object Current
{
get
{
return m_Token;
}
}
public bool MoveNext()
{
if( m_nIdx >= m_strarrTokens.Length )
return false;
m_Token = new Token( m_strarrTokens[m_nIdx]);
m_nIdx++;
return true;
}
public void Reset()
{
m_nIdx = 0;
}
}
#region Exceptions
///
/// For the exceptions thrown by this module.
///
public class RPN_Exception : ApplicationException
{
public RPN_Exception()
{
}
public RPN_Exception( string szMessage):base( szMessage)
{
}
public RPN_Exception( string szMessage, Exception innerException ):base( szMessage, innerException)
{
}
}
#endregion
#endregion
#region Interfaces
public interface IOperand{}
public interface IOperator
{
IOperand Eval( IOperand lhs, IOperand rhs );
}
public interface IArithmeticOperations
{
// to support {"+", "-", "*", "/", "%"} operators
IOperand Plus( IOperand rhs);
IOperand Minus( IOperand rhs);
IOperand Multiply( IOperand rhs);
IOperand Divide( IOperand rhs);
IOperand Modulo( IOperand rhs);
}
public interface IComparisonOperations
{
// to support {"==", "!=","<", "<=", ">", ">="} operators
IOperand EqualTo( IOperand rhs);
IOperand NotEqualTo( IOperand rhs);
IOperand LessThan( IOperand rhs);
IOperand LessThanOrEqualTo( IOperand rhs);
IOperand GreaterThan( IOperand rhs);
IOperand GreaterThanOrEqualTo( IOperand rhs);
}
public interface ILogicalOperations
{
// to support {"||", "&&" } operators
IOperand OR( IOperand rhs);
IOperand AND( IOperand rhs);
}
#endregion
#region Operands
///
/// Base class for all Operands. Provides datastorage
///
public abstract class Operand : IOperand
{
public Operand( string szVarName, object varValue )
{
m_szVarName = szVarName;
m_VarValue = varValue;
}
public Operand( string szVarName )
{
m_szVarName = szVarName;
}
public override string ToString()
{
return m_szVarName;
}
public abstract void ExtractAndSetValue( string szValue, bool bFormula );
public string Name
{
get
{
return m_szVarName;
}
set
{
m_szVarName = value;
}
}
public object Value
{
get
{
return m_VarValue;
}
set
{
m_VarValue = value;
}
}
protected string m_szVarName = "";
protected object m_VarValue = null;
}
///
/// Operand corresponding to the Long (Int32/Int64) datatypes.
///
public class LongOperand : Operand, IArithmeticOperations, IComparisonOperations
{
public LongOperand( string szVarName, object varValue ):base(szVarName, varValue)
{
}
public LongOperand( string szVarName ):base( szVarName )
{
}
public override string ToString()
{
return m_szVarName;
}
public override void ExtractAndSetValue( string szValue, bool bFormula )
{
m_VarValue = !bFormula ?Convert.ToInt64(szValue) ;
}
/// IArithmeticOperations methods. Return of these methods is again a LongOperand
public IOperand Plus( IOperand rhs )
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.Plus : rhs" );
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );
oprResult.Value = (long)this.Value + (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Minus( IOperand rhs )
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.Minus : rhs" );
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );
oprResult.Value = (long)this.Value - (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Multiply( IOperand rhs )
{
if( !(rhs is LongOperand) )
throw new ArgumentException("Argument invalid in LongOperand.Multiply : rhs" );
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );
oprResult.Value = (long)this.Value * (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Divide( IOperand rhs )
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.Divide : rhs" );
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );
oprResult.Value = (long)this.Value / (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand Modulo( IOperand rhs )
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.Modulo : rhs" );
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );
oprResult.Value = (long)this.Value % (long)((Operand)rhs).Value;
return oprResult;
}
/// IComparisonOperators methods. Return values are always BooleanOperands type
public IOperand EqualTo( IOperand rhs)
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.== : rhs" );
BoolOperand oprResult = new BoolOperand("Result" );
oprResult.Value = (long)this.Value == (long)((Operand)rhs).Value;
return oprResult;
}
public IOperand NotEqualTo( IOperand rhs)
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.!= : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value != (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand LessThan( IOperand rhs)
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.< : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value < (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand LessThanOrEqualTo( IOperand rhs)
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.<= : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value <= (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand GreaterThan( IOperand rhs)
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.> : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value > (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand GreaterThanOrEqualTo( IOperand rhs)
{
if( !(rhs is LongOperand) )
throw new RPN_Exception("Argument invalid in LongOperand.>= : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((long)this.Value >= (long)((Operand)rhs).Value) ? true : false;
return oprResult;
}
}
///
/// Operand corresponding to Boolean Type
///
public class BoolOperand : Operand, ILogicalOperations
{
public BoolOperand( string szVarName, object varValue ):base(szVarName, varValue)
{
}
public BoolOperand( string szVarName ):base( szVarName )
{
}
public override string ToString()
{
return this.Value.ToString();
}
public override void ExtractAndSetValue( string szValue, bool bFormula )
{
m_VarValue = !bFormula ?Convert.ToBoolean(szValue):false;
}
public IOperand AND( IOperand rhs)
{
if( !(rhs is BoolOperand) )
throw new RPN_Exception("Argument invalid in BoolOperand.&& : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((bool)this.Value && (bool)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand OR( IOperand rhs)
{
if( !(rhs is BoolOperand) )
throw new RPN_Exception("Argument invalid in BoolOperand.|| : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((bool)this.Value || (bool)((Operand)rhs).Value) ? true : false;
return oprResult;
}
}
public class OperandHelper
{
///
/// Factory method to create corresponding Operands.
/// Extended this method to create newer datatypes.
///
/// <param name="szVarName" />
/// <param name="varType" />
/// <param name="varValue" />
/// <returns>
static public Operand CreateOperand( string szVarName, Type varType, object varValue )
{
Operand oprResult = null;
switch( varType.ToString() )
{
case "System.Int32":
case "System.Int64":
oprResult = new LongOperand( szVarName, varValue );
return oprResult;
//break;
//case System.Decimal:
//case System.Single:
// oprResult = new DecimalOperand( szVarName, varValue );
// return oprResult;
// break;
case "System.String":
oprResult = new StringOperand( szVarName, varValue );
return oprResult;
//break;
}
throw new RPN_Exception("Unhandled type : " + varType.ToString());
}
static public Operand CreateOperand( string szVarName, Type varType )
{
return OperandHelper.CreateOperand( szVarName, varType, null);
}
}
public class StringOperand : Operand, IComparisonOperations{
public StringOperand( string szVarName, object varValue ):base(szVarName, varValue)
{
}
public StringOperand( string szVarName ):base( szVarName )
{
}
public override string ToString()
{
return m_szVarName;
}
public override void ExtractAndSetValue( string szValue, bool bFormula )
{
m_VarValue = !bFormula ?Convert.ToString(szValue):"";
}
/// IComparisonOperators methods. Return values are always BooleanOperands type
public IOperand EqualTo( IOperand rhs)
{
if( !(rhs is StringOperand) )
throw new RPN_Exception("Argument invalid in StringOperand.== : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = (string)this.Value == (string)((Operand)rhs).Value;
return oprResult;
}
public IOperand NotEqualTo( IOperand rhs)
{
if( !(rhs is StringOperand) )
throw new RPN_Exception("Argument invalid in StringOperand.!= : rhs" );
BoolOperand oprResult = new BoolOperand("Result");
oprResult.Value = ((string)this.Value != (string)((Operand)rhs).Value) ? true : false;
return oprResult;
}
public IOperand LessThan( IOperand rhs)
{
// if( !(rhs is StringOperand) )
throw new RPN_Exception("LessThan operator is invalid for string" );
// BoolOperand oprResult = new BoolOperand("Result");
// oprResult.Value = ((string)this.Value < (string)((Operand)rhs).Value) ? true : false;
// return oprResult;
}
public IOperand LessThanOrEqualTo( IOperand rhs)
{
// if( !(rhs is StringOperand) )
throw new RPN_Exception("LessThanOrEqualTo operator is invalid for string" );
// BoolOperand oprResult = new BoolOperand("Result");
// oprResult.Value = ((string)this.Value <= (string)((Operand)rhs).Value) ? true : false;
// return oprResult;
}
public IOperand GreaterThan( IOperand rhs)
{
// if( !(rhs is StringOperand) )
throw new RPN_Exception("GreaterThan operator is invalid for string" );
// BoolOperand oprResult = new BoolOperand("Result");
// oprResult.Value = ((string)this.Value > (string)((Operand)rhs).Value) ? true : false;
// return oprResult;
}
public IOperand GreaterThanOrEqualTo( IOperand rhs)
{
// if( !(rhs is StringOperand) )
throw new RPN_Exception("GreaterThanOrEqualTo operator is invalid for string" );
// BoolOperand oprResult = new BoolOperand("Result");
// oprResult.Value = ((string)this.Value >= (string)((Operand)rhs).Value) ? true : false;
// return oprResult;
}
}
#endregion
#region Operators
///
/// Base class of all operators. Provides datastorage
///
public abstract class Operator : IOperator
{
public Operator( char cOperator )
{
m_szOperator = new String(cOperator, 1);
}
public Operator( string szOperator )
{
m_szOperator = szOperator;
}
public override string ToString()
{
return m_szOperator;
}
public abstract IOperand Eval( IOperand lhs, IOperand rhs );
public string Value
{
get
{
return m_szOperator;
}
set
{
m_szOperator = value;
}
}
protected string m_szOperator = "";
}
///
/// Arithmetic Operator Class providing evaluation services for "+-/*%" operators.
///
public class ArithmeticOperator : Operator
{
public ArithmeticOperator( char cOperator ):base( cOperator )
{
}
public ArithmeticOperator( string szOperator ):base( szOperator )
{
}
//bool bBinaryOperator = true;
public override IOperand Eval( IOperand lhs, IOperand rhs )
{
if( !(lhs is IArithmeticOperations) )
throw new RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs" );
switch( m_szOperator )
{
case "+":
return ((IArithmeticOperations)lhs).Plus( rhs );
case "-":
return ((IArithmeticOperations)lhs).Minus( rhs );
case "*":
return ((IArithmeticOperations)lhs).Multiply( rhs );
case "/":
return ((IArithmeticOperations)lhs).Divide( rhs );
case "%":
return ((IArithmeticOperations)lhs).Modulo( rhs );
}
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator );
}
}
///
/// Comparison Operator Class providing evaluation services for "==", "!=","<", "<=", ">", ">=" operators.
///
public class ComparisonOperator : Operator
{
public ComparisonOperator( char cOperator ):base( cOperator )
{
}
public ComparisonOperator( string szOperator ):base( szOperator )
{
}
//bool bBinaryOperator = true;
//{"==", "!=","<", "<=", ">", ">="}
public override IOperand Eval( IOperand lhs, IOperand rhs )
{
if( !(lhs is IComparisonOperations) )
throw new RPN_Exception("Argument invalid in ComparisonOperator.Eval - Invalid Expression : lhs" );
switch( m_szOperator )
{
case "==":
return ((IComparisonOperations)lhs).EqualTo( rhs );
case "!=":
return ((IComparisonOperations)lhs).NotEqualTo( rhs );
case "<":
return ((IComparisonOperations)lhs).LessThan( rhs );
case "<=":
return ((IComparisonOperations)lhs).LessThanOrEqualTo( rhs );
case ">":
return ((IComparisonOperations)lhs).GreaterThan( rhs );
case ">=":
return ((IComparisonOperations)lhs).GreaterThanOrEqualTo( rhs );
}
throw new RPN_Exception("Unsupported Comparison operation " + m_szOperator );
}
}
///
/// Logical Operator Class providing evaluation services for && and || operators.
///
public class LogicalOperator : Operator
{
public LogicalOperator( char cOperator ):base( cOperator )
{
}
public LogicalOperator( string szOperator ):base( szOperator )
{
}
//bool bBinaryOperator = true;
//{"&&", "||"}
public override IOperand Eval( IOperand lhs, IOperand rhs )
{
if( !(lhs is ILogicalOperations) )
throw new RPN_Exception("Argument invalid in LogicalOperator.Eval - Invalid Expression : lhs" );
switch( m_szOperator )
{
case "&&":
return ((ILogicalOperations)lhs).AND( rhs );
case "||":
return ((ILogicalOperations)lhs).OR( rhs );
}
throw new RPN_Exception("Unsupported Logical operation " + m_szOperator );
}
}
public class OperatorHelper
{
///
/// Factory method to create Operator objects.
///
/// <param name="szOperator" />
/// <returns>
static public IOperator CreateOperator( string szOperator )
{
IOperator oprtr = null;
if( OperatorHelper.IsArithmeticOperator( szOperator ) )
{
oprtr = new ArithmeticOperator( szOperator );
return oprtr;
}
if( OperatorHelper.IsComparisonOperator( szOperator ) )
{
oprtr = new ComparisonOperator( szOperator );
return oprtr;
}
if( OperatorHelper.IsLogicalOperator( szOperator ) )
{
oprtr = new LogicalOperator( szOperator );
return oprtr;
}
throw new RPN_Exception("Unhandled Operator : " + szOperator );
}
static public IOperator CreateOperator( char cOperator )
{
return CreateOperator( new string( cOperator, 1 ) );
}
/// Some helper functions.
public static bool IsOperator( string currentOp )
{
int nPos = Array.IndexOf( m_AllOps, currentOp.Trim() );
if( nPos != -1 )
return true;
else
return false;
}
public static bool IsArithmeticOperator( string currentOp )
{
int nPos = Array.IndexOf( m_AllArithmeticOps, currentOp );
if( nPos != -1 )
return true;
else
return false;
}
public static bool IsComparisonOperator( string currentOp )
{
int nPos = Array.IndexOf( m_AllComparisonOps, currentOp );
if( nPos != -1 )
return true;
else
return false;
}
public static bool IsLogicalOperator( string currentOp )
{
int nPos = Array.IndexOf( m_AllLogicalOps, currentOp );
if( nPos != -1 )
return true;
else
return false;
}
#region Precedence
/// Precedence is determined by relative indices of the operators defined in
/// in m_AllOps variable
///
/// Summary of IsLowerPrecOperator.
///
/// <param name="allOps" />
/// <param name="currentOp" />
/// <param name="prevOp" />
///
public static bool IsLowerPrecOperator( string currentOp, string prevOp )
{
int nCurrIdx;
int nPrevIdx;
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );
if( nCurrIdx < nPrevIdx )
{
return true;
}
return false;
}
///
/// Summary of IsHigherPrecOperator.
///
/// <param name="allOps" />
/// <param name="currentOp" />
/// <param name="prevOp" />
///
public static bool IsHigherPrecOperator( string currentOp, string prevOp )
{
int nCurrIdx;
int nPrevIdx;
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );
if( nCurrIdx > nPrevIdx )
{
return true;
}
return false;
}
///
/// Summary of IsEqualPrecOperator.
///
/// <param name="allOps" />
/// <param name="currentOp" />
/// <param name="prevOp" />
///
public static bool IsEqualPrecOperator( string currentOp, string prevOp )
{
int nCurrIdx;
int nPrevIdx;
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );
if( nCurrIdx == nPrevIdx )
{
return true;
}
return false;
}
///
/// Summary of GetCurrentAndPreviousIndex.
///
/// <param name="allOps" />
/// <param name="currentOp" />
/// <param name="prevOp" />
/// <param name="nCurrIdx" />
/// <param name="nPrevIdx" />
///
private static void GetCurrentAndPreviousIndex( string[] allOps, string currentOp, string prevOp,
out int nCurrIdx, out int nPrevIdx )
{
nCurrIdx = -1;
nPrevIdx = -1;
for( int nIdx = 0; nIdx < allOps.Length; nIdx++ )
{
if( allOps[nIdx] == currentOp )
{
nCurrIdx = nIdx;
}
if( allOps[nIdx] == prevOp )
{
nPrevIdx = nIdx;
}
if( nPrevIdx != -1 && nCurrIdx != -1 )
{
break;
}
}
if( nCurrIdx == -1 )
{
throw new RPN_Exception("Unknown operator - " + currentOp );
}
if( nPrevIdx == -1 )
{
throw new RPN_Exception("Unknown operator - " + prevOp );
}
}
#endregion
#region RegEx
///
/// This gets the regular expression used to find operators in the input
/// expression.
///
/// <param name="exType" />
/// <returns>
static public string GetOperatorsRegEx( ExpressionType exType )
{
StringBuilder strRegex = new StringBuilder();
if( (exType & ExpressionType.ET_ARITHMETIC).Equals(ExpressionType.ET_ARITHMETIC) )
{
if( strRegex.Length == 0 )
{
strRegex.Append( m_szArthmtcRegEx );
}
else
{
strRegex.Append( "|" + m_szArthmtcRegEx );
}
}
if( (exType & ExpressionType.ET_COMPARISON).Equals(ExpressionType.ET_COMPARISON) )
{
if( strRegex.Length == 0 )
{
strRegex.Append( m_szCmprsnRegEx );
}
else
{
strRegex.Append( "|" + m_szCmprsnRegEx );
}
}
if( (exType & ExpressionType.ET_LOGICAL).Equals(ExpressionType.ET_LOGICAL) )
{
if( strRegex.Length == 0 )
{
strRegex.Append( m_szLgclRegEx );
}
else
{
strRegex.Append( "|" + m_szLgclRegEx );
}
}
if( strRegex.Length == 0 )
throw new RPN_Exception("Invalid combination of ExpressionType value");
return "(" + strRegex.ToString() + ")";
}
///
/// Expression to pattern match various operators
///
static string m_szArthmtcRegEx = @"[+\-*/%()]{1}";
static string m_szCmprsnRegEx = @"[=<>!]{1,2}";
static string m_szLgclRegEx = @"[&|]{2}";
#endregion
public static string[] AllOperators
{
get
{
return m_AllOps;
}
}
///
/// All Operators supported by this module currently.
/// Modify here to add more operators IN ACCORDANCE WITH their precedence.
/// Additionally add into individual variables to support some helper methods above.
///
static string[] m_AllOps = { "||", "&&", "|", "^", "&", "==", "!=",
"<", "<=", ">", ">=", "+", "-", "*", "/", "%", "(", ")" };
static string[] m_AllArithmeticOps = { "+", "-", "*", "/", "%" };
static string[] m_AllComparisonOps = { "==", "!=","<", "<=", ">", ">=" };
static string[] m_AllLogicalOps = { "&&", "||" };
}
#endregion
#region TODO List
/// TODO: Support for unary operators
/// TODO: Support for bitwise & and |
/// TODO: how to handle a combo expression with multiple braces as a logical/comparison expression?
/// e.g. ((2+3)*2<10 || 1!=1) && 2*2==4 as a logical expression?
/// TODO: Form to accept values for formulae
#endregion
// Function to test for Positive Integers.
#region Content check
public class StringContentCheck
{
static public bool IsNaturalNumber(String strNumber)
{
Regex objNotNaturalPattern=new Regex("[^0-9]");
Regex objNaturalPattern=new Regex("0*[1-9][0-9]*");
return !objNotNaturalPattern.IsMatch(strNumber) &&
objNaturalPattern.IsMatch(strNumber);
}
// Function to test for Positive Integers with zero inclusive
static public bool IsWholeNumber(String strNumber)
{
Regex objNotWholePattern=new Regex("[^0-9]");
return !objNotWholePattern.IsMatch(strNumber);
}
// Function to Test for Integers both Positive & Negative
static public bool IsInteger(String strNumber)
{
Regex objNotIntPattern=new Regex("[^0-9-]");
Regex objIntPattern=new Regex("^-[0-9]+$|^[0-9]+$");
return !objNotIntPattern.IsMatch(strNumber) && objIntPattern.IsMatch(strNumber);
}
// Function to Test for Positive Number both Integer & Real
static public bool IsPositiveNumber(String strNumber)
{
Regex objNotPositivePattern=new Regex("[^0-9.]");
Regex objPositivePattern=new Regex("^[.][0-9]+$|[0-9]*[.]*[0-9]+$");
Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");
return !objNotPositivePattern.IsMatch(strNumber) &&
objPositivePattern.IsMatch(strNumber) &&
!objTwoDotPattern.IsMatch(strNumber);
}
// Function to test whether the string is valid number or not
static public bool IsNumber(String strNumber)
{
Regex objNotNumberPattern=new Regex("[^0-9.-]");
Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");
Regex objTwoMinusPattern=new Regex("[0-9]*[-][0-9]*[-][0-9]*");
String strValidRealPattern="^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$";
String strValidIntegerPattern="^([-]|[0-9])[0-9]*$";
Regex objNumberPattern =new Regex("(" + strValidRealPattern +")|(" + strValidIntegerPattern + ")");
return !objNotNumberPattern.IsMatch(strNumber) &&
!objTwoDotPattern.IsMatch(strNumber) &&
!objTwoMinusPattern.IsMatch(strNumber) &&
objNumberPattern.IsMatch(strNumber);
}
// Function To test for Alphabets.
static public bool IsAlpha(String strToCheck)
{
Regex objAlphaPattern=new Regex("[^a-zA-Z ]");
return !objAlphaPattern.IsMatch(strToCheck);
}
// Function to Check for AlphaNumeric.
static public bool IsAlphaNumeric(String strToCheck)
{
Regex objAlphaNumericPattern=new Regex("[^a-zA-Z0-9 ]");
return !objAlphaNumericPattern.IsMatch(strToCheck);
}
}
#endregion
}
|
|
|
|
|
Thanks for to update the code with your modification.
It was really helpfull for me...
|
|
|
|
|
Hi all,
I had some difficulties with the code above. I could mix long comparation with string comparation.
Working Example :
RPNParser parser = new RPNParser();<br />
parser.EvaluateExpression(@"(""aaa""==""bbb"" && 1 == 1) ||(""aa""==""aa"")"
Here is the modified code :
using System;<br />
using System.Collections;<br />
using System.Text;<br />
using System.Text.RegularExpressions;<br />
<br />
namespace cfring.util<br />
{<br />
#region RPN<br />
public class RPNParser<br />
{<br />
public RPNParser()<br />
{<br />
}<br />
public object EvaluateExpression( string szExpr, Type varType, bool bFormula, Hashtable htValues )<br />
{<br />
ArrayList arrExpr = GetPostFixNotation( szExpr, varType, bFormula );<br />
return EvaluateRPN(arrExpr, varType, htValues );<br />
}<br />
<br />
public object EvaluateExpression( string szExpr )<br />
{<br />
long myType = 0;<br />
ArrayList arrExpr = GetPostFixNotation( szExpr, myType.GetType(),false);<br />
return EvaluateRPN(arrExpr, myType.GetType(), null );<br />
}<br />
<br />
#region RPN_Parser<br />
public ArrayList GetPostFixNotation( string szExpr, Type varType, bool bFormula )<br />
{<br />
Stack stkOp = new Stack();<br />
ArrayList arrFinalExpr = new ArrayList();<br />
string szResult = "";<br />
<br />
Tokenizer tknzr = null;<br />
switch(varType.ToString())<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
tknzr = new Tokenizer( szExpr,ExpressionType.ET_ARITHMETIC|<br />
ExpressionType.ET_COMPARISON|<br />
ExpressionType.ET_LOGICAL );<br />
break;<br />
case "System.String":<br />
tknzr = new Tokenizer( szExpr, ExpressionType.ET_COMPARISON);<br />
break;<br />
}<br />
<br />
<br />
<br />
foreach(Token token in tknzr)<br />
{<br />
string szToken = token.Value.Trim();<br />
if( szToken.Length == 0 )<br />
continue;<br />
switch(varType.ToString())<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
if( !OperatorHelper.IsOperator(szToken) )<br />
{<br />
Operand oprnd;<br />
if (szToken.IndexOf("\"") != -1)<br />
{<br />
string myStringType = "";<br />
oprnd = OperandHelper.CreateOperand( szToken, myStringType.GetType() );<br />
}<br />
else oprnd = OperandHelper.CreateOperand( szToken, varType );<br />
oprnd.ExtractAndSetValue( szToken, bFormula );<br />
arrFinalExpr.Add( oprnd );<br />
<br />
szResult += szToken;<br />
continue;<br />
}<br />
break;<br />
case "System.String":<br />
if( !OperatorHelper.IsComparisonOperator(szToken) )<br />
{<br />
Operand oprnd = OperandHelper.CreateOperand( szToken, varType );<br />
oprnd.ExtractAndSetValue( szToken, bFormula );<br />
arrFinalExpr.Add( oprnd );<br />
<br />
szResult += szToken;<br />
continue;<br />
}<br />
<br />
break;<br />
}<br />
<br />
string szOp = szToken;<br />
if( szOp == "(" )<br />
{<br />
stkOp.Push( szOp );<br />
}<br />
else if( szOp == ")" )<br />
{<br />
string szTop;<br />
while( (szTop = (string)stkOp.Pop()) != "(")<br />
{<br />
IOperator oprtr = OperatorHelper.CreateOperator( szTop );<br />
arrFinalExpr.Add( oprtr );<br />
<br />
szResult += szTop;<br />
<br />
if( stkOp.Count == 0 )<br />
throw new RPN_Exception( "Unmatched braces!" );<br />
}<br />
}<br />
else<br />
{<br />
if( stkOp.Count == 0 || (string)stkOp.Peek() == "("<br />
|| OperatorHelper.IsHigherPrecOperator( szOp, (string)stkOp.Peek()) )<br />
{<br />
stkOp.Push( szOp );<br />
}<br />
else<br />
{<br />
while( stkOp.Count != 0 )<br />
{<br />
if( OperatorHelper.IsLowerPrecOperator( szOp, (string)stkOp.Peek())<br />
|| OperatorHelper.IsEqualPrecOperator( szOp, (string)stkOp.Peek()) )<br />
{<br />
string szTop = (string)stkOp.Peek();<br />
if( szTop == "(" )<br />
break;<br />
szTop = (string)stkOp.Pop();<br />
<br />
IOperator oprtr = OperatorHelper.CreateOperator( szTop );<br />
arrFinalExpr.Add( oprtr );<br />
<br />
szResult += szTop;<br />
}<br />
else<br />
break;<br />
}<br />
stkOp.Push( szOp );<br />
}<br />
}<br />
}<br />
while( stkOp.Count != 0 )<br />
{<br />
string szTop = (string)stkOp.Pop();<br />
if( szTop == "(" )<br />
throw new RPN_Exception("Unmatched braces");<br />
<br />
IOperator oprtr = OperatorHelper.CreateOperator( szTop );<br />
arrFinalExpr.Add( oprtr );<br />
<br />
szResult += szTop;<br />
}<br />
return arrFinalExpr;<br />
}<br />
<br />
#endregion<br />
<br />
public string Convert2String( ArrayList arrExpr )<br />
{<br />
string szResult = "";<br />
foreach( object obj in arrExpr )<br />
{<br />
szResult += obj.ToString();<br />
}<br />
return szResult;<br />
}<br />
<br />
<br />
#region RPN_Evaluator<br />
<br />
public object EvaluateRPN( ArrayList arrExpr, Type varType, Hashtable htValues )<br />
{<br />
Stack stPad = new Stack();<br />
foreach( object var in arrExpr )<br />
{<br />
Operand op1 = null;<br />
Operand op2 = null;<br />
IOperator oprtr = null;<br />
if( var is IOperand )<br />
{<br />
stPad.Push( var );<br />
}<br />
else if( var is IOperator )<br />
{<br />
op2 = (Operand)stPad.Pop();<br />
if( htValues != null )<br />
{<br />
op2.Value = htValues[op2.Name];<br />
}<br />
op1 = (Operand)stPad.Pop();<br />
if( htValues != null )<br />
{<br />
op1.Value = htValues[op1.Name];<br />
}<br />
oprtr = (IOperator)var;<br />
IOperand opRes = oprtr.Eval( op1, op2 );<br />
stPad.Push( opRes );<br />
}<br />
}<br />
return ((Operand)stPad.Pop()).Value;<br />
}<br />
#endregion<br />
}<br />
#endregion<br />
<br />
#region UtilClasses<br />
<br />
[Flags]<br />
public enum ExpressionType<br />
{<br />
ET_ARITHMETIC = 0x0001,<br />
ET_COMPARISON = 0x0002,<br />
ET_LOGICAL = 0x0004<br />
}<br />
public enum TokenType<br />
{<br />
TT_OPERATOR,<br />
TT_OPERAND<br />
}<br />
public class Token<br />
{<br />
public Token( string szValue )<br />
{<br />
m_szValue = szValue;<br />
}<br />
public string Value<br />
{<br />
get<br />
{<br />
return m_szValue;<br />
}<br />
}<br />
string m_szValue;<br />
}<br />
public class Tokenizer : IEnumerable<br />
{<br />
public Tokenizer( string szExpression ):this(szExpression, ExpressionType.ET_ARITHMETIC|<br />
ExpressionType.ET_COMPARISON|<br />
ExpressionType.ET_LOGICAL)<br />
{<br />
}<br />
public Tokenizer( string szExpression, ExpressionType exType )<br />
{<br />
m_szExpression = szExpression;<br />
m_exType = exType;<br />
m_RegEx = new Regex(OperatorHelper.GetOperatorsRegEx( m_exType ));<br />
m_strarrTokens = SplitExpression( szExpression );<br />
}<br />
public IEnumerator GetEnumerator()<br />
{<br />
return new TokenEnumerator( m_strarrTokens );<br />
}<br />
public string[] SplitExpression( string szExpression )<br />
{<br />
return m_RegEx.Split( szExpression );<br />
}<br />
ExpressionType m_exType;<br />
string m_szExpression;<br />
string[] m_strarrTokens;<br />
Regex m_RegEx;<br />
}<br />
<br />
public class TokenEnumerator : IEnumerator<br />
{<br />
Token m_Token;<br />
int m_nIdx;<br />
string[] m_strarrTokens;<br />
<br />
public TokenEnumerator( string[] strarrTokens )<br />
{<br />
m_strarrTokens = strarrTokens;<br />
Reset();<br />
}<br />
public object Current<br />
{<br />
get<br />
{<br />
return m_Token;<br />
}<br />
}<br />
public bool MoveNext()<br />
{<br />
if( m_nIdx >= m_strarrTokens.Length )<br />
return false;<br />
<br />
m_Token = new Token( m_strarrTokens[m_nIdx]);<br />
m_nIdx++;<br />
return true;<br />
}<br />
public void Reset()<br />
{<br />
m_nIdx = 0;<br />
}<br />
}<br />
#region Exceptions<br />
public class RPN_Exception : ApplicationException<br />
{<br />
public RPN_Exception()<br />
{<br />
}<br />
public RPN_Exception( string szMessage):base( szMessage)<br />
{<br />
}<br />
public RPN_Exception( string szMessage, Exception innerException ):base( szMessage, innerException)<br />
{<br />
}<br />
}<br />
#endregion<br />
#endregion<br />
<br />
#region Interfaces<br />
public interface IOperand{}<br />
public interface IOperator<br />
{<br />
IOperand Eval( IOperand lhs, IOperand rhs );<br />
}<br />
<br />
public interface IArithmeticOperations<br />
{<br />
IOperand Plus( IOperand rhs);<br />
IOperand Minus( IOperand rhs);<br />
IOperand Multiply( IOperand rhs);<br />
IOperand Divide( IOperand rhs);<br />
IOperand Modulo( IOperand rhs);<br />
}<br />
public interface IComparisonOperations<br />
{<br />
IOperand EqualTo( IOperand rhs);<br />
IOperand NotEqualTo( IOperand rhs);<br />
IOperand LessThan( IOperand rhs);<br />
IOperand LessThanOrEqualTo( IOperand rhs);<br />
IOperand GreaterThan( IOperand rhs);<br />
IOperand GreaterThanOrEqualTo( IOperand rhs);<br />
}<br />
public interface ILogicalOperations<br />
{<br />
IOperand OR( IOperand rhs);<br />
IOperand AND( IOperand rhs);<br />
}<br />
#endregion<br />
<br />
#region Operands<br />
public abstract class Operand : IOperand<br />
{<br />
public Operand( string szVarName, object varValue )<br />
{<br />
m_szVarName = szVarName;<br />
m_VarValue = varValue;<br />
}<br />
public Operand( string szVarName )<br />
{<br />
m_szVarName = szVarName;<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public abstract void ExtractAndSetValue( string szValue, bool bFormula );<br />
public string Name<br />
{<br />
get<br />
{<br />
return m_szVarName;<br />
}<br />
set<br />
{<br />
m_szVarName = value;<br />
}<br />
}<br />
public object Value<br />
{<br />
get<br />
{<br />
return m_VarValue;<br />
}<br />
set<br />
{<br />
m_VarValue = value;<br />
}<br />
}<br />
protected string m_szVarName = "";<br />
protected object m_VarValue = null;<br />
}<br />
public class LongOperand : Operand, IArithmeticOperations, IComparisonOperations<br />
{<br />
public LongOperand( string szVarName, object varValue ):base(szVarName, varValue)<br />
{<br />
}<br />
public LongOperand( string szVarName ):base( szVarName )<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public override void ExtractAndSetValue( string szValue, bool bFormula )<br />
{<br />
m_VarValue = !bFormula ?Convert.ToInt64(szValue):0;<br />
}<br />
public IOperand Plus( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Plus : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value + (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Minus( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Minus : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value - (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Multiply( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new ArgumentException("Argument invalid in LongOperand.Multiply : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value * (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Divide( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Divide : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value / (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Modulo( IOperand rhs )<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.Modulo : rhs" );<br />
LongOperand oprResult = new LongOperand("Result", Type.GetType("System.Int64") );<br />
oprResult.Value = (long)this.Value % (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
<br />
public IOperand EqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.== : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result" );<br />
oprResult.Value = (long)this.Value == (long)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand NotEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.!= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value != (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThan( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.< : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value < (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThanOrEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.<= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value <= (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThan( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.> : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value > (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThanOrEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is LongOperand) )<br />
throw new RPN_Exception("Argument invalid in LongOperand.>= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((long)this.Value >= (long)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
}<br />
public class BoolOperand : Operand, ILogicalOperations<br />
{<br />
public BoolOperand( string szVarName, object varValue ):base(szVarName, varValue)<br />
{<br />
}<br />
public BoolOperand( string szVarName ):base( szVarName )<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return this.Value.ToString();<br />
}<br />
public override void ExtractAndSetValue( string szValue, bool bFormula )<br />
{<br />
m_VarValue = !bFormula ?Convert.ToBoolean(szValue):false;<br />
}<br />
public IOperand AND( IOperand rhs)<br />
{<br />
if( !(rhs is BoolOperand) )<br />
throw new RPN_Exception("Argument invalid in BoolOperand.&& : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((bool)this.Value && (bool)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand OR( IOperand rhs)<br />
{<br />
if( !(rhs is BoolOperand) )<br />
throw new RPN_Exception("Argument invalid in BoolOperand.|| : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((bool)this.Value || (bool)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
}<br />
<br />
public class OperandHelper<br />
{<br />
static public Operand CreateOperand( string szVarName, Type varType, object varValue )<br />
{<br />
Operand oprResult = null;<br />
switch( varType.ToString() )<br />
{<br />
case "System.Int32":<br />
case "System.Int64":<br />
oprResult = new LongOperand( szVarName, varValue );<br />
return oprResult;<br />
case "System.String":<br />
oprResult = new StringOperand( szVarName, varValue );<br />
return oprResult;<br />
<br />
<br />
<br />
<br />
}<br />
throw new RPN_Exception("Unhandled type : " + varType.ToString());<br />
}<br />
static public Operand CreateOperand( string szVarName, Type varType )<br />
{<br />
return OperandHelper.CreateOperand( szVarName, varType, null);<br />
}<br />
}<br />
public class StringOperand : Operand, IComparisonOperations<br />
{<br />
public StringOperand( string szVarName, object varValue ):base(szVarName, varValue)<br />
{<br />
}<br />
public StringOperand( string szVarName ):base( szVarName )<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public override void ExtractAndSetValue( string szValue, bool bFormula )<br />
{<br />
m_VarValue = !bFormula ?Convert.ToString(szValue):"";<br />
}<br />
public IOperand EqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is StringOperand) )<br />
throw new RPN_Exception("Argument invalid in StringOperand.== : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = (string)this.Value == (string)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand NotEqualTo( IOperand rhs)<br />
{<br />
if( !(rhs is StringOperand) )<br />
throw new RPN_Exception("Argument invalid in StringOperand.!= : rhs" );<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((string)this.Value != (string)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThan( IOperand rhs)<br />
{<br />
throw new RPN_Exception("LessThan operator is invalid for string" );<br />
}<br />
public IOperand LessThanOrEqualTo( IOperand rhs)<br />
{<br />
throw new RPN_Exception("LessThanOrEqualTo operator is invalid for string" );<br />
}<br />
public IOperand GreaterThan( IOperand rhs)<br />
{<br />
throw new RPN_Exception("GreaterThan operator is invalid for string" );<br />
}<br />
public IOperand GreaterThanOrEqualTo( IOperand rhs)<br />
{<br />
throw new RPN_Exception("GreaterThanOrEqualTo operator is invalid for string" );<br />
}<br />
}<br />
#endregion<br />
<br />
#region Operators<br />
public abstract class Operator : IOperator<br />
{<br />
public Operator( char cOperator )<br />
{<br />
m_szOperator = new String(cOperator, 1);<br />
}<br />
public Operator( string szOperator )<br />
{<br />
m_szOperator = szOperator;<br />
}<br />
public override string ToString()<br />
{<br />
return m_szOperator;<br />
}<br />
public abstract IOperand Eval( IOperand lhs, IOperand rhs );<br />
public string Value<br />
{<br />
get<br />
{<br />
return m_szOperator;<br />
}<br />
set<br />
{<br />
m_szOperator = value;<br />
}<br />
}<br />
protected string m_szOperator = "";<br />
}<br />
public class ArithmeticOperator : Operator<br />
{<br />
public ArithmeticOperator( char cOperator ):base( cOperator )<br />
{<br />
}<br />
public ArithmeticOperator( string szOperator ):base( szOperator )<br />
{<br />
}<br />
<br />
public override IOperand Eval( IOperand lhs, IOperand rhs )<br />
{<br />
if( !(lhs is IArithmeticOperations) )<br />
throw new RPN_Exception("Argument invalid in ArithmeticOperator.Eval - Invalid Expression : lhs" );<br />
switch( m_szOperator )<br />
{<br />
case "+":<br />
return ((IArithmeticOperations)lhs).Plus( rhs );<br />
case "-":<br />
return ((IArithmeticOperations)lhs).Minus( rhs );<br />
case "*":<br />
return ((IArithmeticOperations)lhs).Multiply( rhs );<br />
case "/":<br />
return ((IArithmeticOperations)lhs).Divide( rhs );<br />
case "%":<br />
return ((IArithmeticOperations)lhs).Modulo( rhs );<br />
}<br />
throw new RPN_Exception("Unsupported Arithmetic operation " + m_szOperator );<br />
}<br />
}<br />
public class ComparisonOperator : Operator<br />
{<br />
public ComparisonOperator( char cOperator ):base( cOperator )<br />
{<br />
}<br />
public ComparisonOperator( string szOperator ):base( szOperator )<br />
{<br />
}<br />
<br />
public override IOperand Eval( IOperand lhs, IOperand rhs )<br />
{<br />
if( !(lhs is IComparisonOperations) )<br />
throw new RPN_Exception("Argument invalid in ComparisonOperator.Eval - Invalid Expression : lhs" );<br />
switch( m_szOperator )<br />
{<br />
case "==":<br />
return ((IComparisonOperations)lhs).EqualTo( rhs );<br />
case "!=":<br />
return ((IComparisonOperations)lhs).NotEqualTo( rhs );<br />
case "<":<br />
return ((IComparisonOperations)lhs).LessThan( rhs );<br />
case "<=":<br />
return ((IComparisonOperations)lhs).LessThanOrEqualTo( rhs );<br />
case ">":<br />
return ((IComparisonOperations)lhs).GreaterThan( rhs );<br />
case ">=":<br />
return ((IComparisonOperations)lhs).GreaterThanOrEqualTo( rhs );<br />
}<br />
throw new RPN_Exception("Unsupported Comparison operation " + m_szOperator );<br />
}<br />
}<br />
<br />
public class LogicalOperator : Operator<br />
{<br />
public LogicalOperator( char cOperator ):base( cOperator )<br />
{<br />
}<br />
public LogicalOperator( string szOperator ):base( szOperator )<br />
{<br />
}<br />
<br />
public override IOperand Eval( IOperand lhs, IOperand rhs )<br />
{<br />
if( !(lhs is ILogicalOperations) )<br />
throw new RPN_Exception("Argument invalid in LogicalOperator.Eval - Invalid Expression : lhs" );<br />
switch( m_szOperator )<br />
{<br />
case "&&":<br />
return ((ILogicalOperations)lhs).AND( rhs );<br />
case "||":<br />
return ((ILogicalOperations)lhs).OR( rhs );<br />
}<br />
throw new RPN_Exception("Unsupported Logical operation " + m_szOperator );<br />
}<br />
}<br />
<br />
public class OperatorHelper<br />
{<br />
static public IOperator CreateOperator( string szOperator )<br />
{<br />
IOperator oprtr = null;<br />
if( OperatorHelper.IsArithmeticOperator( szOperator ) )<br />
{<br />
oprtr = new ArithmeticOperator( szOperator );<br />
return oprtr;<br />
}<br />
if( OperatorHelper.IsComparisonOperator( szOperator ) )<br />
{<br />
oprtr = new ComparisonOperator( szOperator );<br />
return oprtr;<br />
}<br />
if( OperatorHelper.IsLogicalOperator( szOperator ) )<br />
{<br />
oprtr = new LogicalOperator( szOperator );<br />
return oprtr;<br />
}<br />
throw new RPN_Exception("Unhandled Operator : " + szOperator );<br />
}<br />
static public IOperator CreateOperator( char cOperator )<br />
{<br />
return CreateOperator( new string( cOperator, 1 ) );<br />
}<br />
public static bool IsOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllOps, currentOp.Trim() );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsArithmeticOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllArithmeticOps, currentOp );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsComparisonOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllComparisonOps, currentOp );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
public static bool IsLogicalOperator( string currentOp )<br />
{<br />
int nPos = Array.IndexOf( m_AllLogicalOps, currentOp );<br />
if( nPos != -1 )<br />
return true;<br />
else<br />
return false;<br />
}<br />
#region Precedence<br />
<br />
public static bool IsLowerPrecOperator( string currentOp, string prevOp )<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );<br />
if( nCurrIdx < nPrevIdx )<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
<br />
public static bool IsHigherPrecOperator( string currentOp, string prevOp )<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );<br />
if( nCurrIdx > nPrevIdx )<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
<br />
public static bool IsEqualPrecOperator( string currentOp, string prevOp )<br />
{<br />
int nCurrIdx;<br />
int nPrevIdx;<br />
GetCurrentAndPreviousIndex( m_AllOps, currentOp, prevOp, out nCurrIdx, out nPrevIdx );<br />
if( nCurrIdx == nPrevIdx )<br />
{<br />
return true;<br />
}<br />
return false;<br />
}<br />
private static void GetCurrentAndPreviousIndex( string[] allOps, string currentOp, string prevOp,<br />
out int nCurrIdx, out int nPrevIdx )<br />
{<br />
nCurrIdx = -1;<br />
nPrevIdx = -1;<br />
for( int nIdx = 0; nIdx < allOps.Length; nIdx++ )<br />
{<br />
if( allOps[nIdx] == currentOp )<br />
{<br />
nCurrIdx = nIdx;<br />
}<br />
if( allOps[nIdx] == prevOp )<br />
{<br />
nPrevIdx = nIdx;<br />
}<br />
if( nPrevIdx != -1 && nCurrIdx != -1 )<br />
{<br />
break;<br />
}<br />
}<br />
if( nCurrIdx == -1 )<br />
{<br />
throw new RPN_Exception("Unknown operator - " + currentOp );<br />
}<br />
if( nPrevIdx == -1 )<br />
{<br />
throw new RPN_Exception("Unknown operator - " + prevOp );<br />
}<br />
<br />
}<br />
#endregion<br />
#region RegEx<br />
static public string GetOperatorsRegEx( ExpressionType exType )<br />
{<br />
StringBuilder strRegex = new StringBuilder();<br />
if( (exType & ExpressionType.ET_ARITHMETIC).Equals(ExpressionType.ET_ARITHMETIC) )<br />
{<br />
if( strRegex.Length == 0 )<br />
{<br />
strRegex.Append( m_szArthmtcRegEx );<br />
}<br />
else<br />
{<br />
strRegex.Append( "|" + m_szArthmtcRegEx );<br />
}<br />
}<br />
if( (exType & ExpressionType.ET_COMPARISON).Equals(ExpressionType.ET_COMPARISON) )<br />
{<br />
if( strRegex.Length == 0 )<br />
{<br />
strRegex.Append( m_szCmprsnRegEx );<br />
}<br />
else<br />
{<br />
strRegex.Append( "|" + m_szCmprsnRegEx );<br />
}<br />
}<br />
if( (exType & ExpressionType.ET_LOGICAL).Equals(ExpressionType.ET_LOGICAL) )<br />
{<br />
if( strRegex.Length == 0 )<br />
{<br />
strRegex.Append( m_szLgclRegEx );<br />
}<br />
else<br />
{<br />
strRegex.Append( "|" + m_szLgclRegEx );<br />
}<br />
}<br />
if( strRegex.Length == 0 )<br />
throw new RPN_Exception("Invalid combination of ExpressionType value");<br />
return "(" + strRegex.ToString() + ")";<br />
}<br />
static string m_szArthmtcRegEx = @"[+\-*/%()]{1}";<br />
static string m_szCmprsnRegEx = @"[=<>!]{1,2}";<br />
static string m_szLgclRegEx = @"[&|]{2}";<br />
#endregion<br />
<br />
public static string[] AllOperators<br />
{<br />
get<br />
{<br />
return m_AllOps;<br />
}<br />
}<br />
<br />
static string[] m_AllOps = { "||", "&&", "|", "^", "&", "==", "!=",<br />
"<", "<=", ">", ">=", "+", "-", "*", "/", "%", "(", ")" };<br />
static string[] m_AllArithmeticOps = { "+", "-", "*", "/", "%" };<br />
static string[] m_AllComparisonOps = { "==", "!=","<", "<=", ">", ">=" };<br />
static string[] m_AllLogicalOps = { "&&", "||" };<br />
}<br />
<br />
#endregion<br />
<br />
#region TODO List<br />
#endregion<br />
#region Content check<br />
public class StringContentCheck<br />
{<br />
static public bool IsNaturalNumber(String strNumber)<br />
{<br />
Regex objNotNaturalPattern=new Regex("[^0-9]");<br />
Regex objNaturalPattern=new Regex("0*[1-9][0-9]*");<br />
return !objNotNaturalPattern.IsMatch(strNumber) &&<br />
objNaturalPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsWholeNumber(String strNumber)<br />
{<br />
Regex objNotWholePattern=new Regex("[^0-9]");<br />
return !objNotWholePattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsInteger(String strNumber)<br />
{<br />
Regex objNotIntPattern=new Regex("[^0-9-]");<br />
Regex objIntPattern=new Regex("^-[0-9]+$|^[0-9]+$");<br />
return !objNotIntPattern.IsMatch(strNumber) && objIntPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsPositiveNumber(String strNumber)<br />
{<br />
Regex objNotPositivePattern=new Regex("[^0-9.]");<br />
Regex objPositivePattern=new Regex("^[.][0-9]+$|[0-9]*[.]*[0-9]+$");<br />
Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");<br />
return !objNotPositivePattern.IsMatch(strNumber) &&<br />
objPositivePattern.IsMatch(strNumber) &&<br />
!objTwoDotPattern.IsMatch(strNumber);<br />
}<br />
<br />
static public bool IsNumber(String strNumber)<br />
{<br />
Regex objNotNumberPattern=new Regex("[^0-9.-]");<br />
Regex objTwoDotPattern=new Regex("[0-9]*[.][0-9]*[.][0-9]*");<br />
Regex objTwoMinusPattern=new Regex("[0-9]*[-][0-9]*[-][0-9]*");<br />
String strValidRealPattern="^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$";<br />
String strValidIntegerPattern="^([-]|[0-9])[0-9]*$";<br />
Regex objNumberPattern =new Regex("(" + strValidRealPattern +")|(" + strValidIntegerPattern + ")");<br />
return !objNotNumberPattern.IsMatch(strNumber) &&<br />
!objTwoDotPattern.IsMatch(strNumber) &&<br />
!objTwoMinusPattern.IsMatch(strNumber) &&<br />
objNumberPattern.IsMatch(strNumber);<br />
}<br />
<br />
<br />
static public bool IsAlpha(String strToCheck)<br />
{<br />
Regex objAlphaPattern=new Regex("[^a-zA-Z ]");<br />
return !objAlphaPattern.IsMatch(strToCheck);<br />
}<br />
static public bool IsAlphaNumeric(String strToCheck)<br />
{<br />
Regex objAlphaNumericPattern=new Regex("[^a-zA-Z0-9 ]");<br />
return !objAlphaNumericPattern.IsMatch(strToCheck);<br />
}<br />
}<br />
#endregion<br />
<br />
}
|
|
|
|
|
does this parser work with expression with decimal numbers (like 2.4, 100.46)? I've tried to set "System.Double" type instead "System.Int64" when evaluating but it doesnt work.
|
|
|
|
|
I made some modifications. Mainly I have added a new class called DecimalOperand:
public class DecimalOperand : Operand, IArithmeticOperations, IComparisonOperations<br />
{<br />
public DecimalOperand(string szVarName, object varValue)<br />
: base(szVarName, varValue)<br />
{<br />
}<br />
public DecimalOperand(string szVarName)<br />
: base(szVarName)<br />
{<br />
}<br />
public override string ToString()<br />
{<br />
return m_szVarName;<br />
}<br />
public override void ExtractAndSetValue(string szValue, bool bFormula)<br />
{<br />
m_VarValue = !bFormula ? Convert.ToDecimal(szValue) : 0;<br />
}<br />
public IOperand Plus(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.Plus : rhs");<br />
DecimalOperand oprResult = new DecimalOperand("Result", Type.GetType("System.Decimal"));<br />
oprResult.Value = (decimal)this.Value + (decimal)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Minus(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.Minus : rhs");<br />
DecimalOperand oprResult = new DecimalOperand("Result", Type.GetType("System.Decimal"));<br />
oprResult.Value = (decimal)this.Value - (decimal)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Multiply(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new ArgumentException("Argument invalid in DecimalOperand.Multiply : rhs");<br />
DecimalOperand oprResult = new DecimalOperand("Result", Type.GetType("System.Decimal"));<br />
oprResult.Value = (decimal)this.Value * (decimal)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Divide(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.Divide : rhs");<br />
DecimalOperand oprResult = new DecimalOperand("Result", Type.GetType("System.Decimal"));<br />
oprResult.Value = (decimal)this.Value / (decimal)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand Modulo(IOperand rhs)<br />
{<br />
throw new RPN_Exception("Invalid operation with Decimals in DecimalOperand.Modulo : rhs");<br />
}<br />
<br />
public IOperand EqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.== : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = (decimal)this.Value == (decimal)((Operand)rhs).Value;<br />
return oprResult;<br />
}<br />
public IOperand NotEqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.!= : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((decimal)this.Value != (decimal)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThan(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.< : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((decimal)this.Value < (decimal)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand LessThanOrEqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.<= : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((decimal)this.Value <= (decimal)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThan(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.> : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((decimal)this.Value > (decimal)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
public IOperand GreaterThanOrEqualTo(IOperand rhs)<br />
{<br />
if (!(rhs is DecimalOperand))<br />
throw new RPN_Exception("Argument invalid in DecimalOperand.>= : rhs");<br />
BoolOperand oprResult = new BoolOperand("Result");<br />
oprResult.Value = ((decimal)this.Value >= (decimal)((Operand)rhs).Value) ? true : false;<br />
return oprResult;<br />
}<br />
}<br />
Also you have to modify static method CreateOperator din clasa OperandHelper. Add/uncomment comething like this:
case "System.Decimal":<br />
case "System.Single":<br />
oprResult = new DecimalOperand( szVarName, varValue );<br />
return oprResult;<br />
|
|
|
|
|
I tried this script, but did not work
does anyone have a working script?!
|
|
|
|
|