CLASS-ID. ComputeFormula AS "InterpreterPattern.ComputeFormula".
environment division.
configuration section.
repository.
class SystemCollectionHashTable as "System.Collections.Hashtable"
class SystemString as "System.String"
class SystemCollectionStack as "System.Collections.Stack"
class SystemDoubleWrapper as "System.Double"
class SystemObject as "System.Object"
class ClassAddExpression as "InterpreterPattern.AddExpression"
class ClassSubtractExpression as "InterpreterPattern.SubtractExpression"
class ClassMultiplyExpression as "InterpreterPattern.MultiplyExpression"
class ClassDivideExpression as "InterpreterPattern.DivideExpression"
class ClassPowerExpression as "InterpreterPattern.PowerExpression"
class ClassTerminalExpression as "InterpreterPattern.TerminalExpression"
class ClassNonTerminalExpression as "InterpreterPattern.NonTerminalExpression"
class ClassContext as "InterpreterPattern.Context"
interface IExpression as "InterpreterPattern.IExpression"
property StringNull as "Empty"
property StringLength as "Length"
property StackCount as "Count".
*> Instance's data and methods
object.
data division.
working-storage section.
copy "types.book".
01 booleanTrue pic 1 value b"1".
01 booleanFalse pic 1 value b"0".
01 expression object reference SystemString.
01 ctx object reference ClassContext.
01 operators object reference SystemCollectionHashTable private.
01 tempObject object reference SystemObject.
procedure division.
method-id. NEW.
procedure division.
invoke SystemCollectionHashTable "NEW" returning operators
invoke operators "Add" using by value "+" by value "1"
invoke operators "Add" using by value "-" by value "1"
invoke operators "Add" using by value "/" by value "2"
invoke operators "Add" using by value "*" by value "2"
invoke operators "Add" using by value "^" by value "2"
invoke operators "Add" using by value "(" by value "0"
end method NEW.
method-id. SetContext as "SetContext".
data division.
linkage section.
01 inContext object reference ClassContext.
procedure division using inContext.
set ctx to inContext
end method SetContext.
method-id. SetExpression as "SetExpression".
data division.
linkage section.
01 inExpression object reference SystemString.
procedure division using inExpression.
set expression to inExpression
end method SetExpression.
method-id. EvaluateExpression as "Evaluate".
data division.
working-storage section.
01 postFixExp object reference SystemString.
01 rootNode object reference IExpression.
linkage section.
01 outValue type SystemDouble.
procedure division returning outValue.
set postFixExp to self::"infixToPostFix"(expression)
set rootNode to self::"BuildTree"(postFixExp)
set outValue to rootNode::"Evaluate"(ctx)
end method EvaluateExpression.
method-id. GetNonTerminalExpression as "GetNonTerminalExpression" private.
data division.
working-storage section.
01 postFixExp object reference SystemString.
01 rootNode object reference IExpression.
01 singleChar pic x.
linkage section.
01 operation object reference SystemString.
01 leftExpression object reference IExpression.
01 rightExpression object reference IExpression.
01 outValue object reference ClassNonTerminalExpression.
procedure division using operation leftExpression
rightExpression returning outValue.
set outValue to null
set singleChar to operation::"Trim"()
evaluate singleChar
when "+"
invoke ClassAddExpression "NEW" using leftExpression,
rightExpression
returning outValue
when "-"
invoke ClassSubtractExpression "NEW" using leftExpression,
rightExpression
returning outValue
when "*"
invoke ClassMultiplyExpression "NEW" using leftExpression,
rightExpression
returning outValue
when "/"
invoke ClassDivideExpression "NEW" using leftExpression,
rightExpression
returning outValue
when "^"
invoke ClassPowerExpression "NEW" using leftExpression,
rightExpression
returning outValue
end-evaluate
end method GetNonTerminalExpression.
method-id. BuildTree as "BuildTree" private.
data division.
working-storage section.
01 currentChar object reference SystemString.
01 leftOperand object reference IExpression.
01 rightOperand object reference IExpression.
01 exp object reference IExpression.
01 stack object reference SystemCollectionStack.
01 rootNode object reference IExpression.
01 indexer pic s9(09) value zeros.
linkage section.
01 inFormula object reference SystemString.
01 outExpression object reference IExpression.
procedure division using inFormula returning outExpression.
invoke SystemCollectionStack "NEW" returning stack
move zeros to indexer
perform until indexer = StringLength of inFormula
set currentChar to inFormula::"Substring"(indexer, 1)
if (self::"IsOperator"(currentChar) = booleanFalse)
set exp to ClassTerminalExpression::"NEW"(currentChar)
invoke stack "Push" using by value exp
else
set tempObject to stack::"Pop"()
set rightOperand to tempObject as IExpression
set tempObject to stack::"Pop"()
set leftOperand to tempObject as IExpression
set exp to self::"GetNonTerminalExpression"
(currentChar, leftOperand, rightOperand)
invoke stack "Push" using by value exp
end-if
add 1 to indexer
end-perform
set tempObject to stack::"Pop"()
set outExpression to tempObject as IExpression
end method BuildTree.
method-id. IsOperator as "IsOperator" private.
data division.
working-storage section.
01 singleChar pic x.
linkage section.
01 inCharacter object reference SystemString.
01 outBool pic 1.
procedure division using inCharacter returning outBool.
set singleChar to inCharacter
if (singleChar = "+" or "-" or "*" or "/" or "^")
move booleanTrue to outBool
else
move booleanFalse to outBool
end-if
end method IsOperator.
method-id. infixToPostFix as "InFixToPostFix".
data division.
working-storage section.
01 stack object reference SystemCollectionStack.
01 pfExpr object reference SystemString.
01 tempString object reference SystemString.
01 expr object reference SystemString.
01 indexer type SystemInt32.
01 stringVal1 object reference SystemString.
01 stringVal2 object reference SystemString.
01 val1 type SystemDouble.
01 val2 type SystemDouble.
01 currentChar object reference SystemString.
linkage section.
01 inString object reference SystemString.
01 outString object reference SystemString.
procedure division using inString returning outString.
invoke SystemCollectionStack "NEW" returning stack
set pfExpr to StringNull of SystemString
set tempString to StringNull of SystemString
set expr to inString::"Trim"()
move zeros to indexer
perform until indexer = StringLength of inString
set currentChar to inString::"Substring"(indexer, 1)
if (currentChar::"Equals"(" ") = booleanTrue)
add 1 to indexer
exit to test of perform
end-if
if (self::"IsOperator"(currentChar) = booleanFalse)
and (currentChar::"Equals"("(") = booleanFalse)
and (currentChar::"Equals"(")") = booleanFalse)
set pfExpr to SystemString::"Concat"(pfExpr, currentChar)
end-if
if (currentChar::"Equals"("(") = booleanTrue)
invoke stack "Push" using currentChar
end-if
if (currentChar::"Equals"(")") = booleanTrue)
set tempObject to stack::"Pop"()
set tempString to tempObject as SystemString
perform until tempString::"Equals"("(") = booleanTrue
set pfExpr to SystemString::"Concat"(pfExpr, tempString)
set tempObject to stack::"Pop"()
set tempString to tempObject as SystemString
end-perform
set tempString to StringNull of SystemString
end-if
if (self::"IsOperator"(currentChar) = booleanTrue)
if (StackCount of stack >; 0)
set tempObject to stack::"Pop"()
set tempString to tempObject as SystemString
set tempObject to operators::"Get_Item"(tempString)
set stringVal1 to tempObject as SystemString
set tempObject to operators::"Get_Item"(currentChar)
set stringVal2 to tempObject as SystemString
move SystemDoubleWrapper::"Parse"(stringVal1) to val1
move SystemDoubleWrapper::"Parse"(stringVal2) to val2
perform until val1 <; val2
set pfExpr to SystemString::"Concat"(pfExpr, tempString)
move -100 to val1
if (StackCount of stack >; 0)
set tempObject to stack::"Pop"()
set tempString to tempObject as SystemString
set tempObject to operators::"Get_Item"(tempString)
set stringVal1 to tempObject as SystemString
set val1 to SystemDoubleWrapper::"Parse"(stringVal1)
end-if
end-perform
if (val1 <; val2) and (val1 > -100)
invoke stack "Push" using tempString
end-if
end-if
invoke stack "Push" using currentChar
end-if
add 1 to indexer
end-perform
perform until StackCount of stack = 0
set tempObject to stack::"Pop"()
set tempString to tempObject as SystemString
set pfExpr to SystemString::"Concat"(pfExpr, tempString)
end-perform
set outString to pfExpr
end method infixToPostFix.
end object.
END CLASS ComputeFormula.