Resultados 1 al 2 de 2

Tema: Interpretador

  1. #1
      Administrador
    Avatar de Kuk

    Registrado
    enero de 2015
    Ubicación
    Madrid
    Edad
    37
    Mensajes
    2,084
    Última visita
    Ayer a las 17:02

    Agradecimientos
     
    Recibidos
    906
    Enviados
    782

    Citaciones y menciones
     
    Mentioned
    38 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    12 Post(s)
    Poder de Reputación
    10

    Predeterminado Interpretador

    Cita Iniciado por Eslopes
    Cobol does not have the ability to evaluate expressions dynamically, i.e. defining an expression in a string and having it evaluated during the runtime. OO Cobol is a whole different story. There is no eval command, but we can create our own way to evaluate things using the Interpreter Pattern!
    That sounds great, but what is an evalute command anyways? Good question. Language elements stored in a string are nothing, but a string. An eval command take that string and interpret its content, processing the elements accordling. That means power, the ability to define code blocks and have it processed when needed. The Interpreter Pattern allows you to define your own grammar, and process it in order to do some useful task.

    The Interpreter Pattern allows much more than simple arithmetic expressions evaluation, thought this is exactly what we are going to show here. The classes in this solutions are:
    • IExpression: Interface that declares an operation
    • Context: Global information used by the expression
    • TerminalExpression: Represent elements in the grammar that do no to get replace, such as symbols
    • NonTerminalExpression: Represents elements that will be replaced during the evaluation such as variables or even rules
    • ComputeFormula: Client class that also contains the parser used to break expression's elements.


    The ComputeFormula class deals with a lot of concepts not covered in this article, but I recommend you to understand that class in order to get yourself used to things like stacks, collections, string handling and much more.

    OO Cobol code

    Everything starts with an Interface definition. IExpression declares the contract to which classes must adhere in order to participate in this solution.

    COBOL Código:
    1.  INTERFACE-ID. IExpression as "InterpreterPattern.IExpression".
    2.    environment division.
    3.      configuration section.
    4.        repository.
    5.          class  ClassContext as "InterpreterPattern.Context".
    6.          
    7.    procedure division.
    8.    
    9.      method-id. EvaluateExpression as "Evaluate".
    10.        
    11.         data division.
    12.           linkage section.
    13.          
    14.           01  inContext   object reference ClassContext.
    15.           01  outValue    usage comp-2.
    16.          
    17.          procedure division using inContext returning outValue.
    18.       end method EvaluateExpression.
    19.  END INTERFACE IExpression.      

    The following classes implements the IExpression interface: AddExpression.cob, SubtractExpression.cob, , MultiplyExpression.cob, DivideExpression.cob, and PowerExpression.cob. These are also the classes that contains the actual calculation performed over operands.

    Below the code for PowerExpression code:

    COBOL Código:
    1.  CLASS-ID. PowerExpression AS "InterpreterPattern.PowerExpression"
    2.            inherits ClassNonTerminalExpression.
    3.    environment division.
    4.      configuration section.
    5.        repository.
    6.          class ClassContext               as "InterpreterPattern.Context"
    7.          class SystemString               as "System.String"
    8.          class ClassNonTerminalExpression as "InterpreterPattern.NonTerminalExpression"
    9.          
    10.           interface IExpression             as "InterpreterPattern.IExpression".
    11.          
    12.    *> Instance's data and methods
    13.     object.
    14.       data division.
    15.         working-storage section.
    16.         copy "types.book".
    17.        
    18.         01  variable  object reference SystemString private.
    19.        
    20.       procedure division.
    21.      
    22.         method-id. NEW.
    23.            data division.
    24.              linkage section.
    25.              01   inLeftExpression    object reference IExpression.
    26.              01   inRightExpression   object reference IExpression.
    27.              
    28.            procedure division using inLeftExpression, inRightExpression.
    29.              
    30.              invoke super "NEW" using inLeftExpression, inRightExpression.
    31.          
    32.         end method NEW.
    33.        
    34.         method-id. EvaluateExpresion as "Evaluate" override.
    35.           data division.
    36.             working-storage section.
    37.            
    38.             01 anExpression   object reference IExpression.
    39.            
    40.             linkage section.
    41.            
    42.             01 inContext  object reference ClassContext.
    43.             01 outValue   type SystemDouble.
    44.          
    45.           procedure division using inContext returning outValue.
    46.          
    47.             invoke super "GetLeftNode" returning anExpression
    48.             move  anExpression::"Evaluate"(inContext)  to  outValue
    49.             invoke super "GetRightNode" returning anExpression
    50.              
    51.             *> This is the real "PowerExpression"
    52.              compute outValue = outValue ** anExpression::"Evaluate"(inContext)
    53.                
    54.         end method EvaluateExpresion.
    55.     end object.
    56.   END CLASS PowerExpression.

    Other operations' classes such as AddExpression or MultiplyExpression have pretty much basically the same code structure.

    The TerminalExpression class that defines symbols behavior:

    COBOL Código:
    1.  CLASS-ID. TerminalExpression AS "InterpreterPattern.TerminalExpression".
    2.    environment division.
    3.      configuration section.
    4.        repository.
    5.          class ClassContext       as "InterpreterPattern.Context"
    6.          class SystemCollectionHashTable as "System.Collections.Hashtable"
    7.          class SystemString       as "System.String"
    8.          
    9.          interface IExpression       as "InterpreterPattern.IExpression".
    10.          
    11.    *> Instance's data and methods
    12.     object. implements IExpression.
    13.       data division.
    14.         working-storage section.
    15.         copy "types.book".
    16.        
    17.         01  variable  object reference SystemString private.
    18.        
    19.       procedure division.
    20.      
    21.         method-id. NEW.
    22.            data division.
    23.              linkage section.
    24.              01   inName    object reference SystemString.
    25.              
    26.            procedure division using inName.
    27.            
    28.              set   variable     to  inName
    29.          
    30.         end method NEW.
    31.        
    32.         method-id. EvaluateExpression as "Evaluate".
    33.           data division.
    34.             linkage section.
    35.            
    36.             01 inContext  object reference ClassContext.
    37.             01 outValue   type SystemDouble.
    38.          
    39.           procedure division using inContext returning outValue.
    40.          
    41.             move inContext::"GetValue"(variable)   to  outValue
    42.                
    43.         end method EvaluateExpression.
    44.     end object.
    45.   END CLASS TerminalExpression.

    The NonTerminalExpression class that defines rules:

    COBOL Código:
    1.  CLASS-ID. NonTerminalExpression AS "InterpreterPattern.NonTerminalExpression".
    2.    environment division.
    3.      configuration section.
    4.        repository.
    5.          class ClassContext       as "InterpreterPattern.Context"
    6.          class SystemCollectionHashTable as "System.Collections.Hashtable"
    7.          class SystemString       as "System.String"
    8.          
    9.          interface IExpression       as "InterpreterPattern.IExpression".
    10.          
    11.    *> Instance's data and methods
    12.     object. implements IExpression.
    13.       data division.
    14.         working-storage section.
    15.         copy "types.book".
    16.      
    17.         01  leftNode    object reference IExpression private.      
    18.         01  rightNode   object reference IExpression private.      
    19.        
    20.       procedure division.
    21.      
    22.         method-id. NEW.
    23.            data division.
    24.              linkage section.
    25.              01   inLeftExpression  object reference IExpression.
    26.              01   inRightExpression object reference IExpression.
    27.            procedure division using inLeftExpression inRightExpression.
    28.              
    29.              invoke self "SetLeftNode"  using inLeftExpression
    30.              invoke self "SetRightNode"   using inRightExpression
    31.            
    32.         end method NEW.
    33.        
    34.          method-id. SetLeftNode.
    35.           data division.
    36.             linkage section.
    37.            
    38.             01 inNode   object reference IExpression.
    39.          
    40.           procedure division using inNode.
    41.          
    42.             set  leftNode     to  inNode
    43.                
    44.         end method SetLeftNode.  
    45.          method-id. SetRightNode.
    46.           data division.
    47.             linkage section.
    48.            
    49.             01 inNode   object reference IExpression.
    50.          
    51.           procedure division using inNode.
    52.          
    53.             set  rightNode     to  inNode
    54.              
    55.         end method SetRightNode.  
    56.          method-id. GetLeftNode.
    57.           data division.
    58.             linkage section.
    59.            
    60.             01 outNode   object reference IExpression.
    61.          
    62.           procedure division returning outNode.
    63.          
    64.             set  outNode      to  leftNode
    65.                
    66.         end method GetLeftNode.  
    67.          method-id. GetRightNode.
    68.           data division.
    69.             linkage section.
    70.            
    71.             01 outNode   object reference IExpression.
    72.          
    73.           procedure division returning outNode.
    74.          
    75.             set  outNode       to  rightNode
    76.                
    77.         end method GetRightNode.  
    78.         method-id. EvaluateExpression as "Evaluate".
    79.           data division.
    80.             linkage section.
    81.            
    82.             01 inContext  object reference ClassContext.
    83.             01 outValue   type SystemDouble.
    84.          
    85.           procedure division using inContext returning outValue.
    86.          
    87.             *> Implemented because NetCobol.Net does not supports Abstract classes
    88.                
    89.         end method EvaluateExpression.
    90.     end object.
    91.   END CLASS NonTerminalExpression.
    Imagem Anexada Imagem Anexada

    0 Not allowed!
    ¿Te han ayudado? NO TE OLVIDES de darle al botón
    ¿Quieres dirigirte a alguien en tu post? Notifícale con una mención, tienes 2 opciones:
    1. Haciendo clic en el icono al lado de su nick
    2. Haciendo clic en el botón en el editor y escribiendo su nick.

  2. #2
      Administrador
    Avatar de Kuk

    Registrado
    enero de 2015
    Ubicación
    Madrid
    Edad
    37
    Mensajes
    2,084
    Última visita
    Ayer a las 17:02

    Agradecimientos
     
    Recibidos
    906
    Enviados
    782

    Citaciones y menciones
     
    Mentioned
    38 Post(s)
    Tagged
    0 Thread(s)
    Quoted
    12 Post(s)
    Poder de Reputación
    10

    Predeterminado Continuación...

    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.

    COBOL Código:
    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:

    COBOL Código:
    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

    0 Not allowed!
    ¿Te han ayudado? NO TE OLVIDES de darle al botón
    ¿Quieres dirigirte a alguien en tu post? Notifícale con una mención, tienes 2 opciones:
    1. Haciendo clic en el icono al lado de su nick
    2. Haciendo clic en el botón en el editor y escribiendo su nick.

Información de Tema

Usuarios Viendo este Tema

Actualmente hay 1 usuarios viendo este tema. (0 miembros y 1 visitantes)

Temas Similares

  1. [Herramienta] Interpretador de JCL para Windows
    Por B4K4NDFCV en el foro JCL y utilidades
    Respuestas: 4
    Último Mensaje: 20.07.2018, 18:19

Marcadores

Marcadores

Permisos de Publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •