Ver Mensaje Individual
  #2
Antiguo 23 de febrero de 2017, 09:43
Kuk
Administrador
Última Actividad 19.09.2026 20:11
Posts Posts: 2.500
Likes enviados Enviados: 1037
Likes recibidos Recibidos: 1207
Predeterminado Continuación...
0 Inactivo Inactivo

The ComputeFormula class is the "client" class of this example. It contains a parser, the expression tree builder and, of course, uses Interpreter pattern to arrange things.

Código COBOL:
  1.  CLASS-ID. ComputeFormula AS "InterpreterPattern.ComputeFormula".
  2.    environment division.
  3.      configuration section.
  4.        repository.
  5.          class SystemCollectionHashTable   as "System.Collections.Hashtable"
  6.          class SystemString               as "System.String"
  7.          class SystemCollectionStack       as "System.Collections.Stack"
  8.          class SystemDoubleWrapper         as "System.Double"
  9.          class SystemObject               as "System.Object"
  10.          
  11.           class ClassAddExpression         as "InterpreterPattern.AddExpression"
  12.           class ClassSubtractExpression     as "InterpreterPattern.SubtractExpression"
  13.           class ClassMultiplyExpression     as "InterpreterPattern.MultiplyExpression"
  14.           class ClassDivideExpression       as "InterpreterPattern.DivideExpression"
  15.           class ClassPowerExpression       as "InterpreterPattern.PowerExpression"
  16.           class ClassTerminalExpression     as "InterpreterPattern.TerminalExpression"
  17.           class ClassNonTerminalExpression as "InterpreterPattern.NonTerminalExpression"
  18.           class ClassContext               as "InterpreterPattern.Context"
  19.          
  20.           interface IExpression             as "InterpreterPattern.IExpression"
  21.          
  22.           property StringNull               as "Empty"
  23.           property StringLength             as "Length"
  24.           property StackCount               as "Count".
  25.          
  26.    *> Instance's data and methods
  27.     object.
  28.       data division.
  29.         working-storage section.
  30.         copy "types.book".
  31.         01 booleanTrue  pic 1 value b"1".
  32.         01 booleanFalse   pic 1 value b"0".
  33.         01 expression   object reference SystemString.
  34.         01 ctx      object reference ClassContext.      
  35.         01 operators    object reference SystemCollectionHashTable private.
  36.         01 tempObject   object reference SystemObject.
  37.        
  38.       procedure division.
  39.      
  40.         method-id. NEW.
  41.          
  42.            procedure division.
  43.              invoke SystemCollectionHashTable "NEW" returning operators
  44.              
  45.              invoke operators "Add" using by value "+" by value "1"
  46.              invoke operators "Add" using by value "-" by value "1"
  47.              invoke operators "Add" using by value "/" by value "2"
  48.              invoke operators "Add" using by value "*" by value "2"
  49.              invoke operators "Add" using by value "^" by value "2"
  50.              invoke operators "Add" using by value "(" by value "0"
  51.         end method NEW.
  52.        
  53.         method-id. SetContext   as "SetContext".
  54.            data division.
  55.              linkage section.
  56.              
  57.              01  inContext  object reference ClassContext.
  58.            
  59.            procedure division using inContext.
  60.            
  61.              set ctx        to  inContext
  62.                      
  63.         end method SetContext.
  64.         method-id. SetExpression   as "SetExpression".
  65.            data division.
  66.              linkage section.
  67.              
  68.              01  inExpression  object reference SystemString.
  69.            
  70.            procedure division using inExpression.
  71.            
  72.              set expression       to  inExpression
  73.                      
  74.         end method SetExpression.
  75.        
  76.         method-id. EvaluateExpression as "Evaluate".
  77.          
  78.           data division.
  79.          
  80.             working-storage section.
  81.            
  82.             01 postFixExp   object reference SystemString.
  83.             01 rootNode   object reference IExpression.
  84.            
  85.             linkage section.
  86.            
  87.             01 outValue   type SystemDouble.
  88.            
  89.           procedure division returning outValue.
  90.            
  91.             set   postFixExp    to  self::"infixToPostFix"(expression)
  92.             set   rootNode      to  self::"BuildTree"(postFixExp)
  93.             set   outValue      to  rootNode::"Evaluate"(ctx)
  94.            
  95.         end method EvaluateExpression.
  96.    
  97.         method-id. GetNonTerminalExpression as "GetNonTerminalExpression" private.
  98.          
  99.           data division.
  100.            
  101.              working-storage section.
  102.              
  103.              01 postFixExp    object reference SystemString.
  104.              01 rootNode    object reference IExpression.
  105.              01 singleChar    pic x.
  106.              
  107.              linkage section.
  108.              
  109.              01 operation     object reference SystemString.
  110.              01 leftExpression  object reference IExpression.
  111.              01 rightExpression object reference IExpression.
  112.              01 outValue    object reference ClassNonTerminalExpression.
  113.              
  114.            procedure division using operation leftExpression
  115.                                               rightExpression returning outValue.
  116.              set  outValue       to  null
  117.              set  singleChar       to  operation::"Trim"()
  118.              
  119.              evaluate singleChar
  120.              
  121.                   when "+"
  122.                     invoke ClassAddExpression "NEW" using leftExpression,
  123.                                                           rightExpression
  124.                            returning outValue
  125.              
  126.                   when "-"
  127.                     invoke ClassSubtractExpression "NEW" using leftExpression,
  128.                                                                rightExpression
  129.                            returning outValue
  130.                   when "*"
  131.                     invoke ClassMultiplyExpression "NEW" using leftExpression,
  132.                                                                rightExpression
  133.                            returning outValue
  134.                   when "/"
  135.                     invoke ClassDivideExpression "NEW" using leftExpression,
  136.                                                              rightExpression
  137.                            returning outValue
  138.              
  139.                   when "^"
  140.                     invoke ClassPowerExpression "NEW" using leftExpression,
  141.                                                             rightExpression
  142.                            returning outValue
  143.              end-evaluate
  144.                    
  145.          end method GetNonTerminalExpression.
  146.          
  147.          method-id. BuildTree as "BuildTree" private.
  148.            
  149.            data division.
  150.            
  151.              working-storage section.
  152.              
  153.              01 currentChar   object reference SystemString.
  154.              01 leftOperand   object reference IExpression.
  155.              01 rightOperand  object reference IExpression.
  156.              01 exp       object reference IExpression.
  157.              01 stack       object reference SystemCollectionStack.  
  158.              01 rootNode    object reference IExpression.
  159.              01 indexer     pic s9(09) value zeros.
  160.              linkage section.
  161.              
  162.              01 inFormula     object reference SystemString.
  163.              01 outExpression   object reference IExpression.
  164.              
  165.            procedure division using inFormula returning outExpression.
  166.              invoke SystemCollectionStack "NEW" returning stack
  167.              
  168.              move   zeros         to  indexer
  169.              perform until indexer = StringLength of inFormula
  170.                set  currentChar     to  inFormula::"Substring"(indexer, 1)
  171.                
  172.                if   (self::"IsOperator"(currentChar) = booleanFalse)
  173.                   set   exp       to  ClassTerminalExpression::"NEW"(currentChar)
  174.                  
  175.                   invoke stack "Push" using by value exp
  176.                else
  177.                   set  tempObject   to  stack::"Pop"()
  178.                   set  rightOperand   to  tempObject as IExpression
  179.                   set  tempObject   to  stack::"Pop"()
  180.                   set  leftOperand  to  tempObject as IExpression
  181.                   set  exp  to  self::"GetNonTerminalExpression"
  182.                                (currentChar, leftOperand, rightOperand)
  183.                  
  184.                   invoke stack "Push" using by value exp
  185.                end-if
  186.                
  187.                add  1           to  indexer
  188.                
  189.              end-perform
  190.              
  191.              set  tempObject        to  stack::"Pop"()
  192.              set  outExpression     to  tempObject as IExpression
  193.                    
  194.          end method BuildTree.
  195.          
  196.          method-id. IsOperator as "IsOperator" private.
  197.            data division.
  198.            
  199.              working-storage section.
  200.              01  singleChar   pic x.
  201.              
  202.              linkage section.
  203.              
  204.              01  inCharacter  object reference SystemString.
  205.              01  outBool    pic 1.
  206.              
  207.            procedure division using inCharacter returning outBool.
  208.              set   singleChar      to  inCharacter
  209.            
  210.              if (singleChar = "+" or "-" or "*" or "/" or "^")
  211.                move  booleanTrue     to  outBool
  212.              else
  213.                move  booleanFalse    to  outBool
  214.              end-if
  215.              
  216.          end method IsOperator.
  217.          
  218.          method-id. infixToPostFix as "InFixToPostFix".
  219.            data division.
  220.              working-storage section.
  221.              01 stack       object reference SystemCollectionStack.  
  222.              01 pfExpr      object reference SystemString.
  223.              01 tempString    object reference SystemString.
  224.              01 expr      object reference SystemString.
  225.              01 indexer     type SystemInt32.
  226.              01 stringVal1    object reference SystemString.
  227.              01 stringVal2    object reference SystemString.
  228.              01 val1      type SystemDouble.
  229.              01 val2      type SystemDouble.
  230.              01 currentChar   object reference SystemString.
  231.              
  232.              linkage section.
  233.              01 inString    object reference SystemString.
  234.              01 outString     object reference SystemString.
  235.    
  236.            procedure division using inString returning outString.
  237.              invoke SystemCollectionStack "NEW" returning stack
  238.      
  239.              set  pfExpr        to  StringNull of SystemString
  240.              set  tempString      to  StringNull of SystemString
  241.              set  expr        to  inString::"Trim"()
  242.              
  243.              move   zeros         to  indexer
  244.              perform until indexer = StringLength of inString
  245.                set currentChar     to  inString::"Substring"(indexer, 1)
  246.              
  247.                if  (currentChar::"Equals"(" ") = booleanTrue)
  248.                  add  1        to  indexer
  249.                  exit to test of perform
  250.                end-if
  251.                if (self::"IsOperator"(currentChar) = booleanFalse)
  252.                and (currentChar::"Equals"("(") = booleanFalse)
  253.                and (currentChar::"Equals"(")") = booleanFalse)
  254.                   set  pfExpr   to  SystemString::"Concat"(pfExpr, currentChar)
  255.                end-if
  256.            
  257.                if (currentChar::"Equals"("(") = booleanTrue)
  258.                   invoke stack "Push" using currentChar
  259.                end-if
  260.                  
  261.                if (currentChar::"Equals"(")") = booleanTrue)
  262.                   set  tempObject      to  stack::"Pop"()
  263.                   set  tempString      to  tempObject as SystemString
  264.                   perform until tempString::"Equals"("(") = booleanTrue
  265.                       set  pfExpr    to  SystemString::"Concat"(pfExpr, tempString)
  266.                       set  tempObject  to  stack::"Pop"()
  267.                       set  tempString  to  tempObject as SystemString
  268.                   end-perform
  269.            
  270.                   set   tempString     to  StringNull of SystemString
  271.                end-if
  272.          
  273.                if (self::"IsOperator"(currentChar) = booleanTrue)
  274.                   if (StackCount of stack >; 0)
  275.                    set  tempObject     to  stack::"Pop"()
  276.                    set  tempString     to  tempObject as SystemString
  277.                    set  tempObject     to  operators::"Get_Item"(tempString)
  278.                    set  stringVal1     to  tempObject as SystemString
  279.                    set  tempObject     to  operators::"Get_Item"(currentChar)
  280.                    set  stringVal2     to  tempObject as SystemString
  281.                    
  282.                    move SystemDoubleWrapper::"Parse"(stringVal1)  to  val1
  283.                    move SystemDoubleWrapper::"Parse"(stringVal2)  to  val2
  284.                    
  285.                    perform until val1 <; val2
  286.                        set   pfExpr       to  SystemString::"Concat"(pfExpr, tempString)
  287.                        
  288.                        move  -100         to  val1
  289.                        
  290.                        if (StackCount of stack >; 0)
  291.                         set  tempObject     to  stack::"Pop"()
  292.                         set  tempString     to  tempObject as SystemString
  293.                         set  tempObject     to  operators::"Get_Item"(tempString)
  294.                         set  stringVal1     to  tempObject as SystemString
  295.                         set  val1       to  SystemDoubleWrapper::"Parse"(stringVal1)
  296.                        end-if
  297.                        
  298.                    end-perform    
  299.                    
  300.                    if (val1 <; val2) and (val1 > -100)
  301.                     invoke stack "Push" using tempString
  302.                    end-if
  303.                   end-if
  304.                
  305.                   invoke stack "Push" using currentChar
  306.                end-if
  307.                
  308.                add   1       to  indexer
  309.              end-perform
  310.            
  311.              perform until StackCount of stack = 0
  312.                  set   tempObject  to  stack::"Pop"()
  313.                  set   tempString  to  tempObject as SystemString
  314.                  set   pfExpr    to  SystemString::"Concat"(pfExpr, tempString)
  315.              end-perform
  316.              
  317.              set   outString     to  pfExpr
  318.            
  319.             end method infixToPostFix.
  320.          
  321.      end object.
  322.    END CLASS ComputeFormula.

Testing our expression evaluator

The little application below shows how to use our expression evaluator:

Código COBOL:
  1.  IDENTIFICATION DIVISION.
  2.  PROGRAM-ID. MAIN AS "ConsoleApplication1.Main".
  3.  ENVIRONMENT DIVISION.
  4.  CONFIGURATION SECTION.
  5.  SPECIAL-NAMES.
  6.  REPOSITORY.
  7.      class ClassComputeFormula   as "InterpreterPattern.ComputeFormula"
  8.      class ClassContext         as "InterpreterPattern.Context".
  9.      
  10.   DATA DIVISION.
  11.   WORKING-STORAGE SECTION.
  12.   01  computeFormula    object reference ClassComputeFormula.
  13.   01  context           object reference ClassContext.
  14.   01  result            comp-2.
  15.   01  displayResult     pic s9(09)v99.
  16.  
  17.   PROCEDURE DIVISION.
  18.       invoke  ClassComputeFormula "NEW" returning computeFormula
  19.       invoke  ClassContext        "NEW" returning context
  20.      
  21.       invoke  computeFormula "SetExpression" using "((a ^ b) + c) * d"
  22.      
  23.       invoke  context "CreateVariable" using "a", 10
  24.       invoke  context "CreateVariable" using "b", 2
  25.       invoke  context "CreateVariable" using "c", 2
  26.       invoke  context "CreateVariable" using "d", 8.5
  27.      
  28.       invoke  computeFormula "SetContext" using context
  29.       invoke  computeFormula "Evaluate" returning result
  30.      
  31.       move    result                 to  displayResult
  32.      
  33.       display displayResult
  34.      
  35.   END PROGRAM MAIN.

What else can I do with that Pattern?

You name it! Maybe a script language to provide some automation support in your application. Maybe you could create basic Cobol evaluators. That would be something really cool! There are no limits!

Download the source

Cool things with OO Cobol - Source Code

Some references in the web

Interpreter .NET Design Pattern in C# and VB - dofactory.com



NORMAS DEL FORO - para garantizar el buen funcionamiento del Foro.
¿Te han ayudado? NO TE OLVIDES de darle a
¿Quieres dirigirte a alguien en tu post? Notifícale haciendo clic en su Nick
Kuk is offline   Responder Con Cita