//  CAFE2011.EXE is licensed under the terms of the CC-LGPL.
//  (CC-LGPL Version 3, 29 junio 2007 y CAFE2011 version 2011)
//  El objetivo es el libre uso comercial y no comercial del software.
//  Una copia de dicho documento se incluye en esta distribucion.
//  CWSDPMI.EXE, STREAMCO.PAS, el procedimiento TextOut
//  se tomaron de la distribucion FreePascal 2.4.2. con patente similar.
//        StreamCo.PAS es una contraccion conveniente a ocho letras del
//        nombre StreamColl.PAS en la distribucion FreePascal
  {$MODE                OBJFPC          }
  {$INCLUDEPATH         ..\INCLUDE      }
  {$INCLUDE             CAFE_INC.INC    }
  {$DEFINE              SILENCIAR       }
  {$DEFINE              PRU_EJ3         }

  { Especifico en CAFE_Ej3              }
  {$TYPEDADDRESS        OFF             }
UNIT CAFE_Ej3;

INTERFACE

USES CAFE_Ej1, CAFE_Ej2, SysUtils, Variants, Classes , Math;

CONST
  CAFE_TamanoCadenaSintactica        = 20;
{
  Utilizado como tamano de Strings predefinidos,
  su valor podria cambiar en el futuro sin previo aviso,
  si se requiere
}

CONST
  CAFE_IdentificadorUpIgualDown      : Boolean                  = TRUE;
{
  CAFE_IdentificadorUpIgualDown      : TRUE produce que las mayusculas
        sean equivalentes a las minusculas en los identificadores.
        Si FALSE, se toman como diferentes
}

CONST
  CAFE_CharStringPascal              = '''';
{
  CAFE_CharStringPascal              : Delimitador de cadenas String
        Otra version de CAFE_ByteDelimitadorStringSintactico
        La doble version, puede considerarse un descuido
}

  CAFE_ByteStringPascal              = Ord( CAFE_CharStringPascal );
{
  CAFE_ByteStringPascal              : Version Byte del
        CAFE_CharStringPascal
}

  CAFE_ComentarioIzquierda1Pascal    = '{';
{
  CAFE_ComentarioIzquierda1Pascal    : Delimitador izquierdo de comentario
        Pascal.
}

  CAFE_ComentarioDerecha1Pascal      = '}';
{
  CAFE_ComentarioDerecha1Pascal      : Delimitador derecho de comentario
        Pascal.
}

  CAFE_ComentarioIzquierda2Pascal    = '(*';
{
  CAFE_ComentarioIzquierda2Pascal    : Delimitador izquierdo de comentario
        Pascal.
}

  CAFE_ComentarioDerecha2Pascal      = '*)';
{
  CAFE_ComentarioDerecha2Pascal      : Delimitador derecho de comentario
        Pascal.
}

  CAFE_ComentarioIzquierda3Pascal    = '//';
{
  CAFE_ComentarioIzquierda3Pascal    : Delimitado izquierdo de comentario
        Pascal.
}

  CAFE_ComentarioDerecha3Pascal      = #13;
{
  CAFE_ComentarioDerecha3Pascal      : El delimitador de comentario //
        acaba en final de renglon.
}

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  CAFE_CharParentesisAbrirArregloIndicePascal                = '['
                                        unimplemented;
{
  CAFE_CharParentesisAbrirArregloIndicePascal   : Parentesis abrir de
        arreglo en Pascal
}

  CAFE_ByteParentesisAbrirArregloIndicePascal                =
                        Ord( CAFE_CharParentesisAbrirArregloIndicePascal )
                                        unimplemented;
{
  CAFE_ByteParentesisAbrirArregloIndicePascal   : Version byte de
        CAFE_CharParentesisAbrirArregloIndicePascal
}

  CAFE_CharParentesisCerrarArregloIndicePascal               = ']'
                                        unimplemented;
{
  CAFE_CharParentesisCerrarArregloIndicePascal  : Parentesis cerrar de
        arreglo en Pascal
}

  CAFE_ByteParentesisCerrarArregloIndicePascal               =
                        Ord( CAFE_CharParentesisCerrarArregloIndicePascal )
                                        unimplemented;
{
  CAFE_ByteParentesisCerrarArregloIndicePascal  : Version byte de
        CAFE_CharParentesisCerrarArregloIndicePascal
}

  CAFE_CharParentesisAbrirConjuntoPascal                     = '['
                                        unimplemented;
{
  CAFE_CharParentesisAbrirConjuntoPascal        : Parentesis abrir de
        tipo conjunto de Pascal
}

  CAFE_ByteParentesisAbrirConjuntoPascal                     =
                        Ord( CAFE_CharParentesisAbrirConjuntoPascal )
                                        unimplemented;
{
  CAFE_ByteParentesisAbrirConjuntoPascal        : Version Byte de
        CAFE_CharParentesisAbrirConjuntoPascal
}

  CAFE_CharParentesisCerrarConjuntoPascal                    = ']'
                                        unimplemented;
{
  CAFE_CharParentesisCerrarConjuntoPascal       : Parentesis cerrar de
        tipo conjunto de Pascal
}

  CAFE_ByteParentesisCerrarConjuntoPascal                    =
                        Ord( CAFE_CharParentesisCerrarConjuntoPascal )
                                        unimplemented;
{
  CAFE_ByteParentesisCerrarConjuntoPascal       : Version Byte de
        CAFE_CharParentesisCerrarConjuntoPascal
}

  CAFE_RegistroCampoPascal                                   = '.'
                                        unimplemented;
{
  CAFE_RegistroCampoPascal                      : Separador de
        campo de registro en pascal
}

  CAFE_SecuenciaNumeradaOrdenadaPascal                       = '..'
                                        unimplemented;
{
  CAFE_SecuenciaNumeradaOrdenadaPascal          : Indicador de
        secuencia consecutiva de tipo ordenado en Pascal
}

  CAFE_MemoriaApuntadaPascal                                 = '^'
                                        unimplemented;
{
  CAFE_MemoriaApuntadaPascal                    : Indicador de
        Dato asignado por un puntero en Pascal
}

  CAFE_AsignacionBasicaPascal                                = ':='
                                        unimplemented;
{
  CAFE_AsignacionBasicaPascal                   : Indicador de
        asignacion principal de Pascal
}

  CAFE_AsignacionTipoPascal                                  = ':'
                                        unimplemented;
{
  CAFE_AsignacionTipoPascal                     : Indicador de
        tipo en Pascal
}

  CAFE_AsignacionConstantePascal                             = '='
                                        unimplemented;
{
  CAFE_AsignacionConstantePascal                : Indicador de
        asignacion valor de constante en Pascal
}

  CAFE_AsignacionConstanteVARPascal                          = '='
                                        unimplemented;
{
  CAFE_AsignacionConstanteVARPascal             : Indicador de
        asignacion VAR constante de Pascal
}

  CAFE_CharExcepcionDescriptorWritePascal                    = ':'
                                        unimplemented;
{
  CAFE_CharExceptionDescriptorWritePascal       : En pascal
        se escribe por ejemplo Write( Numero:8:2 ).
        Este separador puede tener en esta unidad procesamiento
        adicional
}

  CAFE_ByteExcepcionDescriptorWritePascal                    =
                        Ord( CAFE_CharExcepcionDescriptorWritePascal )
                                        unimplemented;
{
  CAFE_ByteExceptionDescriptorWritePascal       : Version Byte de
        CAFE_CharExcepcionDescriptorWritePascal
}

  CAFE_AsignacionConstanteRegistroPascal                     = ':'
                                        unimplemented;
{
  CAFE_AsignacionConstanteRegistroPascal        : indicacion de
        asignacion de un registro inicializado
        Por ejemplo, un registro declarado en seccion CONST
}

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
  CAFE_OperadorCHRSintactico                                 = 'CHR()';
{
  CAFE_OperadorCHRSintactico                    : Operador CHR, para
        convertir un Byte en Caracter char
}

CONST
        // Operadores introducidos rapidamente
        // por compatibilidad con Hoja de Calculo
        // Probablemente fallaran si no se enmascaran
        // en aplicaciones mas complejas
  CAFE_SecuenciaRectangularHoja                              = ':';
{
  CAFE_SecuenciaRectangularHoja                 : Indicacion de
        secuencia de celdas, tipico de hojas de calculo
}

  CAFE_SecuenciaRectangularHojaTraducidoOperadorBasico       =
                                        CAFE_CharIgnoradoLibre+'AR()';
{
  CAFE_SecuenciaRectangularHojaTraducidoOperadorBasico          :
        En las ordenes de Hoja de Calculo se sustituye el :,
        por este operador de secuencia, a nivel interno
}

CONST
  CAFE_OperadorStringTraducidoOperadorBasico                 =
                                        CAFE_CharIgnoradoLibre+'ST()';
{
  CAFE_OperadorStringTraducidoOperadorBasico    : Al interpretar una
        orden, los String se eliminan de la orden y se sustituyen
        por operadores Self, o Chr(), etc
}

  CAFE_IdentificadorStringNull                               =
                                        CAFE_CharIgnoradoLibre+'0';
{
  CAFE_IdentificadorStringNull                  : Se sustituye
        el '' como String o Char por este identificador del mismo tamano
}

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
  CAFE_OperadorAsignacionBasicaTraducidoOperadorBasico       =
                                        CAFE_CharIgnoradoLibre+'A()';
{
  CAFE_OperadorAsignacionBasicaTraducidoOperadorBasico          :
        Operdor para traducir la asignacion
}

  CAFE_OperadorAsignacionTipoTraducidoOperadorBasico         =
                                        CAFE_CharIgnoradoLibre+'AT()'
                                        unimplemented;
{
  CAFE_OperadorAsignacionTipoTraducidoOperadorBasico            :
        Operador para traducir una asignacion de tipo
}

  CAFE_OperadorRegistroCampoTraducidoOperadorBasico          =
                                        CAFE_CharIgnoradoLibre+'()';
{
  CAFE_OperadorRegistroCampoTraducidoOperadorBasico             :
        Operador de relacion registro - campo
}

  CAFE_OperadorArregloIndiceTraducidoOperadorBasico          =
                                        CAFE_CharIgnoradoLibre+'V()';
{
  CAFE_OperadorArregloIndiceTraducidoOperadorBasico             :
        Operador para el indice del arreglo
}

  CAFE_OperadorConjuntoTraducidoOperadorBasico               =
                                        CAFE_CharIgnoradoLibre+'C()';
{
  CAFE_OperadorConjuntoTraducidoOperadorBasico                  :
        Operador para el tipo conjunto
}

  CAFE_SecuenciaOrdenadaTraducidoOperadorBasico              =
                                        CAFE_CharIgnoradoLibre+'SN()';
{
  CAFE_SecuenciaOrdenadaTraducidoOperadorBasico                 :
        Operador para la secuencia ordenada de elementos
}

  CAFE_OperadorApuntadorTraducidoOperadorBasico              =
                                        CAFE_CharIgnoradoLibre+'LA()';
{
  CAFE_OperadorApuntadorTraducidoOperadorBasico                 :
        Operador para el lugar senalado por un puntero MyPuntero^
}

  CAFE_OperadorJustificadorTipoWrite                         =
                                        CAFE_CharIgnoradoLibre+'JTW()';
{
  CAFE_OperadorJustificadorTipoWrite                            :
        Operador para descriptor : de la orden Write en pascal
        i.e. Write( Numero:8:4 )
}
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }

TYPE
  CAFE_TStringList              = TStringList;
{
  CAFE_TStringList              = Se declara asi por si en el futuro
        se sugiere alguna mejora para evitar el desperdicio
        por String inutiles
}

  CAFE_CadenaSintactica         = STRING[ CAFE_TamanoCadenaSintactica-1 ];
{
  CAFE_CadenaSintactica         : cadena de menor tamano para
        operadores predefinidos.  Podria cambiar de tamano
        en el futuro
}

  CAFE_VariantesRegistroTraductorSintactico                  =
        ( ActivoRTS                     , OperadorBinarioRTS            ,
          OperadorDerechoRTS            , OperadorIzquierdoRTS          ,
          SumaRestaRTS                  , ConfundibleIdentificadorRTS   ,
          ArregloIndiceRTS              , ArregloConjuntoRTS            ,
          RegistroDecimalConfundibleRTS , ProtegerRTS                   ,
          Variantes11RTS                , Variantes12RTS                ,
          Variantes13RTS                , Variantes14RTS                ,
          Variantes15RTS                , Variantes16RTS                ,
          Variantes17RTS                , Variantes18RTS                ,
          Variantes19RTS                , Variantes20RTS                ,
          Variantes21RTS                , Variantes22RTS                ,
          Variantes23RTS                , Variantes24RTS                ,
          Variantes25RTS                , Variantes26RTS                ,
          Variantes27RTS                , Variantes28RTS                ,
          Variantes29RTS                , Variantes30RTS                ,
          Variantes31RTS                , ExtendibleRTS                 );
{
  CAFE_VariantesRegistroTraductorSintactico     : tipo enumerado
        para describir a los operadores sintacticos
  ActivoRTS                     : on  -> el operador en lista esta activo
                                  off -> el operador en lista se ignora
  OperadorBinarioRTS            : on  -> operador con parametros a ambos
                                         lados.  i.e. Partido * 2.5E-3
  OperadorDerechoRTS            : on  -> operador con parametro a la
                                         derecha. i.e.  @MyDato
  OperadorIzquierdoRTS          : on  -> operador con parametro a la
                                         izquierda. i.e.  MyPuntero^
  SumaRestaRTS                  : on  -> para operadores + y -
  ConfundibleIdentificadorRTS   : on  -> puede confundirse con un
                                         nombre de identificador. i.e. AND
  ArregloIndiceRTS              : on  -> operador parentesis cuadrado
                                         de arreglo
  ArregloConjuntoRTS            : on  -> operador parentesis cuadrado
                                         de conjunto
  RegistroDecimalConfundibleRTS : on  -> se confunde el . decimal y el
                                         separador registro campo
  ProtegerRTS                   : on  -> en algunos algoritmos el
                                         operador podria requerir
                                         algun tipo de proteccion
                                         especial.  i.e. el :=
  Variantes11RTS..
  Variantes30RTS                : reservados
  ExtendibleRTS                 : on  -> para indicar una posible
                                         futura extension de cardinalidad
}

  CAFE_ConjuntoVariantesRegistroTraductorSintactico          =
                        SET OF CAFE_VariantesRegistroTraductorSintactico;
{
  CAFE_ConjuntoVariantesRegistroTraductorSintactico             :
        Conjunto para el tipo ordenado
        CAFE_VariantesRegistroTraductorSintactico
}

TYPE
  CAFE_PointerRegistroTraductorOperadorSintactico            =
                        ^CAFE_RegistroTraductorOperadorSintactico;
{
  CAFE_PointerRegistroTraductorOperadorSintactico               :
        Puntero al tipo CAFE_RegistroTraductorOperadorSintactico
}

  CAFE_RegistroTraductorOperadorSintactico                   = RECORD
{
  CAFE_RegistroTraductorOperadorSintactico                      :
        Es un registro para describir las caracteristicas
        del operador
}

        OperadorSimpleReconocido,
{
  OperadorSimpleReconocido      : es el operador en su version
        original antes de traducir a operadorsimple. i.e. +,*,/
}

        OperadorNuevoBasico             : CAFE_CadenaSintactica;
{
  OperadorNuevoBasico           : Es el operador en su version
        traducida a sintaxis de OpBas( param1, param2 )
}

        ConjuntoControlRegistroTraductor                :
                        CAFE_ConjuntoVariantesRegistroTraductorSintactico;
{
  ConjuntoControlRegistroTraductor                              :
        Es un conjunto control para los operadores, puede utilizar
        ActivoRTS para activar o inhabilitar un operador
}

                                                          END;
                { RECORD CAFE_RegistroTraductorOperadorSintactico }

CONST
  CAFE_SumaTraducidaOperadorBasico   = CAFE_CharIgnoradoLibre+'S()';
{
  CAFE_SumaTraducidaOperadorBasico                              :
        Es el operador correspondiente a la suma binaria
}

  CAFE_RestaTraducidaOperadorBasico  = CAFE_CharIgnoradoLibre+'R()';
{
  CAFE_RestaTraducidaOperadorBasico                             :
        Es el operador correspondiente a la resta binaria
}

  CAFE_MultiplicacionTraducidaOperadorBasico                 =
                                        CAFE_CharIgnoradoLibre+'M()';
{
  CAFE_MultiplicacionTraducidaOperadorBasico                    :
        Es el operador correspondiente a la multiplicacion binaria
}

  CAFE_DivisionTraducidaOperadorBasico                       =
                                        CAFE_CharIgnoradoLibre+'D()';
{
  CAFE_DivisionTraducidaOperadorBasico                          :
        Es el operador correspondiente a la division binaria
}

  CAFE_PositivoTraducidoOperadorBasico                       =
                                        CAFE_CharIgnoradoLibre+'P()';
{
  CAFE_PositivoTraducidoOperadorBasico                          :
        Es el operador correspondiente al signo para numero
        positivo cuando se requiera
}

  CAFE_NegativoTraducidoOperadorBasico                       =
                                        CAFE_CharIgnoradoLibre+'N()';
{
  CAFE_NegativoTraducidoOperadorBasico                          :
        Es el operador correspondiente al signo para numero
        negativo cuando se requiera
}

  CAFE_OperadorDireccionTraducidoOperadorBasico              =
                                        CAFE_CharIgnoradoLibre+'L()';
{
  CAFE_OperadorDireccionTraducidoOperadorBasico                 :
        Es el operador correspondiente a direccion @ en Pascal
}

  CAFE_IgualLogicoTraducidoOperadorBasico                    =
                                        CAFE_CharIgnoradoLibre+'I()';
{
  CAFE_IgualLogicoTraducidoOperadorBasico                       :
        Es el operador correspondiente a el igual logico con
        parametros boolean.
}

  CAFE_NoIgualLogicoTraducidoOperadorBasico                  =
                                        CAFE_CharIgnoradoLibre+'NI()';
{
  CAFE_NoIgualLogicoTraducidoOperadorBasico                     :
        Es el operador correspondiente a el no igual logico con
        parametros boolean.
}

  CAFE_MayorTraducidoOperadorBasico                          =
                                        CAFE_CharIgnoradoLibre+'G()';
{
  CAFE_MayorTraducidoOperadorBasico                             :
        Es el operador para > en comparaciones.
}

  CAFE_MenorTraducidoOperadorBasico                          =
                                        CAFE_CharIgnoradoLibre+'NGI()';
{
  CAFE_MenorTraducidoOperadorBasico                             :
        Es el operador para < en comparaciones.
}

  CAFE_MayorIgualTraducidoOperadorBasico                     =
                                        CAFE_CharIgnoradoLibre+'GI()';
{
  CAFE_MayorIgualTraducidoOperadorBasico                        :
        Es el operador para >= en comparaciones.
}

  CAFE_MenorIgualTraducidoOperadorBasico                     =
                                        CAFE_CharIgnoradoLibre+'NG()';
{
  CAFE_MenorIgualTraducidoOperadorBasico                        :
        Es el operador para <= en comparaciones.
}

  CAFE_CharMultiplicacionGeneral     = '*';
{
  CAFE_CharMultiplicacionGeneral        : es el caracter para multiplicacion
}

  CAFE_ByteMultiplicacionGeneral     = Ord( CAFE_CharMultiplicacionGeneral );
{
  CAFE_ByteMultiplicacionGeneral        : Byte correspondiente al
        CAFE_CharMultiplicacionGeneral
}

  CAFE_CharDivisionGeneral           = '/';
{
  CAFE_CharDivisionGeneral              : es el caracter para division
}

  CAFE_ByteDivisionGeneral           = Ord( CAFE_CharDivisionGeneral );
{
  CAFE_ByteDivisionGeneral              : Version
        Byte de CAFE_CharDivisionGeneral
}

  CAFE_CharAlternativoDivision       = 'ö';
{
  CAFE_CharAlternativoDivision       = Puede que algunos sistemas prefieran
        este simbolo
}

  CAFE_OperadorPotenciaDos           = 'ý';
{
  CAFE_OperadorPotenciaDos           = Para potencia cuadrada
}

  CAFE_TraducidoOperadorPotenciaDos  =
                        CAFE_CharIgnoradoLibre+'SQR()';
{
  CAFE_TraducidoOperadorPotenciaDos  = se transforma a un operador
        equivalente al SQR().
}

  CAFE_OperadorPotenciaTres          = 'ü';
{
  CAFE_OperadorPotenciaTres          = Para potencia cubica
}

  CAFE_TraducidoOperadorPotenciaTres =
                        CAFE_CharIgnoradoLibre+'CUBO()';
{
  CAFE_TraducidoOperadorPotenciaTres = Se transforma a un operador de cubo.
}

  CAFE_CharOperadorDireccionPascal   = '@';
{
  CAFE_CharOperadorDireccionPascal      : caracter para direccion en Pascal
}

  CAFE_ByteOperadorDireccionPascal   =
                        Ord( CAFE_CharOperadorDireccionPascal );
{
  CAFE_ByteOperadorDireccionPascal      : Version Byte de
        CAFE_CharOperadorDireccionPascal
}

  CAFE_NegacionBinariaPascal         = 'NOT';
{
  CAFE_NegacionBinariaPascal            : operador de negacion binaria
}

  CAFE_NegacionBinariaTraducidoOperadorBasico                =
           CAFE_CharIgnoradoLibre+CAFE_NegacionBinariaPascal+'()';
{
  CAFE_NegacionBinariaTraducidoOperadorBasico                   :
        Version operador de CAFE_NegacionBinariaPascal
}

  CAFE_IgualLogicoPascal             = '=';
{
  CAFE_IgualLogicoPascal                : operador de igualdad en
        comparacion boolean
}

  CAFE_NoIgualLogicoPascal           = '<>';
{
  CAFE_NoIgualLogicoPascal              : operador de no igualdad en
        comparacion boolean
}

  CAFE_MayorBinarioPascal            = '>';
{
  CAFE_MayorBinarioPascal               : operador de (mayor que) en Pascal
}

  CAFE_MenorBinarioPascal            = '<';
{
  CAFE_MenorBinarioPascal               : operador de (menor que) en Pascal
}

  CAFE_MayorIgualBinarioPascal       = '>=';
{
  CAFE_MayorIgualBinarioPascal          : operador de (mayor o igual que)
        en Pascal para comparaciones
}

  CAFE_MenorIgualBinarioPascal       = '<=';
{
  CAFE_MenorIgualBinarioPascal          : operador de (menor o igual que)
        en Pascal para comparaciones
}

  CAFE_ANDBinarioPascal              = 'AND';
{
  CAFE_ANDBinarioPascal                 : operador logico de conjuncion
}

  CAFE_ANDBinarioTraducidoOperadorBasico                     =
                        CAFE_CharIgnoradoLibre+CAFE_ANDBinarioPascal+'()';
{
  CAFE_ANDBinarioTraducidoOperadorBasico                        :
        Version operador basico para el AND logico
}

  CAFE_ORBinarioPascal               = 'OR';
{
  CAFE_ORBinarioPascal                  : operador de adicion logica booleana
}

  CAFE_ORBinarioTraducidoOperadorBasico                      =
                        CAFE_CharIgnoradoLibre+CAFE_ORBinarioPascal+'()';
{
  CAFE_ORBinarioTraducidoOperadorBasico : version operador basico
        del OR logico
}

  CAFE_XORBinarioPascal              = 'XOR';
{
  CAFE_XORBinarioPascal                 : operador de or exclusivo en Pascal
}

  CAFE_XORBinarioTraducidoOperadorBasico                     =
                        CAFE_CharIgnoradoLibre+CAFE_XORBinarioPascal+'()';
{
  CAFE_XORBinarioTraducidoOperadorBasico                        :
        operador XOR binario logico en Pascal
}

  CAFE_DIVAritmeticoPascal           = 'DIV';
{
  CAFE_DIVAritmeticoPascal              : operador de division entera
}

  CAFE_DIVAritmeticoTraducidoOperadorBasico                  =
                        CAFE_CharIgnoradoLibre+CAFE_DIVAritmeticoPascal+'()';
{
  CAFE_DIVAritmeticoTraducidoOperadorBasico                     :
        version operador basico del DIV entero
}

  CAFE_MODAritmeticoPascal           = 'MOD';
{
  CAFE_MODAritmeticoPascal              : operador de resto
        de division entera
}

  CAFE_MODAritmeticoTraducidoOperadorBasico                  =
                        CAFE_CharIgnoradoLibre+CAFE_MODAritmeticoPascal+'()';
{
  CAFE_MODAritmeticoTraducidoOperadorBasico                     :
        version operador basico del MOD resto de division entera.
}

  CAFE_SHLBinarioPascal              = 'SHL';
{
  CAFE_SHLBinarioPascal                 : operador SHL binario
}

  CAFE_SHLBinarioTraducidoOperadorBasico                     =
                        CAFE_CharIgnoradoLibre+CAFE_SHLBinarioPascal+'()';
{
  CAFE_SHLBinarioTraducidoOperadorBasico                        :
        version operador basico del SHL en Pascal
}

  CAFE_SHRBinarioPascal              = 'SHR';
{
  CAFE_SHRBinarioPascal                 : operador SHR binario
}

  CAFE_SHRBinarioTraducidoOperadorBasico                     =
                        CAFE_CharIgnoradoLibre+CAFE_SHRBinarioPascal+'()';
{
  CAFE_SHRBinarioTraducidoOperadorBasico                        :
        version operador basico del SHR en Pascal
}

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  CAFE_INConjuntoPascal              = 'IN'
                                        unimplemented;
{
  CAFE_INConjuntoPascal                 : operador IN de conjunto en Pascal
}

  CAFE_INConjuntoTraducidoOperadorBasico                     =
                        CAFE_CharIgnoradoLibre+CAFE_INConjuntoPascal+'()';
{
  CAFE_INConjuntoTraducidoOperadorBasico                        :
        version operador basico del IN en Pascal
}

  CAFE_ASClasePascal                 = 'AS'
                                        unimplemented;
{
  CAFE_ASClasePascal                    : operador AS de conjunto en Pascal
}

  CAFE_ASClaseTraducidoOperadorBasico                        =
                        CAFE_CharIgnoradoLibre+CAFE_ASClasePascal+'()';
{
  CAFE_ASClaseTraducidoOperadorBasico   : version operador basico
        del AS para clases en FreePascal
}

  CAFE_ISClasePascal                 = 'IS'
                                        unimplemented;
{
  CAFE_ISClaseTraducidoOperadorBasico   : operador IS de conjunto en Pascal
}

  CAFE_ISClaseTraducidoOperadorBasico                        =
                        CAFE_CharIgnoradoLibre+CAFE_ISClasePascal+'()';
{
  GMEG_ISClaseTraducidoOperadorBasico   : version operador basico del
        IS para clases en FreePascal
}

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
  CAFE_OperadorPower                 = '**';
{
  CAFE_OperadorPower                    : Para operacion de potencia
        similar a la unidad Math de FreePascal
}

  CAFE_TraducidoOperadorPower        =
                        CAFE_CharIgnoradoLibre+'POWER()';
{
  CAFE_TraducidoOperadorPower           : Version operador basico
        de la potencia.
        NOTA: En CAFE_EJ4, tambien se reconoce la
        version sin CAFE_CharIgnoradoLibre para hoja de calculo
}

  CAFE_OperadorFactorial             = '!';
{
  CAFE_OperadorFactorial                : operador factorial
}

  CAFE_TraducidoOperadorFactorial    =
                        CAFE_CharIgnoradoLibre+'FACTORIAL()';
{
  CAFE_TraducidoOperadorFactorial       : versio operador basico,
        NOTA: En CAFE_Ej4, tambien se reconoce la
        version sin CAFE_CharIgnoradoLibre para hoja de calculo
}

CONST
  CAFE_MaximoOperadorMismaPrioridad  = 20;
{
  CAFE_MaximoOperadorMismaPrioridad     : maximo previsto por
        economias de memoria, para operadores a un
        mismo nivel de prioridad en el proceso de
        traduccion a operador basico
}

TYPE
  CAFE_PointerArrayRegistroTraductorOperadorSintactico       =
                        ^CAFE_ArrayRegistroTraductorOperadorSintactico;
{
  CAFE_PointerArrayRegistroTraductorOperadorSintactico          :
        puntero al tipo ArrayRegistroTraductorOperadorSintactico
}

  CAFE_ArrayRegistroTraductorOperadorSintactico              =
                        ARRAY [ 1..CAFE_MaximoOperadorMismaPrioridad ] OF
                           CAFE_RegistroTraductorOperadorSintactico;
{
  CAFE_ArrayRegistroTraductorOperadorSintactico                 :
        Tipo arreglo para mismo nivel de prioridad de operadores
}

CONST
  CAFE_MaximoIndiceArregloPrimerNivelOperadorPascal          = 5;
{
  CAFE_MaximoIndiceArregloPrimerNivelOperadorPascal             :
        total de elementos del Primer nivel de prioridad
        de operadores Pascal
}

  CAFE_ArregloPrimerNivelOperadorPascal                      :
        ARRAY [ 1..CAFE_MaximoIndiceArregloPrimerNivelOperadorPascal ] OF
                CAFE_RegistroTraductorOperadorSintactico     =
        ( ( OperadorSimpleReconocido                    :
                                        CAFE_CharOperadorDireccionPascal;
            OperadorNuevoBasico                         :
                                CAFE_OperadorDireccionTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorDerechoRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_NegacionBinariaPascal;
            OperadorNuevoBasico                         :
                                CAFE_NegacionBinariaTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorDerechoRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_OperadorPotenciaDos;
            OperadorNuevoBasico                         :
                                CAFE_TraducidoOperadorPotenciaDos;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorIzquierdoRTS ]     ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_OperadorPotenciaTres;
            OperadorNuevoBasico                         :
                                CAFE_TraducidoOperadorPotenciaTres;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorIzquierdoRTS ]     ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_OperadorFactorial;
            OperadorNuevoBasico                         :
                                CAFE_TraducidoOperadorFactorial;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorIzquierdoRTS ]     ) );
{
  CAFE_ArregloPrimerNivelOperadorPascal         :
        Contiene informacion del primer nivel de prioridad
        de operadores Pascal
}

CONST
  CAFE_MaximoIndiceArregloSegundoNivelOperadorPascal         = 10;
{
  CAFE_MaximoIndiceArregloSegundoNivelOperadorPascal            :
        total de elementos del Segundo nivel de prioridad
        de operadores Pascal
}

  CAFE_ArregloSegundoNivelOperadorPascal                     :
        ARRAY [ 1..CAFE_MaximoIndiceArregloSegundoNivelOperadorPascal ] OF
                CAFE_RegistroTraductorOperadorSintactico     =
        ( ( OperadorSimpleReconocido                    :
                                        CAFE_OperadorPower;
            OperadorNuevoBasico                         :
                                CAFE_TraducidoOperadorPower;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_CharMultiplicacionGeneral;
            OperadorNuevoBasico                         :
                                CAFE_MultiplicacionTraducidaOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_CharDivisionGeneral;
            OperadorNuevoBasico                         :
                                CAFE_DivisionTraducidaOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_CharAlternativoDivision;
            OperadorNuevoBasico                         :
                                CAFE_DivisionTraducidaOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_DIVAritmeticoPascal;
            OperadorNuevoBasico                         :
                                CAFE_DIVAritmeticoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_MODAritmeticoPascal;
            OperadorNuevoBasico                         :
                                CAFE_MODAritmeticoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_ANDBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_ANDBinarioTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_SHLBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_SHLBinarioTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_SHRBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_SHRBinarioTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
          ( OperadorSimpleReconocido                    :
                                        CAFE_ASClasePascal;
            OperadorNuevoBasico                         :
                                CAFE_ASClaseTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ) );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
{
  CAFE_ArregloSegundoNivelOperadorPascal                        :
        Contiene informacion del segundo nivel de prioridad
        de operadores Pascal
}

CONST
  CAFE_MaximoIndiceArregloTercerNivelOperadorPascal          = 6;
{
  CAFE_MaximoIndiceArregloTercerNivelOperadorPascal             :
        total de elementos del Tercer nivel de prioridad
        de operadores Pascal
}

  CAFE_ArregloTercerNivelOperadorPascal                      :
        ARRAY [ 1..CAFE_MaximoIndiceArregloTercerNivelOperadorPascal ] OF
                CAFE_RegistroTraductorOperadorSintactico     =
        ( ( OperadorSimpleReconocido                    :
                                        CAFE_CharPositivoNumerico;
            OperadorNuevoBasico                         :
                                CAFE_SumaTraducidaOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, SumaRestaRTS ]             ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_CharPositivoNumerico;
            OperadorNuevoBasico                         :
                                CAFE_PositivoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, SumaRestaRTS ]             ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_CharNegativoNumerico;
            OperadorNuevoBasico                         :
                                CAFE_RestaTraducidaOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, SumaRestaRTS ]             ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_CharNegativoNumerico;
            OperadorNuevoBasico                         :
                                CAFE_NegativoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, SumaRestaRTS ]             ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_ORBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_ORBinarioTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_XORBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_XORBinarioTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ) );
{
  CAFE_ArregloTercerNivelOperadorPascal                         :
        Contiene informacion del tercer nivel de prioridad
        de operadores Pascal
}

CONST
  CAFE_MaximoIndiceArregloCuartoNivelOperadorPascal          = 9;
{
  CAFE_MaximoIndiceArregloCuartoNivelOperadorPascal             :
        total de elementos del Cuarto nivel de prioridad
        de operadores Pascal
}

  CAFE_ArregloCuartoNivelOperadorPascal                      :
        ARRAY [ 1..CAFE_MaximoIndiceArregloCuartoNivelOperadorPascal ] OF
                CAFE_RegistroTraductorOperadorSintactico     =
        ( ( OperadorSimpleReconocido                    :
                                        CAFE_IgualLogicoPascal;
            OperadorNuevoBasico                         :
                                CAFE_IgualLogicoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_NoIgualLogicoPascal;
            OperadorNuevoBasico                         :
                                CAFE_NoIgualLogicoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_MayorBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_MayorTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_MenorBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_MenorTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_MayorIgualBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_MayorIgualTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_MenorIgualBinarioPascal;
            OperadorNuevoBasico                         :
                                CAFE_MenorIgualTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
          ( OperadorSimpleReconocido                    :
                                        CAFE_INConjuntoPascal;
            OperadorNuevoBasico                         :
                                CAFE_INConjuntoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_ISClasePascal;
            OperadorNuevoBasico                         :
                                CAFE_ISClaseTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, ConfundibleIdentificadorRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_AsignacionBasicaPascal;
            OperadorNuevoBasico                         : '';
            ConjuntoControlRegistroTraductor            :
                                        [ ActivoRTS, ProtegerRTS ]      ) );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
{
  CAFE_ArregloCuartoNivelOperadorPascal                         :
        Contiene informacion del cuarto nivel de prioridad
        de operadores Pascal
}

TYPE
  CAFE_PointerRegistroNivelOperador  = ^CAFE_RegistroNivelOperador;
{
  CAFE_PointerRegistroNivelOperador     : puntero al
        CAFE_RegistroNivelOperador
}

  CAFE_RegistroNivelOperador         = RECORD
{
  CAFE_RegistroNivelOperador            : Registro para contener
        la informacion de operadores pascal por nivel de prioridad
}

        TotalOperadoresNivel    : LongInt;
{
  TotalOperadoresNivel                  : Se interpreta como
        un tamano de matriz, no como datos activos
}

        PunteroArregloOperador  :
                        CAFE_PointerArrayRegistroTraductorOperadorSintactico;
{
  PunteroArregloOperador                : Puntero al arreglo
        que contiene la lista de operadores y su descripcion
        El tamano no concuerda seguramente.  Simplemente
        son utiles TotalOperadoresNivel
}

                                  END;
                                  { RECORD CAFE_RegistroNivelOperador }

CONST
  CAFE_MaximoNivelHipoteticoPrecedencia                      = 10;
{
  CAFE_MaximoNivelHipoteticoPrecedencia : valor hipotetico
        para un maximo de niveles de precedencia, para un lenguaje
        accesible por la unidad
}

TYPE
  CAFE_PointerArrayRegistroNivelOperador                     =
                                        ^CAFE_ArrayRegistroNivelOperador;
{
  CAFE_PointerArrayRegistroNivelOperador                :
        puntero al tipo CAFE_ArrayRegistroNivelOperador
}

  CAFE_ArrayRegistroNivelOperador    =
                ARRAY [ 1..CAFE_MaximoNivelHipoteticoPrecedencia ] OF
                                                CAFE_RegistroNivelOperador;
{
  CAFE_ArrayRegistroNivelOperador                       :
        Arreglo para contener los diferentes niveles de precedencia
        del lenguaje o interprete utilizado
}

TYPE
  CAFE_PointerRegistroPrecedenciaOperadorSintactico          =
                        ^CAFE_RegistroPrecedenciaOperadorSintactico;
{
  CAFE_PointerRegistroPrecedenciaOperadorSintactico     :
        Puntero al tipo CAFE_RegistroPrecedenciaOperadorSintactico
}

  CAFE_RegistroPrecedenciaOperadorSintactico                 = RECORD
{
  CAFE_RegistroPrecedenciaOperadorSintactico            :
        Registro para contener un paquete completo de niveles
        de precedencia de operadores a utilzar
        en la traduccion de una orden sintactica
}

        TotalNivelesPrecedencia,
{
  TotalNivelesPrecedencia       : total verdadero de niveles
        de precedencia a considerar, no necesita concordar con el maximo
}

        NivelPrecedenciaSumaResta,
{
  NivelPrecedenciaSumaResta     : si aplica indica el nivel
        que se encarga de los operadores suma y resta.
        Es importante destacarlo pues afecta la interpretacion
        de numeros en notacion cientifica, etc...
}

        UbicacionSumaBinariaRegistroTraductor,
{
  UbicacionSumaBinariaRegistroTraductor         :
        Para ubicar la suma binaria en el nivel respectivo
        cuando aplique
}

        UbicacionSumaUnariaRegistroTraductor,
{
  UbicacionSumaUnariaRegistroTraductor          :
        Para ubicar la suma unaria en el nivel respectivo cuando aplique
}

        UbicacionRestaBinariaRegistroTraductor,
{
  UbicacionRestaBinariaRegistroTraductor        :
        Para ubicar la resta binaria en el nivel respectivo
        cuando aplique
}

        UbicacionRestaUnariaRegistroTraductor           : Word;
{
  UbicacionRestaUnariaRegistroTraductor         :
        Para ubicar la resta unaria en el nivel respectivo cuando aplique
}

        NivelPrecedenciaArregloIndice,
{
  NivelPrecedenciaArregloIndice                 :
        Cuando aplique indica la ubicacion de nivel para
        el operador de indices en arreglo
}

        UbicacionParentesisAbrirArregloIndice,
{
  UbicacionParentesisAbrirArregloIndice         :
        Cuando aplique ubica en el nivel la posicion
        del parentesis abrir para arreglos indice
}

        UbicacionParentesisCerrarArregloIndice,
{
  UbicacionParentesisCerrarArregloIndice        :
        Cuando aplique ubica en el nivel la posicion
        del parentesis cerrar para arreglos indice
}

        UbicacionConjuntoOperadorRegistroTraductor      : Word;
{
  UbicacionConjuntoOperadorRegistroTraductor    :
        Cuando aplique ubica en el mismo nivel que
        el parentesis de arreglo, el parentesis de conjunto
        NOTA: Concuerdan en pascal su simbolo
}

        PunteroArregloRegistroNivel                     :
                                CAFE_PointerArrayRegistroNivelOperador;
{
  PunteroArregloRegistroNivel                   :
        Como puntero se¤ala a un arreglo de niveles, no
        es en realidad de tamano maximo, si no de
        TotalNivelesPrecedencia
}

                                                          END;
      { RECORD CAFE_RegistroPrecedenciaOperadorSintactico }

CONST
  CAFE_MaximoNivelPrecedenciaPascal  = 4;
{
  CAFE_MaximoNivelPrecedenciaPascal                     :
        Se refiere a los niveles de precedencia a aplicar en Pascal
}

  CAFE_ArregloRegistroNivelOperadorPascal                    :
    ARRAY [ 1..CAFE_MaximoNivelPrecedenciaPascal ] OF
        CAFE_RegistroNivelOperador  =
        ( ( TotalOperadoresNivel                        :
                        CAFE_MaximoIndiceArregloPrimerNivelOperadorPascal;
            PunteroArregloOperador                      :
              Pointer( @CAFE_ArregloPrimerNivelOperadorPascal )    ),
          ( TotalOperadoresNivel                        :
                        CAFE_MaximoIndiceArregloSegundoNivelOperadorPascal;
            PunteroArregloOperador                      :
              Pointer( @CAFE_ArregloSegundoNivelOperadorPascal )   ),
          ( TotalOperadoresNivel                        :
                        CAFE_MaximoIndiceArregloTercerNivelOperadorPascal;
            PunteroArregloOperador                      :
              Pointer( @CAFE_ArregloTercerNivelOperadorPascal )    ),
          ( TotalOperadoresNivel                        :
                        CAFE_MaximoIndiceArregloCuartoNivelOperadorPascal;
            PunteroArregloOperador                      :
              Pointer( @CAFE_ArregloCuartoNivelOperadorPascal )    ) );
{
  CAFE_ArregloRegistroNivelOperadorPascal               :
        Arreglo de direcciones para cada nivel de precedencia en Pascal
}

  CAFE_RegistroPrecedenciaOperadorSintacticoPascal           :
                        CAFE_RegistroPrecedenciaOperadorSintactico           =
        ( TotalNivelesPrecedencia                       :
                                CAFE_MaximoNivelPrecedenciaPascal;
          NivelPrecedenciaSumaResta                     : 3;
          UbicacionSumaBinariaRegistroTraductor         : 1;
          UbicacionSumaUnariaRegistroTraductor          : 2;
          UbicacionRestaBinariaRegistroTraductor        : 3;
          UbicacionRestaUnariaRegistroTraductor         : 4;
          NivelPrecedenciaArregloIndice                 : 0;
          UbicacionParentesisAbrirArregloIndice         : 0;
          UbicacionParentesisCerrarArregloIndice        : 0;
          UbicacionConjuntoOperadorRegistroTraductor    : 0;
          PunteroArregloRegistroNivel                   :
            Pointer( @CAFE_ArregloRegistroNivelOperadorPascal )  );
{
  CAFE_RegistroPrecedenciaOperadorSintacticoPascal      :
        Registro para el conteo de niveles de precedencia en Pascal
}

CONST
  CAFE_MaximoIndiceDescriptorIdentificadorOperadorPascal     = 6;
  CAFE_ArregloDescriptorIdentificadorOperadorPascal          :
        ARRAY [ 1..CAFE_MaximoIndiceDescriptorIdentificadorOperadorPascal ] OF
                CAFE_RegistroTraductorOperadorSintactico     =
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
        ( ( OperadorSimpleReconocido                    :
                                        CAFE_MemoriaApuntadaPascal;
            OperadorNuevoBasico                         :
                                CAFE_OperadorApuntadorTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorIzquierdoRTS ]     ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_RegistroCampoPascal;
            OperadorNuevoBasico                         :
              CAFE_OperadorRegistroCampoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                OperadorBinarioRTS, RegistroDecimalConfundibleRTS ]     ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_SecuenciaNumeradaOrdenadaPascal;
            OperadorNuevoBasico                         :
                                CAFE_SecuenciaOrdenadaTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ),
          ( OperadorSimpleReconocido                    :
                                CAFE_CharParentesisAbrirArregloIndicePascal;
            OperadorNuevoBasico                         :
                                CAFE_OperadorArregloIndiceTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                                ArregloIndiceRTS, ArregloConjuntoRTS ]  ),
          ( OperadorSimpleReconocido                    :
                                CAFE_CharParentesisCerrarArregloIndicePascal;
            OperadorNuevoBasico                         :
                                CAFE_OperadorConjuntoTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            : [ ActivoRTS,
                                ArregloIndiceRTS, ArregloConjuntoRTS ]  ),
          ( OperadorSimpleReconocido                    :
                                        CAFE_SecuenciaRectangularHoja;
            OperadorNuevoBasico                         :
                CAFE_SecuenciaRectangularHojaTraducidoOperadorBasico;
            ConjuntoControlRegistroTraductor            :
                                [ ActivoRTS, OperadorBinarioRTS ]       ) );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }

CONST
  CAFE_MaximoNivelPrecedenciaDescriptorIdentificadorPascal   = 1;
{
  CAFE_MaximoNivelPrecedenciaDescriptorIdentificadorPascal      :
        Niveles para especificadores de identificador como
        Tipo registro, indice de arreglo, etc...
}

  CAFE_ArregloRegistroNivelDescriptorIdentificadorPascal     :
    ARRAY [ 1..CAFE_MaximoNivelPrecedenciaDescriptorIdentificadorPascal ] OF
                        CAFE_RegistroNivelOperador           =
        ( ( TotalOperadoresNivel                        :
              CAFE_MaximoIndiceDescriptorIdentificadorOperadorPascal;
            PunteroArregloOperador                      :
        Pointer( @CAFE_ArregloDescriptorIdentificadorOperadorPascal ) ) );
{
  CAFE_ArregloRegistroNivelDescriptorIdentificadorPascal        :
        Niveles (solo uno) para los descriptores de identificadores
        en Pascal
}

  CAFE_RegistroPrecedenciaDescriptorIdentificadorPascal      :
                        CAFE_RegistroPrecedenciaOperadorSintactico           =
        ( TotalNivelesPrecedencia                       :
            CAFE_MaximoNivelPrecedenciaDescriptorIdentificadorPascal;
          NivelPrecedenciaSumaResta                     : 0;
          UbicacionSumaBinariaRegistroTraductor         : 0;
          UbicacionSumaUnariaRegistroTraductor          : 0;
          UbicacionRestaBinariaRegistroTraductor        : 0;
          UbicacionRestaUnariaRegistroTraductor         : 0;
          NivelPrecedenciaArregloIndice                 : 1;
          UbicacionParentesisAbrirArregloIndice         : 4;
          UbicacionParentesisCerrarArregloIndice        : 5;
          UbicacionConjuntoOperadorRegistroTraductor    : 5;
          PunteroArregloRegistroNivel                   :
    Pointer( @CAFE_ArregloRegistroNivelDescriptorIdentificadorPascal )  );
{
  CAFE_RegistroPrecedenciaDescriptorIdentificadorPascal         :
        Contiene el registro a aplicar para los descriptores de
        identificadores en Pascal
}

VAR
  CAFE_ConjuntoConfundibleIdentificadorSintactico : CAFE_ConjuntoByte;
{
  CAFE_ConjuntoConfundibleIdentificadorSintactico               :
        Para indicar aquellos caracteres que podrian provocar
        confusion al identificar simultaneamente operadores e
        identificadores. i.e. AND.
}

  CAFE_ComentarioIzquierda1Sintactico,
{
  CAFE_ComentarioIzquierda1Sintactico                           :
        Apertura de comentario 1 Sintactico.
}

  CAFE_ComentarioIzquierda2Sintactico,
{
  CAFE_ComentarioIzquierda2Sintactico                           :
        Apertura de comentario 2 Sintactico.
}

  CAFE_ComentarioIzquierda3Sintactico,
{
  CAFE_ComentarioIzquierda3Sintactico                           :
        Apertura de comentario 3 Sintactico.
}

  CAFE_ComentarioDerecha1Sintactico,
{
  CAFE_ComentarioDerecha1Sintactico                             :
        Cierre de comentario 1 Sintactico
}

  CAFE_ComentarioDerecha2Sintactico,
{
  CAFE_ComentarioDerecha2Sintactico                             :
        Cierre de comentario 2 Sintactico
}

  CAFE_ComentarioDerecha3Sintactico               : CAFE_CadenaSintactica;
{
  CAFE_ComentarioDerecha3Sintactico                             :
        Cierre de comentario 3 Sintactico
}

  CAFE_UltimoIdentificadorStringSintactico,
{
  CAFE_UltimoIdentificadorStringSintactico                      :
        Los String se almacenan en listas de String, se numeran
        con un numero secuencial.  Este es el ultimo numero
        secuencial asignado
}

  CAFE_IncrementoIdentificadorStringSintactico    : LongInt;
{
  CAFE_IncrementoIdentificadorStringSintactico                  :
        Los String se almacenen en listas de String, se numeran
        con un numero secuenical.  Self es la separacion
        entre numero y numero en la secuencia.
        Debido a la implementation de
                CAFE_AgregarNumeradoString
        en CAFE_Ej4, esto numero deberia ser la unidad,
        para evitar dificultades.
        Esto es un defecto, que esperamos se corrija en el futuro
}

  CAFE_ByteStringSintactico                       : Byte;
{
  CAFE_ByteStringSintactico     : Es el byte de String para efectos
        finales de analisis sintactica.
}

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  CAFE_BanderaEnmascararStringSintactico          : Boolean
                                                  unimplemented;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
{
  CAFE_BanderaEnmascararStringSintactico                :
       Su objetivo es ahorrar tiempo, pues es bastante probable
       un lenguaje sin String, en donde no haga falta perder
       el tiempo con el enmascarado de String.
}

CONST
  CAFE_3ErrorSintaxisAsignacionGeneral          : LongInt               = 1;
{
  CAFE_3ErrorSintaxisAsignacionGeneral          :
        Fallo en la sintaxis del operador asignacion de tipo general
}

  CAFE_3ErrorSintaxisJustificadoresWrite        : LongInt               = 1;
{
  CAFE_3ErrorSintaxisJustificadoresWrite        :
        Fallo en la sintaxis de justificadores para ordenes Write Pascal
        o similar
}

type
  CAFE_CharByte2Sintactico      = Packed CLASS ( CAFE_CharByteSintactico )
{
  Clase evolucion de CAFE_CharByteSintactico, permitiendo ahora
  analisis sintactico de diferentes operadores
  y la descomposicion sin interpretacion de un renglon Pascal Standard
  aunque con algunas excepciones
  Carece de bloques estructurados
}

  Public
  // Actualizar siempre
CONSTRUCTOR Create
  (     Tamano          : LongInt                               ); override;
{
  Inicializa el CharByte para su buen funcionamiento,
  pero completamente vacio.
  Tamano es el nuevo TamanoVector. (no compatible FreeMem)
}

  // Actualizar siempre
CONSTRUCTOR Create
  ( CONST
        Msg             : ShortString;
        Tamano          : LongInt                               ); override;
{
  Inicializar el CharByte para su buen funcionamiento,
  con Msg como datos iniciales. No importa, utilizar Tamano "muy grande".
  Msg podria ser ''.
}

  // Actualizar siempre
CONSTRUCTOR Create
  (     Modelo          : CAFE_ClassCharByte                    ); override;
{
  Inicializa el CharByte, copiando completamente el dato
  CharByte de modelo, incluyendo su TamanoVector.
  No asigna el mismo nivel de clase.
}

DESTRUCTOR  Destroy; override;
{
  DESTRUCTOR Destroy;
        Se produce la destruccion del CharByte.
}

FUNCTION    ExtraccionByteDuplicadoString
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual : LongInt; VAR PosicionFinal     : LongInt;
        ByteDuplicado           : Byte;
        AdmisibleCharByte       : Boolean                       ) : Boolean;
{
  FUNCTION ExtraccionByteDuplicadoString
        A partir de PosicionActual no incluida, se busca el
        siguiente grupo de comillas tipo ByteDuplicado para String o similar.
        Se extrae la informacion en Self.
  VectorFuente                  : Contiene la informacion a analizar
  PosicionActual                : Admisible 0 para busqueda total.
        A partir de PosicionActual no incluida, se busca el
        siguiente grupo de ByteDuplicado (si en PosicionActual hay
        un elemento de grupo, el grupo completo se ignora).
        De salida la posicion inicial de dicho grupo, o 0 si no encuentra.
  PosicionFinal                 : -> PosicionFinal del String o similar
        por la regla ByteDuplicado.
  ByteDuplicado                 : Byte delimitador, con la regla
        de Byte duplicado en el interior.
  AdmisibleCharByte             : TRUE no limite de tamano,
                                        excepto Self.TamanoVector
                                  FALSE limitado por capacidad de ShortString
  FUNCTION ExtraccionByteDuplicadoString        : TRUE si exito
        o no encontro nada.  FALSE si fracaso o error.
        No encontro nada devolveria PosicionActual <> 0, y
        String Null seria PosicionActual <> 0 y Self.Ocupado = 0.
        En Self se devuelve el String extraido y simplificado de
        comillas.
}

FUNCTION    ExtraccionSustitucionByteDuplicadoString
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual          : LongInt;
        AdmisibleCharByte       : Boolean;
        Lista                   : CAFE_TStringList      = NIL   ) : Boolean;
{
  FUNCTION ExtraccionSustitucionByteDuplicadoString
        Busca el primer String a partir de PosicionActual no incluida.
        Lo extrae en Self, que se borra al inicio de FUNCTION;
        y VectorFuente sustituye la cadena con las siguientes posibilidades
        * CAFE_IdentificadorStringNull
        * CHR(BYTE)
        * OperadorString(NumeroSecuencial)
        El Numero Secuencial asignado se obtiene de
        la variable Global,
                CAFE_UltimoIdentificadorStringSintactico
        que se espera unico, pues FUNCTION aplica la instruccion
        Inc( CAFE_UltimoIdentificadorStringSintactico,
                  CAFE_IncrementoIdentificadorStringSintactico );
        antes de generar la sustitucion.
        ADVERTENCIA : Self contiene el String con comillas simplificadas,
        corresponde al tratamiento posterior, disponer de alguna
        manera de ese String o se perdera.
  VectorFuente                  : Contiene la informacion a analizar.
  PosicionActual                : Admisible 0 para busqueda total.
        A partir de PosicionActual no incluida, se busca el
        siguiente grupo de ByteDuplicado (si en PosicionActual hay
        un elemento de grupo, el grupo completo se ignora).
        De salida la posicion inicial de dicho grupo, o 0 si no encuentra.
  AdmisibleCharByte             : TRUE no limite de tamano,
                                        excepto Self.TamanoVector
                                  FALSE limitado por capacidad de ShortString
  FUNCTION ExtraccionSustitucionByteDuplicadoString             :
        Devuelve TRUE si encuentra String y lo sustituye con exito,
        FALSE cuando no encuentra el String.
        Puede usar Self.Ocupado para determinar si fue Null, Chr, u
        OperadorString (CAFE_OperadorStringTraducidoOperadorBasico)
}

FUNCTION    ReescribirAsignacionOperadorSintactico
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual          : LongInt;
        OperadorAsignacion, OperadorTraducido   : CAFE_CadenaSintactica;
        BanderaOperadorParentesis               : Boolean       ) : Boolean;
{
  FUNCTION ReescribirAsignacionOperadorSintactico
        A partir de PosicionActual se busca la siguiente aparicion
        del OperadorAsignacion y se sustituye
        por OperadorTraducido como operador basico
        Por que existe FUNCTION?
        Veamos el siguiente ejemplo
        i.e.
        CABALLO = (1,2,3)
        se traduce por
        CASE BanderaOperadorParentesis
        TRUE  -> OperadorTraducido(CABALLO,OperadorParentesis(1,2,3))
        FALSE -> OperadorTraducido(CABALLO,(1,2,3))
        Pero el Arbol sintactico en el caso FALSE
        generado sera el mismo que generaria
                 OperadorTraducido(CABALLO,1,2,3)
        por diseno interno de
        CAFE_NudoSintactico.GenerarArbolSintacticoBasico.
        Aunque EJES.EXE utiliza en general TRUE,
        se tiene como alternativa la regla FALSE.
        El Operador Parentesis se inducira si existe en realidad
        un parentesis suelto, como la asignacion directa.
        No generan operador parentesis CABALLO := 3 o CABALLO := Sin(0).
        El programa podria estudiar la descendencia del
        OperadorParentesis para determinar si se trata o no
        de un parentesis redundante.
        i.e.
        CABALLO := (1)
        -> OperadorTraducido(CABALLO,OperadorParentesis(1))
  VectorFuente                  : Contiene la informacion a analizar
  PosicionActual                : Posicion inicial no elegible
        de busqueda del operador de asignacion, i.e. :,:=,=
        OUTPUT -> Posicion inicial de sustitucion
                  con seguridad antes de la posicion
                  inicial del operador asignacion,
                  ahora sustituido
  OperadorAsignacion            : Se refiere al operador de asignacion.
  OperadorTraducido             : Se refiere al operador basico,
        que sustituye al operador de asignacion.
  BanderaOperadorTraducido      : ( Ver arriba )
        TRUE  -> induce un OperadorBasico de parentesis si cree conveniente
        FALSE -> no induce Operador Parentesis
  FUNCTION ReescribirAsignacionOperadorSintactico               :
        TRUE si se encontro una asignacion, FALSE si no se encontro
}

PROCEDURE   ReescribirJustificadorTipoWritePascal
  (     VectorFuente            : CAFE_ClassCharByte;
        OperadorTipoWrite       : CAFE_CadenaSintactica                 );
{
  PROCEDURE ReescribirJustificadorTipoWritePascal
        Su objetivo es manejar el : para instrucciones Write.
        Se sustituye por CAFE_OperadorJustificadorTipoWrite
  VectorFuente                  : Contiene la informacion a ser procesada
  OperadorTipoWrite             : Se refiere al operador de cadenas
        como Write(), WriteLn(), Str(), debe contener el parentesis.
  NOTA: PROCEDURE podria tener dificultades con : por otros usos
        dentro del Write.  Eso probablemente no sea posible
        en Pascal Standard. Pero en otros lenguajes podria ocurrir.
        No hay interferencia, si el : se encuentra en un segundo
        nivel de anidamiento
        i.e. WriteLn( sum( A1:A5 ):8:4 ) --> sin problemas
                        dos operadores de formato
        i.e. WriteLn( [ A1:A5 ]:8:4 )    --> error
                        solo hay dos operadores de formato
                        pero el programa supone tres
        EJES.EXE no reconoce los operadores WriteLn, Write, ni Str
        en su primera version.  Ni existe el operador [ A1:A5 ]
        en dicha version.
}

FUNCTION    BuscarSiguienteIdentificador
  ( VAR PosicionActual          : LongInt;
    CONST
        Cadena                  : ShortString;
        Direccion              : Boolean                       ) : Boolean;
{
  FUNCTION BuscarSiguienteIdentificador
        En esta busqueda FUNCTION se cerciora que no existan
        caracteres confundibles en la vecindad del identificador
        i.e. TRUE AND FALSE  -->  (TRUE para  AND)
             MANDEL          -->  (FALSE para AND)
        Por lo demas es casi identica a BuscarSiguienteCadena.
        Caracteres confundibles son aquellos que podrian formar parte
        del nombre de un identificador.
        Ademas se impide el uso de parentesis a la izquierda,
        en contacto con el identificador; aunque podrian estar no
        en contacto
        i.e. TRUE AND (FALSE) --> (TRUE para AND )
        i.e. TRUE AND(FALSE)  --> (FALSE para AND) CUIDADO!!!
        Esto debido a que probablemente se trate de un OperadorBasico
        CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible
        podria utilizarse para corregir este problema
  PosicionActual         : Posicion inicial no elegible de busqueda
                OUTPUT -> Posicion encontrada o 0 si no encuentra
  Cadena                 : String que se esta buscando.  No necesita
        que sea en realidad un identificador.  Se revisa meramente
        la vecindad.  No se impuso la condicion de identificador
        entre otras razones para permitir busqueda de cadenas
        con marcadores como CAFE_CharImposible0, etc.
  Direccion              : TRUE  busqueda hacia la derecha
                           FALSE busqueda hacia la izquierda
  FUNCTION BuscarSiguienteIdentificador         : TRUE  si se encontro
                                                  FALSE no se encontro
}

FUNCTION    BuscarSiguienteIdentificadorEnmascarado
  ( VAR PosicionActual          : LongInt;
    CONST
        Cadena                  : ShortString;
        ByteDuplicado           : Byte                          ) : Boolean;
{
  FUNCTION BuscarSiguienteIdentificadorEnmascarado
        En ocasiones puede ser util, realizar la busqueda de identificador
        enmascarada.  Es decir, con String o equivalente presente
        Por lo demas es identico a BuscarSiguienteIdentificador excepto
        que solo permite busqueda hacia la derecha
  PosicionActual         : Posicion inicial no elegible de busqueda
                OUTPUT -> Posicion encontrada o 0 si no encuentra
  Cadena                 : String que se esta buscando.  No necesita
        que sea en realidad un identificador.  Se revisa meramente
        la vecindad.
  ByteDuplicado          : Byte utilizado para delimitar el String
  FUNCTION BuscarSiguienteIdentificadorEnmascarado : TRUE  si se encontro
                                                     FALSE no se encontro
}

PROCEDURE   BuscarSustituirIdentificadorDobleEnmascarado
   (    VectorFuente            : CAFE_CharByte2Sintactico;
     CONST
        Original, Nuevo         : ShortString;
        ForzarUpCase            : Boolean               = FALSE         );
{
  PROCEDURE BuscarSustituirIdentificadorDobleEnmascarado
        Procedimiento utilizado para sustitucion de identificador
        Original por Nuevo en VectorFuente.  Self pierde su contenido.
        Se permiten comentarios, String, equivalentes de blancos, etc.
        CAFE_IdentificadorUpIgualDown decide si UpCase igual a DownCase;
        puede sin embargo forzarse este estado con ForzarUpCase TRUE
        lo que seria valido para ciertos identificadores,
        como podrian ser los nombres de casillas de Hoja de Calculo.
        CAFE_IdentificadorUpIgualDown como TRUE tiene prioridad.
        No afecta nombres de OperadorBasico.
        NOTA: En la regla en EJES.EXE para hojas de calculo
        A1 si se afecta y A1( X ) no.
        PROCEDURE es util en Copiar casillas.
  VectorFuente                  : contiene la informacion para analizar
        y el resultado de sustitucion.  Self se pierde.
  Original                      : Nombre de identificador a buscar,
        aunque no requiere que cumpla las reglas.  Esta propiedad
        se aprovecha en EJES.EXE para el marcado de nombres de casillas.
  Nuevo                         : El resultado de la sustitucion,
        tampoco se revisa el cumplimiento de reglas.
  ForzarUpCase                  : TRUE, fuerza temporalmente el estado
        CAFE_IdentificadorUpIgualDown como TRUE, para que Original
        se busque sin importar mayusculas ni minusculas.  Esto
        podria ser util en un lenguaje de regla multiple.
        i.e., casillas de Hoja de Calculo combinadas con constantes.
        en las casillas no importa el UpCase y en la constante si.
        En EJES.EXE la regla es siempre CAFE_IdentificadorIgualDown como TRUE
        FALSE, no afecta CAFE_IdentificadorUpIgualDown.
}

PROCEDURE   ReescribirOperadoresReferenciaNivelesPrecedencia
  (     VectorFuente            : CAFE_ClassCharByte;
        PunteroPrecedencia      :
                        CAFE_PointerRegistroPrecedenciaOperadorSintactico;
    VAR CadenaError             : ShortString                           );
{
  PROCEDURE ReescribirOperadoresReferenciaNivelesPrecedencia
        El objetivo de PROCEDURE es recorrer PunteroPrecedencia^
        en busca de todos los operadores, para transformarlos
        a modo de OperadorBasico()
        Ejemplo
        CABALLO := PERRO+GATO*PERICO
        ->
        CABALLO :=OperadorSuma(PERRO,OperadorMultiplicacion(GATO,PERICO))
        o similar...
        * Probablemente se ubica en nivel de precedencia superior
        se evalua primero el indice menor.  Para un mismo
        nivel se revisa de izquierda a derecha.CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible  VectorFuente                  : contiene el CharByte que se analiza
  VectorFuente                  : contiene el CharByte que se analiza
        NOTA: VectorFuente.Ocupado = 0 no genera problemas.
  PunteroPrecedencia            : Paquete con la informacion
        de precedencia sintactica.  Las opciones programadas
        en esta unidad son :
        @CAFE_RegistroPrecedenciaDescriptorIdentificadorPascal
        @CAFE_RegistroPrecedenciaOperadorSintacticoPascal
  CadenaError                   : devuelve '' si todo bien. En
        caso contrario devuelve el operador como
        ( OperadorSimpleReconocido o similar i.e. '*', '/' )
  NOTA : Revisar CAFE_IntentoInfructuosoSintactico = TRUE
        para errores
}

  {$IFNDEF      PRU_Ej3         }
  Strict Private
  {$ENDIF                       }
FUNCTION    ReescribirOrdenReferenciaTraductorOperadorSintactico
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual : LongInt; VAR PosicionFinal             : LongInt;
    VAR DesplazadoFuente        : LongInt;
        PunteroRegistroTraductor                :
                        CAFE_PointerRegistroTraductorOperadorSintactico;
        PunteroPrecedenciaEspecial              : Pointer       ) : Boolean;

  {$IFNDEF      PRU_Ej3         }
  Strict Private
  {$ENDIF                       }
FUNCTION    AgregarOrdenBasicaSumaRestaParametro
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionIzquierda       : LongInt;
    VAR PosicionDerecha         : LongInt;
        SumaResta               : Boolean;
        PunteroPrecedencia      :
          CAFE_PointerRegistroPrecedenciaOperadorSintactico     ) : Boolean;

  {$IFNDEF      PRU_Ej3         }
  Strict Private
  {$ENDIF                       }
FUNCTION    AgregarOrdenBasicaArregloIndiceParametro
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionIzquierda       : LongInt;
    VAR PosicionDerecha         : LongInt;
        PunteroPrecedencia      :
          CAFE_PointerRegistroPrecedenciaOperadorSintactico     ) : Boolean;

  {$IFNDEF      PRU_Ej3         }
  Strict Private
  {$ENDIF                       }
FUNCTION    ReescribirUnNivelOperadorSintactico
  (     VectorFuente            : CAFE_ClassCharByte;
        PunteroPrecedencia      :
                        CAFE_PointerRegistroPrecedenciaOperadorSintactico;
        NivelBusqueda           : Byte;
    VAR CadenaError             : ShortString                   ) : Boolean;

                          END;  { CLASS CAFE_CharByte2Sintactico }

PROCEDURE   CAFE_EliminarSustituirUpCaseBlancoComentario
  (     VectorFuente            : CAFE_ClassCharByte;
        BanderaEnmascararString : Boolean                               );
{
  PROCEDURE CAFE_EliminarSustituirUpCaseBlancoComentario
        El objetivo es eliminar los comentarios, pasar a UpCase
        y colocar blancos.
  VectorFuente                  : Contiene la informacion a analizar.
  BanderaEnmascararString       :
        TRUE  -> Protege los String, evitando ser afectados en el proceso
        FALSE -> Actua, como si no existieran los String en el lenguaje
        La variable CAFE_ByteStringSintactico, controla el byte delimitador
        de String, por el metodo Byte Duplicado
}

PROCEDURE   CAFE_DesplazarBlancoParentesisIzquierdo
  (       VectorFuente                  : CAFE_ClassCharByte;
          ByteParentesisAbrir           : Byte;
    CONST OperadorParentesisAbrir       : CAFE_CadenaSintactica;
          BanderaOperador               : Boolean                       );
{
  PROCEDURE CAFE_DesplazarBlancoParentesisIzquierdo
        Su objetivo es desplazar los parentesis a la izquierda,
        pues muchos algoritmos en EJES.EXE, lo requieren
        para identificar un Operador
        i.e.
        SIN ( COS ( 2*PI ) )
        -->
        SIN(  COS(  2*PI ) )
        En algunas ocasiones, probablemente sea conveniente
        agregar operadores a ciertos parentesis sueltos.
        i.e.
        ( ( 1, 2 ), ( 3, 4 ) )
        -->
        ((  1, 2 ),(  3, 4 ) )
        O bien -->
        (OperadorParentesisAbrir( 1, 2 ),OperadorParentesisAbrir( 3, 4 ) )
        o algo similar...
        La sustitucion a OperadorParentesisAbrir es conveniente por
        que el algoritmo de CAFE_NudoSintactico.GenerarArbolSintacticoBasico
        que no distingue entre ( ( 1, 2 ), ( 3, 4 ) ) y ( 1,2,3,4 ).
        El operador le ayuda a corregir este defecto.
        Se agregan operadores parentesis si se detecta a la
        izquierda ByteParentesisAbrir, o CAFE_ByteSeparadorSintactico ','
  VectorFuente                  : Contiene la informacion a analizar
  ByteParentesisAbrir           : Se refiere al parentesis de apertura
  OperadorParentesisAbrir       : OperadorParentesisAbrir a insertar
        en caso de BanderaOperador TRUE.  Debe tener los dos Parentesis
        de OperadorBasico.
  BanderaOperador               : TRUE -> cuando se requiera (Ver Arriba)
        se inserta OperadorParentesisAbrir.  FALSE -> nada.
}

PROCEDURE   CAFE_InsertarStringBlancoZona
  (     VectorFuente            : CAFE_ClassCharByte;
        Cadena                  : ShortString;
        PosicionInsertar, TamanoZonaBlanco              : LongInt ;
        InicioFinal             : Boolean                               );
{
  PROCEDURE CAFE_InsertarStringBlancoZona
        Al insertar una Cadena generalmente existen en la ubicacion
        espacios en blanco, que se pueden aprovechar en la insercion.
        Esto se indica con TamanoZonaBlanco, que podria ser cero.
        Se intenta insertar Cadena en TamanoZonaBlanco, justificando
        al inicio o final segun bandera InicioFinal.
        Si el tamano de TamanoZonaBlanco no es suficiente, se inserta
        entonces, agregando los espacios necesarios.
  VectorFuente                  : Se refiere a la informacion a analizar
  Cadena                        : Cadena a insertar en VectorFuente.
  PosicionInsertar              : Lugar a realizar la insercion,
        que tiene que ser en la zona util 1..Ocupado+1
  TamanoZonaBlanco              : Indica la cantidad de espacios en blanco
        disponibles para la insercion sin corrimiendo de datos.
  InicioFinal                   : Cuando cadena es pequena.  TRUE ->
        solicita insertar al inicio de TamanoZonaBlanco y FALSE -> al final.
}

PROCEDURE   CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible
  (     VectorFuente            : CAFE_ClassCharByte;
        PalabraReservada        : CAFE_CadenaSintactica                 );
{
  PROCEDURE CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible
        Agrega un espacio vacio a la derecha de una PalabraReservada
        (sin definicion aqui).
        Con algunas condiciones razonables:
        * PalabraReservada no es antecedida ni seguida por
                bytes confundibles (aquellos que se utilizan
                para generar identificadores, i.e. vocales)
        * PalabraReservada es seguida por algo que no es
                ni confundible ni espacio en blanco
        i.e. con PalabraReservada 'AND'
        CABALLO := PERICO AND( PERRO )
        -->
        CABALLO := PERICO AND ( PERRO )
        La razon es que AND( PERRO ) se puede confundir en muchos algoritmos
        con un identificador basico.
        Note que esta situacion puede generarse internamente debido
        a un llamado a CAFE_DesplazarBlancoParentesisIzquierdo,
        aunque esto no estaba en el algoritmo inicial.
  VectorFuente                  : Contiene la informacion a analizar
  PalabraReservada              : Se refiere a la cadena a buscar
        con las condiciones arriba mencionadas.
}

PROCEDURE   CAFE_AgregarEspacioIzquierdoOperadorConfundiblePrecedencia
  (     VectorFuente            : CAFE_ClassCharByte;
        PunteroPrecedencia      :
            CAFE_PointerRegistroPrecedenciaOperadorSintactico           );
{
  PROCEDURE CAFE_AgregarEspacioIzquierdoOperadorConfundiblePrecedencia
        El objetivo es aplicar el PROCEDURE
        CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible
        a los miembros de PunteroPrecedencia que tengan activo al menos
        las banderas [ ActivoRTS, ConfundibleIdentificadorRTS ]
  VectorFuente                  : Contiene la informacion a analizar
  PunteroPrecedencia            : Contiene la lista de operadores
        confundibles a aplicar el algoritmo.
        En esta unidad se ofrece como parametro
        @CAFE_RegistroPrecedenciaOperadorSintacticoPascal.
        El usuario podria crear su propia version.
}

IMPLEMENTATION

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
CONSTRUCTOR CAFE_CharByte2Sintactico.Create
  (     Tamano          : LongInt                               );
BEGIN  { CONSTRUCTOR CAFE_CharByte2Sintactico.Create }
  Inherited;
  ModeloInterior        := CAFE_CharByte2Sintactico;
END;   { CONSTRUCTOR CAFE_CharByte2Sintactico.Create }
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
CONSTRUCTOR CAFE_CharByte2Sintactico.Create
  ( CONST
        Msg             : ShortString;
        Tamano          : LongInt                               );
BEGIN  { CONSTRUCTOR CAFE_CharByte2Sintactico.Create }
  Inherited;
  ModeloInterior        := CAFE_CharByte2Sintactico;
END;   { CONSTRUCTOR CAFE_CharByte2Sintactico.Create }
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
CONSTRUCTOR CAFE_CharByte2Sintactico.Create
  (     Modelo          : CAFE_ClassCharByte                    );
BEGIN  { CONSTRUCTOR CAFE_CharByte2Sintactico.Create }
  Inherited;
  ModeloInterior        := CAFE_CharByte2Sintactico;
END;   { CONSTRUCTOR CAFE_CharByte2Sintactico.Create }
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }

DESTRUCTOR  CAFE_CharByte2Sintactico.Destroy;
BEGIN  { DESTRUCTOR CAFE_CharByte2Sintactico.Destroy }
  Inherited;
END;   { DESTRUCTOR CAFE_CharByte2Sintactico.Destroy }

FUNCTION    CAFE_CharByte2Sintactico.
                ReescribirOrdenReferenciaTraductorOperadorSintactico
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual : LongInt; VAR PosicionFinal             : LongInt;
    VAR DesplazadoFuente        : LongInt;
        PunteroRegistroTraductor                :
                        CAFE_PointerRegistroTraductorOperadorSintactico;
        PunteroPrecedenciaEspecial              : Pointer       ) : Boolean;
VAR
  PivoteCadena                  : ShortString;
  PunteroPivote                 : PChar;
  TamanoEliminar,
  PivoteIzquierda,
  PivoteDerecha,
  PosicionIzquierda,
  PosicionDerecha               : LongInt;
  BanderaAjusteIzquierda,
  BanderaAjusteDerecha,
  SumaResta                     : Boolean;

LABEL
  ProcesoInsertar,
  SalidaError,
  SalidaFalsa;

BEGIN  { FUNCTION ...ReescribirOrdenReferencia... }
  Ocupado                       := 0;
  IF ( PosicionActual <= 0 ) OR ( PosicionActual > VectorFuente.Ocupado )
  THEN GOTO SalidaError;
  DesplazadoFuente              := 0;
  IF PunteroRegistroTraductor = NIL THEN GOTO SalidaError;
  WITH PunteroRegistroTraductor^ DO BEGIN
    BanderaAjusteIzquierda      := TRUE;
    BanderaAjusteDerecha        := TRUE;
    IF NOT( ActivoRTS IN
        PunteroRegistroTraductor^.ConjuntoControlRegistroTraductor )
    THEN GOTO SalidaFalsa;
    IF SumaRestaRTS IN
        PunteroRegistroTraductor^.ConjuntoControlRegistroTraductor THEN BEGIN
      BanderaAjusteIzquierda    := FALSE;
      BanderaAjusteDerecha      := FALSE;
      PosicionIzquierda         := PosicionActual-1;
      PosicionDerecha           := PosicionActual+1;
      SumaResta                 :=
        ( VectorFuente[ PosicionActual ] = CAFE_BytePositivoNumerico );
      IF PunteroPrecedenciaEspecial = NIL THEN GOTO SalidaError;
      IF AgregarOrdenBasicaSumaRestaParametro
        ( VectorFuente, PosicionIzquierda, PosicionDerecha, SumaResta,
          PunteroPrecedenciaEspecial ) THEN GOTO ProcesoInsertar
                                       ELSE GOTO SalidaFalsa;
    END;  { IF SumaRestaRTS IN CAFE_ConjuntoControlRegistroTraductor }
    IF ArregloIndiceRTS IN
                PunteroRegistroTraductor^.ConjuntoControlRegistroTraductor
    THEN BEGIN
      BanderaAjusteIzquierda    := FALSE;
      BanderaAjusteDerecha      := FALSE;
      PosicionIzquierda         := PosicionActual-1;
      PosicionDerecha           := PosicionActual+1;
      IF PunteroPrecedenciaEspecial = NIL THEN GOTO SalidaError;
      IF AgregarOrdenBasicaArregloIndiceParametro
        ( VectorFuente, PosicionIzquierda, PosicionDerecha,
          PunteroPrecedenciaEspecial ) THEN GOTO ProcesoInsertar
                                       ELSE GOTO SalidaFalsa;
    END;  { IF ArregloIndiceRTS IN ConjuntoControlRegistroTraductor }
    IF RegistroDecimalConfundibleRTS IN
       PunteroRegistroTraductor^.ConjuntoControlRegistroTraductor
    THEN BEGIN
      IF VectorFuente[ PosicionActual+1 ] IN
                CAFE_ConjuntoByteNumeroArabigo THEN BEGIN
        BanderaAjusteIzquierda  := FALSE;
        BanderaAjusteDerecha    := FALSE;
        PosicionDerecha         := PosicionActual-1;
        PosicionIzquierda       := PosicionActual;
        GOTO ProcesoInsertar;
      END;  { IF ... IN CAFE_ConjuntoNumericoGeneral }
    END;  { IF RegistroDecimalConfundibleRTS IN ... }
    InsertarString( OperadorNuevoBasico, 1 );
    PosicionIzquierda           := PosicionActual;
    IF ( [ OperadorBinarioRTS, OperadorIzquierdoRTS ]*
            PunteroRegistroTraductor^.
            ConjuntoControlRegistroTraductor ) <> [] THEN BEGIN
      BanderaAjusteIzquierda    := FALSE;
      Dec( PosicionIzquierda );
      IF PosicionIzquierda = 0 THEN GOTO SalidaFalsa;
      IF NOT( AgregarOrdenBasicaParametro
                ( VectorFuente, PosicionIzquierda, FALSE ) )
      THEN GOTO SalidaFalsa;
    END;  { IF ( [ OperadorBinarioRTS, OperadorIzquierdoRTS ]*... }
    PivoteCadena                :=
        PunteroRegistroTraductor^.OperadorSimpleReconocido;
    PosicionActual              :=
                PosicionActual+Length( PivoteCadena )-1;
    PosicionDerecha             := PosicionActual;
    IF ( [ OperadorBinarioRTS, OperadorDerechoRTS ]*
             PunteroRegistroTraductor^.
             ConjuntoControlRegistroTraductor ) <> [] THEN BEGIN
      BanderaAjusteDerecha      := FALSE;
      Inc( PosicionDerecha );
      IF PosicionDerecha > VectorFuente.Ocupado THEN GOTO SalidaFalsa;
      IF NOT( AgregarOrdenBasicaParametro
         ( VectorFuente, PosicionDerecha, TRUE ) ) THEN GOTO SalidaFalsa;
    END;  { IF ( [ OperadorBinarioRTS, OperadorIzquierdoRTS ]*... }
    IF ProtegerRTS IN PunteroRegistroTraductor^.
                        ConjuntoControlRegistroTraductor THEN BEGIN
      BanderaAjusteIzquierda    := FALSE;
      BanderaAjusteDerecha      := FALSE;
      PosicionIzquierda         := PosicionDerecha;
      Dec( PosicionDerecha );
    END;  { IF ProtegerRTS IN ConjuntoControlRegistroTraductor }
    IF BanderaAjusteIzquierda THEN BEGIN
      PivoteIzquierda           := PosicionIzquierda;
      IF VectorFuente.BuscarSiguienteByte
                ( PivoteIzquierda, CAFE_ByteBlancoSintactico, FALSE, FALSE )
      THEN BEGIN
        IF VectorFuente[ PivoteIzquierda ] IN
                CAFE_ConjuntoConfundibleIdentificadorSintactico
        THEN PosicionIzquierda  := PivoteIzquierda+2
        ELSE PosicionIzquierda  := PivoteIzquierda+1;
      END ELSE BEGIN  { IF ...BuscarSiguienteByte... ELSE }
        PosicionIzquierda       := 1;
      END;            { IF ...BuscarSiguienteByte... ELSE }
    END;  { IF BanderaAjusteIzquierda }
    IF BanderaAjusteDerecha THEN BEGIN
      PivoteDerecha             := PosicionDerecha;
      IF VectorFuente.BuscarSiguienteByte
                ( PivoteDerecha, CAFE_ByteBlancoSintactico, TRUE, FALSE )
      THEN PosicionDerecha      := PivoteDerecha-1
      ELSE PosicionDerecha      := VectorFuente.Ocupado;
    END;  { IF BanderaAjusteDerecha }
  END;  { WITH PunteroRegistroTraductor }
ProcesoInsertar :
  IF PosicionDerecha >= PosicionIzquierda THEN BEGIN
    TamanoEliminar              :=
                        PosicionDerecha-PosicionIzquierda+1;
    PunteroPivote               := VectorFuente.MemoriaVector;
    PunteroPivote               := PunteroPivote+PosicionIzquierda-1;
    IF TamanoEliminar >= Ocupado THEN BEGIN
      Move( MemoriaVector^, PunteroPivote^, Ocupado );
      Dec( TamanoEliminar, Ocupado );
      IF TamanoEliminar > 0 THEN BEGIN
        PunteroPivote           := PunteroPivote+Ocupado;
        FillByte( PunteroPivote^,
                TamanoEliminar, CAFE_ByteBlancoSintactico );
      END;  { IF TamanoEliminar > 0 }
      DesplazadoFuente          := 0;
    END ELSE BEGIN  { IF TamanoEliminar >= Ocupado ELSE }
      Move( MemoriaVector^, PunteroPivote^, TamanoEliminar );
      PunteroPivote             := MemoriaVector;
      PunteroPivote             := PunteroPivote+TamanoEliminar;
      DesplazadoFuente          := Ocupado-TamanoEliminar;
      VectorFuente.InsertarDatosCharByte
        ( PunteroPivote, PosicionDerecha+1, DesplazadoFuente );
      Inc( PosicionDerecha, DesplazadoFuente );
    END;            { IF TamanoEliminar >= Ocupado ELSE }
  END;  { IF PosicionDerecha >= PosicionIzquierda }
  PosicionActual                := PosicionIzquierda;
  PosicionFinal                 := PosicionDerecha;
  ReescribirOrdenReferenciaTraductorOperadorSintactico          := TRUE;
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create( 'Sintaxis errada al Reescribir Orden' );
SalidaFalsa :
  DesplazadoFuente              := 0;
  PosicionActual                := 0;
  PosicionFinal                 := 0;
  Ocupado                       := 0;
  ReescribirOrdenReferenciaTraductorOperadorSintactico          := FALSE;
END;   { FUNCTION ...ReescribirOrdenReferencia... }

FUNCTION    CAFE_CharByte2Sintactico.AgregarOrdenBasicaSumaRestaParametro
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionIzquierda       : LongInt;
    VAR PosicionDerecha         : LongInt;
        SumaResta               : Boolean;
        PunteroPrecedencia      :
          CAFE_PointerRegistroPrecedenciaOperadorSintactico     ) : Boolean;
VAR
  PunteroArreglo                :
                CAFE_PointerArrayRegistroTraductorOperadorSintactico;
  UbicacionBinaria,
  UbicacionUnaria,
  PivoteIzquierda               : LongInt;
  ByteIzquierda                 : Byte;
  BanderaIzquierda              : Boolean;

LABEL
  SalidaError,
  SalidaFalsa,
  SalidaExitoFinal;

BEGIN  { FUNCTION ...AgregarOrdenBasicaSumaRestaParametro }
  WITH PunteroPrecedencia^ DO BEGIN
    IF SumaResta THEN BEGIN
      UbicacionBinaria          := UbicacionSumaBinariaRegistroTraductor;
      UbicacionUnaria           := UbicacionSumaUnariaRegistroTraductor;
    END ELSE BEGIN  { IF SumaResta ELSE }
      UbicacionBinaria          := UbicacionRestaBinariaRegistroTraductor;
      UbicacionUnaria           := UbicacionRestaUnariaRegistroTraductor;
    END;            { IF SumaResta ELSE }
    Ocupado                     := 0;
    PunteroArreglo              := PunteroArregloRegistroNivel^
                [ NivelPrecedenciaSumaResta ].PunteroArregloOperador;
    BanderaIzquierda            := FALSE;
    IF PosicionIzquierda > 0 THEN BEGIN
      InsertarString
        ( PunteroArreglo^[ UbicacionBinaria ].OperadorNuevoBasico, 1 );
      PivoteIzquierda           := PosicionIzquierda;
      IF AgregarOrdenBasicaParametro
                ( VectorFuente, PivoteIzquierda, FALSE )
      THEN BEGIN
        BanderaIzquierda        := TRUE;
        PosicionIzquierda       := PivoteIzquierda;
      END ELSE BEGIN  { IF AgregarOrdenBasicaParametro... ELSE }
        ByteIzquierda           := VectorFuente[ PosicionIzquierda ];
        IF ByteIzquierda = CAFE_ByteExponenteSintactico THEN BEGIN
          Ocupado               := 0;
          PosicionDerecha       := PosicionIzquierda;
          Inc( PosicionIzquierda );
          GOTO SalidaExitoFinal;
        END;  { IF ByteIzquierda = CAFE_ByteExponenteSintactico }
        IF ByteIzquierda IN CAFE_ConjuntoConfundibleIdentificadorSintactico
        THEN GOTO SalidaFalsa;
        Inc( PosicionIzquierda );
        PivoteIzquierda         := PosicionIzquierda;
        IF VectorFuente.BuscarSiguienteByte
                ( PivoteIzquierda, CAFE_ByteBlancoSintactico, FALSE, FALSE )
        THEN BEGIN
          IF VectorFuente[ PivoteIzquierda ]
                IN CAFE_ConjuntoConfundibleIdentificadorSintactico
          THEN PosicionIzquierda                := PivoteIzquierda+2
          ELSE PosicionIzquierda                := PivoteIzquierda+1;
        END ELSE BEGIN
          PosicionIzquierda  := 1;
        END;
      END;            { IF AgregarOrdenBasicaParametro... ELSE }
    END ELSE BEGIN  { IF PosicionIzquierda > 0 ELSE }
      PosicionIzquierda         := 1;
    END;            { IF PosicionIzquierda > 0 ELSE }
    IF NOT( BanderaIzquierda ) THEN BEGIN
      Ocupado                   := 0;
      InsertarString
        ( PunteroArreglo^[ UbicacionUnaria ].OperadorNuevoBasico, 1 );
    END;  { IF NOT( BanderaIzquierda ) }
    IF ( PosicionDerecha >  VectorFuente.Ocupado ) OR
       ( PosicionDerecha <= 0                    ) THEN GOTO SalidaFalsa;
    IF AgregarOrdenBasicaParametro
        ( VectorFuente, PosicionDerecha, TRUE )
    THEN GOTO SalidaExitoFinal;
    GOTO SalidaFalsa;
  END;  { WITH PunteroPrecedencia^ }
SalidaError :
  RAISE CAFE_Exception.Create( 'No se pudo AgregarOrdenBasicaSumaParametro' );
SalidaFalsa :
  PosicionIzquierda             := 0;
  PosicionDerecha               := 0;
  Ocupado                       := 0;
  AgregarOrdenBasicaSumaRestaParametro                          := FALSE;
  Exit;
SalidaExitoFinal :
  AgregarOrdenBasicaSumaRestaParametro                          := TRUE;
END;   { FUNCTION ...AgregarOrdenBasicaSumaRestaParametro }

FUNCTION    CAFE_CharByte2Sintactico.AgregarOrdenBasicaArregloIndiceParametro
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionIzquierda       : LongInt;
    VAR PosicionDerecha         : LongInt;
        PunteroPrecedencia      :
          CAFE_PointerRegistroPrecedenciaOperadorSintactico     ) : Boolean;
{
  Un espacio en blanco antes del ARRAY se asume tipo conjunto
  Ejemplo
  CABALLO := PERRO AND [ 23, 24 ]
  se traduce como conjunto
  CABALLO := PERRO AND ›C( 23, 24 )
  y en cambio
  CABALLO := PERRO AND[ 23, 24 ]
  produce por error la matriz:
  CABALLO := PERRO ›V(AND, 23, 24 )
  se debe combinar con otros PROCEDURES para corregir esto
}
VAR
  PunteroByte                   : PChar;
  PunteroArreglo                :
                CAFE_PointerArrayRegistroTraductorOperadorSintactico;
  TamanoInsertar,
  TamanoControl,
  PivoteIzquierda,
  PivoteDerecha                 : LongInt;
  ByteIndiceAbrir,
  ByteIndiceCerrar              : Byte;
  BanderaIzquierda              : Boolean;

LABEL
  SalidaError,
  SalidaFalsa;

BEGIN  { FUNCTION ...AgregarOrdenBasicaArregloIndiceParametro }
  WITH PunteroPrecedencia^ DO BEGIN
    Ocupado                     := 0;
    PunteroArreglo              := PunteroArregloRegistroNivel^
        [ NivelPrecedenciaArregloIndice ].PunteroArregloOperador;
    BanderaIzquierda            := FALSE;
    IF PosicionIzquierda > 0 THEN BEGIN
      IF PosicionIzquierda > VectorFuente.Ocupado THEN GOTO SalidaError;
      IF VectorFuente[ PosicionIzquierda ] <>
              CAFE_ByteBlancoSintactico THEN BEGIN
        InsertarString( PunteroArreglo^
          [ PunteroPrecedencia^.
          UbicacionParentesisAbrirArregloIndice ].OperadorNuevoBasico, 1 );
        PivoteIzquierda           := PosicionIzquierda;
        IF AgregarOrdenBasicaParametro
                  ( VectorFuente, PivoteIzquierda, FALSE ) THEN BEGIN
          BanderaIzquierda        := TRUE;
          PosicionIzquierda       := PivoteIzquierda;
        END ELSE BEGIN { IF AgregarOrdenBasicaParametro... ELSE }
          Inc( PosicionIzquierda );
        END;           { IF AgregarOrdenBasicaParametro... ELSE }
      END;           { IF VectorFuente[ PosicionIzquierda ] <> ... }
      IF NOT( BanderaIzquierda ) THEN BEGIN
        PivoteIzquierda         := PosicionIzquierda;
        IF VectorFuente.BuscarSiguienteByte( PivoteIzquierda,
                CAFE_ByteBlancoSintactico, FALSE, FALSE )
        THEN BEGIN
          IF VectorFuente[ PivoteIzquierda ]
                IN CAFE_ConjuntoConfundibleIdentificadorSintactico
          THEN PosicionIzquierda                := PivoteIzquierda+2
          ELSE PosicionIzquierda                := PivoteIzquierda+1;
        END ELSE BEGIN  { IF ...BuscarSiguienteByte... ELSE }
          PosicionIzquierda     := 1;
        END;            { IF ...BuscarSiguienteByte... ELSE }
      END;  { IF NOT( BanderaIzquierda ) }
    END ELSE BEGIN           { IF PosicionIzquierda > 0 ELSE }
      PosicionIzquierda      := 1;
    END;                     { IF PosicionIzquierda > 0 ELSE }
    IF NOT( BanderaIzquierda ) THEN BEGIN
      Ocupado                   := 0;
      IF ArregloConjuntoRTS IN PunteroArreglo^
           [ PunteroPrecedencia^.UbicacionParentesisAbrirArregloIndice ].
                ConjuntoControlRegistroTraductor THEN BEGIN
        InsertarString( PunteroArreglo^
           [ PunteroPrecedencia^.UbicacionConjuntoOperadorRegistroTraductor ].
                OperadorNuevoBasico, 1 );
      END ELSE BEGIN  { IF ArchivoConjuntoRTS IN ... ELSE }
        GOTO SalidaFalsa;
      END;            { IF ArchivoConjuntoRTS IN ... ELSE }
    END;  { IF NOT( BanderaIzquierda ) }
    ByteIndiceAbrir             := Byte( PunteroArreglo^
        [ PunteroPrecedencia^.UbicacionParentesisAbrirArregloIndice ].
                OperadorSimpleReconocido[ 1 ] );
    ByteIndiceCerrar            := Byte( PunteroArreglo^
        [ PunteroPrecedencia^.UbicacionParentesisCerrarArregloIndice ].
                OperadorSimpleReconocido[ 1 ] );
    PivoteIzquierda             := PosicionDerecha;
    PivoteDerecha               := PosicionDerecha-1;
    IF CAFE_BuscarParejaPareadaCharByteSintactico
        ( VectorFuente, PivoteDerecha,
                ByteIndiceAbrir, ByteIndiceCerrar, TRUE ) THEN BEGIN
      PosicionDerecha           := PivoteDerecha;
      TamanoInsertar            := PivoteDerecha-PivoteIzquierda;
      IF TamanoInsertar > 0 THEN BEGIN
        TamanoControl           := Ocupado+TamanoInsertar;
        IF BanderaIzquierda THEN Inc( TamanoControl );
        IF TamanoControl > TamanoVector THEN GOTO SalidaError;
        IF BanderaIzquierda THEN BEGIN
          Self[ Ocupado ]       := CAFE_ByteSeparadorSintactico;
        END ELSE BEGIN  { IF BanderaIzquierda ELSE }
          Dec( Ocupado );
        END;            { IF BanderaIzquierda ELSE }
        PunteroByte                     := VectorFuente.MemoriaVector;
        PunteroByte                     := PunteroByte+PivoteIzquierda-1;
        InsertarDatosCharByte
                        ( PunteroByte, Ocupado+1, TamanoInsertar );
        Inc( Ocupado );
        Self[ Ocupado ]         := CAFE_ByteParentesisCerrarSintactico;
      END;  { IF TamanoInsertar > 0 }
    END ELSE BEGIN  { IF BuscarParejaPareadaCharByteSintactico... }
      GOTO SalidaFalsa;
    END;            { IF BuscarParejaPareadaCharByteSintactico... }
  END;  { WITH PunteroPrecedencia^ }
  PivoteDerecha                 := PosicionDerecha;
  IF VectorFuente.BuscarSiguienteByte
      ( PivoteDerecha, CAFE_ByteBlancoSintactico, TRUE, FALSE )
  THEN PosicionDerecha          := PivoteDerecha-1
  ELSE PosicionDerecha          := VectorFuente.Ocupado;
  AgregarOrdenBasicaArregloIndiceParametro              := TRUE;
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
        ( 'Fallo aplicar AgregarOrdenBasicaArregloIndiceParametro' );
SalidaFalsa :
  PosicionIzquierda             := 0;
  PosicionDerecha               := 0;
  Ocupado                       := 0;
  AgregarOrdenBasicaArregloIndiceParametro              := FALSE;
END;   { FUNCTION ...AgregarOrdenBasicaArregloIndiceParametro }

FUNCTION    CAFE_CharByte2Sintactico.ReescribirUnNivelOperadorSintactico
  (     VectorFuente            : CAFE_ClassCharByte;
        PunteroPrecedencia      :
                        CAFE_PointerRegistroPrecedenciaOperadorSintactico;
        NivelBusqueda           : Byte;
    VAR CadenaError             : ShortString                   ) : Boolean;
VAR
  ArregloBusquedaEquiNivel      :
        ARRAY [ 1..CAFE_MaximoOperadorMismaPrioridad ] OF
  RECORD
        BanderaActivo           : Boolean;
        PosicionPivote          : LongInt;
  END;
        { RECORD ArregloBusquedaEquiNivel }

VAR
  PunteroRegistroNiveles        : CAFE_PointerRegistroNivelOperador;
  PosicionMenor,
  PosicionActual,
  PosicionFinal,
  DesplazadoFuente              : LongInt;
  TamanoPivote,
  RecorreArreglo,
  UbicacionMenor,
  TamanoMenor                   : Byte;
  BanderaBuscar                 : Boolean;

LABEL
  SalidaError,
  SalidaFalsa;

    { ANIDADO }
  FUNCTION    AnidadoBusquedaOperador
    ( VAR PosicionActual        : LongInt;
          PunteroRegistro       :
            CAFE_PointerRegistroTraductorOperadorSintactico     ) : Boolean;
  VAR
    Larguito                    : Byte;
    BanderaSalir                : Boolean;

  BEGIN  { FUNCTION AnidadoBusquedaOperador }
    WITH PunteroRegistro^ DO BEGIN
      REPEAT
        BanderaSalir            := TRUE;
        IF VectorFuente.BuscarSiguienteCadena
                        ( PosicionActual,
                          PunteroRegistro^.OperadorSimpleReconocido, TRUE )
        THEN BEGIN
          IF ConfundibleIdentificadorRTS IN
                          PunteroRegistro^.ConjuntoControlRegistroTraductor
          THEN BEGIN  { IF ConfundibleIdentificadorRTS IN ... }
            Larguito            :=
                Length( PunteroRegistro^.OperadorSimpleReconocido );
            IF PosicionActual > 1 THEN BEGIN
              IF VectorFuente[ PosicionActual-1 ]
                 IN CAFE_ConjuntoConfundibleIdentificadorSintactico
              THEN BanderaSalir := FALSE;
            END;  { IF PosicionActual > 1 }
            IF ( PosicionActual+Larguito ) <= VectorFuente.Ocupado
            THEN BEGIN
              IF VectorFuente[ PosicionActual+Larguito ]
                      IN CAFE_ConjuntoConfundibleIdentificadorSintactico
              THEN BanderaSalir := FALSE;
            END;  { IF ( PosicionActual+Larguito ) <= ... }
          END;        { IF ConfundibleIdentificadorRTS IN ... }
        END;  { IF VectorFuente.BuscarSiguienteCadena(...) }
      UNTIL BanderaSalir;
    END;  { WITH PunteroRegistro^ }
    AnidadoBusquedaOperador     := PosicionActual <> 0;
  END;   { FUNCTION AnidadoBusquedaOperador }
    { ANIDADO }

BEGIN  { FUNCTION ...ReescribirUnNivelOperadorSintactico }
  CadenaError                   := '';
  IF PunteroPrecedencia = NIL THEN GOTO SalidaError;
  IF ( NivelBusqueda = 0 ) OR ( NivelBusqueda >
                PunteroPrecedencia^.TotalNivelesPrecedencia )
  THEN GOTO SalidaError;
  PunteroRegistroNiveles        := @( PunteroPrecedencia^.
        PunteroArregloRegistroNivel^[ NivelBusqueda ] );
  WITH PunteroRegistroNiveles^ DO BEGIN
    FOR RecorreArreglo := 1 TO TotalOperadoresNivel DO BEGIN
      WITH ArregloBusquedaEquiNivel[ RecorreArreglo ] DO BEGIN
        BanderaActivo           := ActivoRTS IN
                PunteroRegistroNiveles^.
                PunteroArregloOperador^[ RecorreArreglo ].
                ConjuntoControlRegistroTraductor;
        PosicionPivote          := 0;
      END;  { WITH ArregloBusquedaEquiNivel[ RecorreArreglo ] }
    END;  { FOR RecorreArreglo }
    IF NivelBusqueda = PunteroPrecedencia^.NivelPrecedenciaSumaResta
    THEN BEGIN
      ArregloBusquedaEquiNivel
        [ PunteroPrecedencia^.UbicacionSumaUnariaRegistroTraductor ].
                                        BanderaActivo   := FALSE;
      ArregloBusquedaEquiNivel
        [ PunteroPrecedencia^.UbicacionRestaUnariaRegistroTraductor ].
                                        BanderaActivo   := FALSE;
    END;  { IF NivelBusqueda = PunteroPrecedencia^.NivelPrecedenciaSumaResta }
    IF NivelBusqueda = PunteroPrecedencia^.NivelPrecedenciaArregloIndice
    THEN BEGIN
      ArregloBusquedaEquiNivel
        [ PunteroPrecedencia^.UbicacionParentesisCerrarArregloIndice ].
                                        BanderaActivo   := FALSE;
    END;  { IF NivelBusqueda = ...NivelPrecedenciaArregloIndice }
    DesplazadoFuente            := 0;
    PosicionFinal               := 0;
    PosicionActual              := 0;
    REPEAT
      UbicacionMenor            := 0;
      PosicionMenor             := 0;
      TamanoMenor               := 0;
      FOR RecorreArreglo := 1 TO
                PunteroRegistroNiveles^.TotalOperadoresNivel DO BEGIN
        WITH ArregloBusquedaEquiNivel[ RecorreArreglo ] DO BEGIN
          IF ArregloBusquedaEquiNivel[ RecorreArreglo ].BanderaActivo
          THEN BEGIN
            BanderaBuscar       := FALSE;
            IF ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote <> 0
            THEN BEGIN
              Inc( ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote,
                                DesplazadoFuente );
              IF ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote <=
                        PosicionFinal THEN BEGIN
                ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote
                                                := PosicionActual;
                BanderaBuscar   := TRUE;
              END;  { IF PosicionPivote <= PosicionFinal }
            END ELSE BEGIN  { IF PosicionPivote <> 0 ELSE }
              BanderaBuscar     := TRUE;
            END;            { IF PosicionPivote <> 0 ELSE }
            IF BanderaBuscar THEN BEGIN
              IF NOT( AnidadoBusquedaOperador(
                ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote,
                 @( PunteroRegistroNiveles^.
                        PunteroArregloOperador^[ RecorreArreglo ] ) ) )
              THEN BEGIN
                ArregloBusquedaEquiNivel[ RecorreArreglo ].
                        BanderaActivo                   := FALSE;
              END;  { IF NOT( ... ) }
            END;  { IF BanderaBuscar }
          END;  { IF BanderaActivo }
          IF ArregloBusquedaEquiNivel[ RecorreArreglo ].BanderaActivo
          THEN BEGIN
            TamanoPivote        :=
                Length( PunteroRegistroNiveles^.
                        PunteroArregloOperador^[ RecorreArreglo ].
                                                OperadorSimpleReconocido );
            IF   ( PosicionMenor  =              0 )   OR
                 ( ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote
                                  <  PosicionMenor )   OR
               ( ( ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote
                                  =  PosicionMenor )   AND
                 ( TamanoPivote   >  TamanoMenor   ) ) THEN BEGIN
              UbicacionMenor    := RecorreArreglo;
              PosicionMenor     :=
                ArregloBusquedaEquiNivel[ RecorreArreglo ].PosicionPivote;
              TamanoMenor       := TamanoPivote;
            END;  { IF ( ... ) OR ( PosicionPivote < PosicionMenor ) OR ... }
          END;  { IF BanderaActivo }
        END;  { WITH ArregloBusquedaEquiNivel[ RecorreArreglo ] }
      END;  { FOR RecorreArreglo }
      IF UbicacionMenor <> 0 THEN BEGIN
        PosicionActual          :=
                ArregloBusquedaEquiNivel[ UbicacionMenor ].PosicionPivote;
        IF ReescribirOrdenReferenciaTraductorOperadorSintactico
           ( VectorFuente, PosicionActual, PosicionFinal, DesplazadoFuente,
    @( PunteroRegistroNiveles^.PunteroArregloOperador^[ UbicacionMenor ] ),
             PunteroPrecedencia ) THEN BEGIN
          IF PosicionFinal < PosicionActual
          THEN PosicionFinal    := PosicionActual;
        END ELSE BEGIN  { IF ReescribirOrdenReferencia... ELSE }
          CadenaError           := PunteroArregloOperador^[ UbicacionMenor ].
                                        OperadorSimpleReconocido;
          GOTO SalidaFalsa;
        END;            { IF ReescribirOrdenReferencia... ELSE }
      END;  { IF PosicionMenor <> 0 }
    UNTIL UbicacionMenor = 0;
  END;  { WITH PunteroRegistoNiveles^ }
  Ocupado                       := 0;
  ReescribirUnNivelOperadorSintactico                   := TRUE;
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
                ( 'Fallo al ReescribirUnNivelOperadorSintactico' );
SalidaFalsa :
  Ocupado                       := 0;
  ReescribirUnNivelOperadorSintactico                   := FALSE;
  CAFE_IntentoInfructuosoSintactico                     := TRUE;
  CAFE_MensajeInfructuosoSintactico                     := CadenaError;
  CAFE_PosicionInfructuosoSintactico                    := PosicionActual;
END;   { FUNCTION ...ReescribirUnNivelOperadorSintactico }

PROCEDURE   CAFE_CharByte2Sintactico.
                ReescribirOperadoresReferenciaNivelesPrecedencia
  (     VectorFuente            : CAFE_ClassCharByte;
        PunteroPrecedencia      :
                        CAFE_PointerRegistroPrecedenciaOperadorSintactico;
    VAR CadenaError             : ShortString                           );
VAR
  RecorreNiveles                : Byte;

LABEL
  SalidaError,
  SalidaInfructuosa;

BEGIN  { PROCEDURE ...ReescribirOperadoresReferencia... }
  CadenaError                   := '';
  IF PunteroPrecedencia = NIL THEN GOTO SalidaError;
  FOR RecorreNiveles := 1 TO
                PunteroPrecedencia^.TotalNivelesPrecedencia DO BEGIN
    IF NOT( ReescribirUnNivelOperadorSintactico
        ( VectorFuente, PunteroPrecedencia, RecorreNiveles, CadenaError ) )
    THEN GOTO SalidaInfructuosa;
  END;  { FOR RecorreNiveles }
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
        ( 'Fallo en ReescribirOperadoresReferenciaNivelesPrecedencia' );
SalidaInfructuosa :
  Ocupado                       := 0;
  CAFE_IntentoInfructuosoSintactico             := TRUE;
END;   { PROCEDURE ...ReescribirOperadoresReferencia... }

PROCEDURE   CAFE_CharByte2Sintactico.
                        BuscarSustituirIdentificadorDobleEnmascarado
   (    VectorFuente            : CAFE_CharByte2Sintactico;
     CONST
        Original, Nuevo         : ShortString;
        ForzarUpCase            : Boolean               = FALSE         );
VAR
  NuevaCadena                   : ShortString;
  RecorreChar,
  RecorreChar2,
  PosicionActual                : LongInt;
  PivoteUpIgualDown             : Boolean;

BEGIN  { PROCEDURE ...BuscarSustituirIdentificadorDobleEnmascarado }
  TransferenciaCharByte( VectorFuente );
  IF Ocupado < TamanoVector THEN BEGIN
    Inc( Ocupado );
    Self[ Ocupado ]             := 13;
    Self[ Ocupado+1 ]           := 0;
  END;  { IF Ocupado < TamanoVector }
  PivoteUpIgualDown             := CAFE_IdentificadorUpIgualDown;
  IF ForzarUpCase THEN BEGIN
    CAFE_IdentificadorUpIgualDown               := TRUE;
  END;  { IF ForzarUpCase }
  CAFE_EliminarSustituirUpCaseBlancoComentario( Self, TRUE );
  CAFE_IdentificadorUpIgualDown := PivoteUpIgualDown;
  PosicionActual                := 0;
  WHILE BuscarSiguienteIdentificadorEnmascarado
                ( PosicionActual, Original, CAFE_ByteStringSintactico )
  DO BEGIN  { WHILE BuscarSiguienteIdentificadorEnmascarado... }
    EscribirByteRepetidoCharByte
             ( CAFE_ByteBlancoSintactico, PosicionActual,
                Length( Original ), FALSE );
    VectorFuente.EscribirByteRepetidoCharByte
             ( CAFE_ByteBlancoSintactico, PosicionActual,
                Length( Original ), FALSE );
    RecorreChar2                := 0;
    FOR RecorreChar := PosicionActual TO
      ( PosicionActual+Pred( Min( Length( Original ), Length( Nuevo ) ) ) )
    DO BEGIN
      Inc( RecorreChar2 );
      Self[ RecorreChar ]               := Byte( Nuevo[ RecorreChar2 ] );
      VectorFuente[ RecorreChar ]       := Byte( Nuevo[ RecorreChar2 ] );
    END;  { FOR RecorreChar }
    IF Length( Nuevo ) > Length( Original ) THEN BEGIN
      NuevaCadena               :=
                Copy( Nuevo, Succ( Length( Original ) ), Length( Nuevo ) );
      InsertarString
                ( NuevaCadena, PosicionActual+Length( Original ) );
      VectorFuente.InsertarString
                ( NuevaCadena, PosicionActual+Length( Original ) );
    END;  { IF Length( Nuevo ) > Length( Original ) }
    PosicionActual              := PosicionActual+Pred( Length( Nuevo ) );
  END;  { WHILE BuscarSiguienteIdentificadorEnmascarado... }
END;   { PROCEDURE ...BuscarSustituirIdentificadorDobleEnmascarado }

PROCEDURE   CAFE_EliminarSustituirUpCaseBlancoComentario
  (     VectorFuente            : CAFE_ClassCharByte;
        BanderaEnmascararString : Boolean                               );
VAR
  LargoPivote,
  PosicionActual                : LongInt;
  BytePivote                    : Byte;

LABEL
  SalidaError,
  SalidaInfructuosa;

BEGIN  { PROCEDURE CAFE_EliminarSustituirUpCaseBlancoComentario }
  IF VectorFuente = NIL THEN GOTO SalidaError;
  VectorFuente.EliminarComentariosCharByte
        ( CAFE_ComentarioIzquierda1Sintactico,
          CAFE_ComentarioDerecha1Sintactico,
          CAFE_ComentarioIzquierda2Sintactico,
          CAFE_ComentarioDerecha2Sintactico,
          CAFE_ComentarioIzquierda3Sintactico,
          CAFE_ComentarioDerecha3Sintactico,
          CAFE_ByteBlancoSintactico, CAFE_ByteStringSintactico,
          BanderaEnmascararString );
  IF CAFE_IntentoInfructuosoSintactico THEN GOTO SalidaInfructuosa;
  IF BanderaEnmascararString THEN BEGIN
    PosicionActual              := 1;
    WHILE PosicionActual <= VectorFuente.Ocupado DO BEGIN
      BytePivote                := VectorFuente[ PosicionActual ];
      IF BytePivote IN CAFE_ConjuntoEquivalenteByteBlancoSintactico
      THEN BEGIN
        VectorFuente[ PosicionActual ]          := CAFE_ByteBlancoSintactico;
      END ELSE BEGIN  { IF BytePivote IN ... ELSE }
        IF BytePivote = CAFE_ByteStringSintactico THEN BEGIN
          Dec( PosicionActual );
          LargoPivote           := VectorFuente.ConteoBuscarSiguienteByte
                ( PosicionActual, CAFE_ByteStringSintactico, TRUE, FALSE );
          IF Odd( LargoPivote ) THEN BEGIN
            REPEAT
              LargoPivote       := VectorFuente.ConteoBuscarSiguienteByte
                ( PosicionActual, CAFE_ByteStringSintactico, TRUE, FALSE );
              IF LargoPivote = 0 THEN GOTO SalidaInfructuosa;
            UNTIL Odd( LargoPivote );
          END;  { IF Odd( LargoPivote ) }
        END ELSE BEGIN  { IF BytePivote = CAFE_ByteStringSintactico ELSE }
          IF CAFE_IdentificadorUpIgualDown
          THEN VectorFuente[ PosicionActual ]
                                := Byte( UpCase( Char( BytePivote ) ) );
        END;            { IF BytePivote = CAFE_ByteStringSintactico ELSE }
      END;            { IF BytePivote IN ... ELSE }
      Inc( PosicionActual );
    END;  { WHILE PosicionActual <= VectorFuente^.Ocupado }
  END ELSE BEGIN  { IF BanderaEnmascararString ELSE }
    IF CAFE_IdentificadorUpIgualDown
    THEN VectorFuente.UpDownCaseCharByte( TRUE );
    VectorFuente.SustitucionConjuntoByte
      ( CAFE_ConjuntoEquivalenteByteBlancoSintactico,
                        CAFE_ByteBlancoSintactico );
  END;            { IF BanderaEnmascararString ELSE }
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
        ( 'Fallo EliminarSustituirUpCaseBlancoComentario' );
SalidaInfructuosa :
  IF CAFE_PosicionInfructuosoSintactico = 0 THEN BEGIN
    CAFE_IntentoInfructuosoSintactico           := TRUE;
    CAFE_MensajeInfructuosoSintactico           :=
                'No se consiguio identificar final de comentario o String';
    CAFE_PosicionInfructuosoSintactico          := CAFE_1ErrorStringGeneral;
    // error mas probable si Posicion = 0
  END;  { IF CAFE_PosicionInfructuosoSintactico }
END;   { PROCEDURE CAFE_EliminarSustituirUpCaseBlancoComentario }

PROCEDURE   CAFE_DesplazarBlancoParentesisIzquierdo
  (       VectorFuente                  : CAFE_ClassCharByte;
          ByteParentesisAbrir           : Byte;
    CONST OperadorParentesisAbrir       : CAFE_CadenaSintactica;
          BanderaOperador               : Boolean                       );
VAR
  OperadorPivote                : ShortString;
  PosicionActual,
  PosicionNueva                 : LongInt;
  BytePivote                    : Byte;
  BanderaInsertarOperador       : Boolean;

LABEL
  SalidaError;

BEGIN  { PROCEDURE CAFE_DesplazarBlancoParentesisIzquierdo }
  IF VectorFuente = NIL THEN GOTO SalidaError;
  PosicionActual                := 0;
  OperadorPivote                :=
        Copy( CAFE_OperadorParentesisTraducidoOperadorBasico, 1,
                Length( OperadorParentesisAbrir )-2 );
  WHILE VectorFuente.BuscarSiguienteByte
        ( PosicionActual, ByteParentesisAbrir, TRUE, TRUE )
  DO BEGIN
    PosicionNueva               := PosicionActual;
    BanderaInsertarOperador     := BanderaOperador;
    IF VectorFuente.BuscarSiguienteByte
        ( PosicionNueva, CAFE_ByteBlancoSintactico, FALSE, FALSE ) THEN BEGIN
      IF BanderaInsertarOperador THEN BEGIN
        BytePivote              := VectorFuente[ PosicionNueva ];
        BanderaInsertarOperador := BytePivote IN
        [ ByteParentesisAbrir, CAFE_ByteSeparadorSintactico ];
      END;  { IF BanderaInsertarOperador }
      Inc( PosicionNueva );
    END ELSE BEGIN  { IF ...BuscarSiguienteByte( ... ) ELSE }
      PosicionNueva             := 1;
    END;            { IF ...BuscarSiguienteByte( ... ) ELSE }
    IF BanderaInsertarOperador THEN BEGIN
      CAFE_InsertarStringBlancoZona( VectorFuente, OperadorPivote,
        PosicionNueva, PosicionActual-PosicionNueva, FALSE );
    END ELSE BEGIN  { IF BanderaInsertarOperador ELSE }
      IF PosicionActual <> PosicionNueva THEN BEGIN
        VectorFuente[ PosicionNueva  ]  := ByteParentesisAbrir;
        VectorFuente[ PosicionActual ]  := CAFE_ByteBlancoSintactico;
      END;  { IF PosicionActual <> PosicionNueva}
    END;            { IF BanderaInsertarOperador ELSE }
  END;  { WHILE ( VectorFuente^.BuscarSiguienteByte... ) }
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
                ( 'Error al DesplazarBlancoParentesisSintactico' );
END;   { PROCEDURE CAFE_DesplazarBlancoParentesisIzquierdo }

PROCEDURE   CAFE_InsertarStringBlancoZona
  (     VectorFuente            : CAFE_ClassCharByte;
        Cadena                  : ShortString;
        PosicionInsertar, TamanoZonaBlanco              : LongInt ;
        InicioFinal             : Boolean                               );
VAR
  PunteroPivote                 : PChar;
  TamanoInsertar                : Byte;

LABEL
  SalidaError;

BEGIN  { PROCEDURE CAFE_InsertarStringBlancoZona }
  IF VectorFuente = NIL THEN GOTO SalidaError;
  IF ( PosicionInsertar <= 0                           ) OR
     ( PosicionInsertar >  ( VectorFuente.Ocupado+1 ) )
  THEN GOTO SalidaError;
  TamanoInsertar                := Length( Cadena );
  IF TamanoZonaBlanco < 0 THEN GOTO SalidaError;
  IF ( VectorFuente.Ocupado+TamanoInsertar-TamanoZonaBlanco ) >
        VectorFuente.TamanoVector THEN GOTO SalidaError;
  IF TamanoInsertar = 0 THEN Exit;
  IF TamanoInsertar <= TamanoZonaBlanco THEN BEGIN
    IF InicioFinal THEN BEGIN
      PunteroPivote             := VectorFuente.MemoriaVector;
      PunteroPivote             := PunteroPivote+PosicionInsertar-1;
    END ELSE BEGIN  { IF InicioFinal ELSE }
      PunteroPivote             := VectorFuente.MemoriaVector;
      PunteroPivote             :=
        PunteroPivote+PosicionInsertar+TamanoZonaBlanco-TamanoInsertar-1;
    END;            { IF InicioFinal ELSE }
    Move( Cadena[ 1 ], PunteroPivote^, TamanoInsertar );
  END ELSE BEGIN  { IF TamanoInsertar < TamanoZonaBlnaco ELSE }
    IF TamanoZonaBlanco > 0 THEN BEGIN
      PunteroPivote             := VectorFuente.MemoriaVector;
      PunteroPivote             := PunteroPivote+PosicionInsertar-1;
      Move( Cadena[ 1 ], PunteroPivote^, TamanoZonaBlanco );
    END;  { IF TamanoZonaBlnaco > 0 }
    PunteroPivote               := @Cadena[ 1+TamanoZonaBlanco ];
    Dec( TamanoInsertar, TamanoZonaBlanco );
    VectorFuente.InsertarDatosCharByte
        ( PunteroPivote, PosicionInsertar+TamanoZonaBlanco, TamanoInsertar );
  END;            { IF TamanoInsertar < TamanoZonaBlanco ELSE }
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create( 'Fallo InsertarStringBlancoZona' );
END;   { PROCEDURE CAFE_InsertarStringBlancoZona }

FUNCTION    CAFE_CharByte2Sintactico.ExtraccionByteDuplicadoString
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual : LongInt; VAR PosicionFinal     : LongInt;
        ByteDuplicado           : Byte;
        AdmisibleCharByte       : Boolean                       ) : Boolean;
CONST
  TamanoMaximoString            = 255;

VAR
  PunteroPivote                 : PChar;
  TamanoExtraccion,
  LargoPivote                   : LongInt;

LABEL
  SalidaError,
  SalidaInfructuosa,
  SalidaFalsa;

BEGIN  { FUNCTION CAFE_CharByte2Sintactico.ExtraccionByteDuplicadoString }
  Ocupado                       := 0;
  IF VectorFuente = NIL THEN GOTO SalidaError;
  LargoPivote                   := VectorFuente.ConteoBuscarSiguienteByte
                ( PosicionActual, ByteDuplicado, TRUE, TRUE );
  IF LargoPivote = 0 THEN GOTO SalidaFalsa;
  PosicionFinal                 := PosicionActual+LargoPivote-1;
  IF Odd( LargoPivote ) THEN BEGIN
    REPEAT
      LargoPivote               := VectorFuente.ConteoBuscarSiguienteByte
                ( PosicionFinal, ByteDuplicado, TRUE, FALSE );
      IF LargoPivote = 0 THEN GOTO SalidaInfructuosa;
    UNTIL Odd( LargoPivote );
  END;  { IF Odd( LargoPivote ) }
  IF NOT( AdmisibleCharByte ) THEN BEGIN
    IF ( PosicionFinal-PosicionActual+1 ) > TamanoMaximoString
    THEN GOTO SalidaInfructuosa;
  END;  { IF NOT( AdmisibleCharByte ) }
  TamanoExtraccion              := PosicionFinal-PosicionActual-1;
  IF TamanoExtraccion > TamanoVector THEN GOTO SalidaError;
  IF TamanoExtraccion <> 0 THEN BEGIN
    PunteroPivote               := VectorFuente.MemoriaVector;
    PunteroPivote               := PunteroPivote+PosicionActual; { +1-1 }
    Move( PunteroPivote^, MemoriaVector^, TamanoExtraccion );
    Ocupado                     := TamanoExtraccion;
    ContraccionByteDuplicado( ByteDuplicado );
  END;  { IF TamanoExtraccion <> 0 }
  Self[ Ocupado+1 ]             := 0;
  ExtraccionByteDuplicadoString := TRUE;
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create( 'Fallo en ExtraccionByteDuplicadoString' );
SalidaInfructuosa :
  CAFE_IntentoInfructuosoSintactico             := TRUE;
  CAFE_MensajeInfructuosoSintactico             :=
                        'Falta delimitador derecho de String';
  CAFE_PosicionInfructuosoSintactico            :=
                        CAFE_1ErrorFaltaFinString;
SalidaFalsa :
  PosicionActual                := 0;
  PosicionFinal                 := 0;
  Ocupado                       := 0;
  ExtraccionByteDuplicadoString := FALSE;
END;   { FUNCTION CAFE_CharByte2Sintactico.ExtraccionByteDuplicadoString }

FUNCTION    CAFE_CharByte2Sintactico.ExtraccionSustitucionByteDuplicadoString
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual          : LongInt;
        AdmisibleCharByte       : Boolean;
        Lista                   : CAFE_TStringList      = NIL   ) : Boolean;
VAR
  OperadorString,
  CadenaNumero                  : CAFE_CadenaSintactica;
  PunteroPivote                 : PChar;
  PosString,
  PosicionFinal,
  PosicionPivote,
  PosicionIzquierda,
  PosicionDerecha               : LongInt;
  PivoteBandera                 : Boolean;

LABEL
  SalidaError;

BEGIN  { FUNCTION ...ExtraccionSustitucionByteDuplicadoString }
  PosicionFinal                 := PosicionActual;
  PivoteBandera                 := ExtraccionByteDuplicadoString
        ( VectorFuente, PosicionActual, PosicionFinal,
          CAFE_ByteStringSintactico, AdmisibleCharByte );
  IF PivoteBandera THEN BEGIN
    IF Ocupado = 0 THEN BEGIN
      OperadorString            := CAFE_IdentificadorStringNull;
    END ELSE BEGIN  { IF Ocupado = 0 ELSE }
      IF Ocupado = 1 THEN BEGIN
        Str( Byte( MemoriaVector^ ), CadenaNumero );
        OperadorString          :=
                  Copy( CAFE_OperadorCHRSintactico, 1,
                          Length( CAFE_OperadorCHRSintactico )-1 )+
                  CadenaNumero+')';
      END ELSE BEGIN  { IF Ocupado = 1 ELSE }
        IF Lista = NIL THEN BEGIN
          Inc( CAFE_UltimoIdentificadorStringSintactico,
                  CAFE_IncrementoIdentificadorStringSintactico );
          PosString     := CAFE_UltimoIdentificadorStringSintactico;
        END ELSE BEGIN  { IF Lista = NIL ELSE }
          PosString             := Lista.IndexOf( MemoriaVector );
          IF PosString < 0
          THEN PosString        := Lista.Add( MemoriaVector );
        END;            { IF Lista = NIL ELSE }
        Str( PosString, CadenaNumero );
        OperadorString          :=
                  Copy( CAFE_OperadorStringTraducidoOperadorBasico, 1,
                    Length( CAFE_OperadorStringTraducidoOperadorBasico )-1 )+
                    CadenaNumero+')';
      END;            { IF Ocupado = 1 ELSE }
    END;            { IF Ocupado = 0 ELSE }
    PunteroPivote               := VectorFuente.MemoriaVector;
    PunteroPivote               := PunteroPivote+PosicionActual-1;
    FillByte( PunteroPivote^, PosicionFinal-PosicionActual+1,
                        CAFE_ByteBlancoSintactico );
    PosicionPivote              := PosicionActual;
    IF VectorFuente.BuscarSiguienteByte
                ( PosicionPivote, CAFE_ByteBlancoSintactico, FALSE, FALSE )
    THEN BEGIN
      IF VectorFuente[ PosicionPivote ] IN
                CAFE_ConjuntoConfundibleIdentificadorSintactico
      THEN PosicionIzquierda    := PosicionPivote+2
      ELSE PosicionIzquierda    := PosicionPivote+1;
    END ELSE BEGIN  { IF ...BuscarSiguienteByte... ELSE }
      PosicionIzquierda         :=1;
    END;            { IF ...BuscarSiguienteByte... ELSE }
    PosicionPivote              := PosicionFinal;
    IF VectorFuente.BuscarSiguienteByte
        ( PosicionPivote, CAFE_ByteBlancoSintactico, TRUE, FALSE )
    THEN PosicionDerecha        := PosicionPivote-1
    ELSE PosicionDerecha        := VectorFuente.Ocupado;
    CAFE_InsertarStringBlancoZona( VectorFuente, OperadorString,
        PosicionIzquierda, PosicionDerecha-PosicionIzquierda+1, TRUE );
  END;  { IF PivoteBandera }
  ExtraccionSustitucionByteDuplicadoString              := PivoteBandera;
  Exit;
SalidaError :
  Ocupado                       := 0;
  PosicionActual                := 0;
  RAISE CAFE_Exception.Create
                ( 'Fallo en ExtraccionSustitucionByteDuplicadoString' );
  ExtraccionSustitucionByteDuplicadoString              := FALSE;
END;   { FUNCTION ...ExtraccionSustitucionByteDuplicadoString }

FUNCTION    CAFE_CharByte2Sintactico.ReescribirAsignacionOperadorSintactico
  (     VectorFuente            : CAFE_ClassCharByte;
    VAR PosicionActual          : LongInt;
        OperadorAsignacion, OperadorTraducido   : CAFE_CadenaSintactica;
        BanderaOperadorParentesis               : Boolean       ) : Boolean;
VAR
  CadenaPivote                  : ShortString;
  RegistroPivote                : CAFE_RegistroTraductorOperadorSintactico;
  DesplazadoFuente,
  PosicionPivoteA,
  PosicionPivoteB               : LongInt;

LABEL
  SalidaError,
  SalidaInfructuosa,
  SalidaFalsa;

BEGIN  { FUNCTION ...ReescribirAsignacionOperadorSintactico }
  IF VectorFuente = NIL THEN GOTO SalidaError;
  IF VectorFuente.BuscarSiguienteCadena
        ( PosicionActual, OperadorAsignacion, TRUE ) THEN BEGIN
    IF BanderaOperadorParentesis THEN BEGIN
      PosicionPivoteA           :=
                        PosicionActual+Length( OperadorAsignacion )-1;
      PosicionPivoteB           := PosicionPivoteA;
      IF VectorFuente.BuscarSiguienteByte
         ( PosicionPivoteB, CAFE_ByteBlancoSintactico, TRUE, FALSE ) THEN BEGIN
        IF VectorFuente[ PosicionPivoteB ]      =
                        CAFE_ByteParentesisAbrirSintactico THEN BEGIN
          CadenaPivote          :=
            Copy( CAFE_OperadorParentesisTraducidoOperadorBasico, 1,
            Length( CAFE_OperadorParentesisTraducidoOperadorBasico )-2 );
          CAFE_InsertarStringBlancoZona( VectorFuente, CadenaPivote,
                PosicionPivoteA+1, PosicionPivoteB-PosicionPivoteA-1, FALSE );
        END;  { IF ...MostrarFlechaByte... = ByteParentesisAbrirSintactico }
      END;  { IF ...BuscarSiguitenByte(...ByteBlancoSintactico...) }
    END;  { IF BanderaOperadorParentesis }
    WITH RegistroPivote DO BEGIN
      OperadorSimpleReconocido  := OperadorAsignacion;
      OperadorNuevoBasico       := OperadorTraducido;
      ConjuntoControlRegistroTraductor                  :=
                                [ ActivoRTS, OperadorBinarioRTS ];
        { Para que funcione requiere aplicar               }
        { despues del cambio de formato del valor asignado }
    END;  { WITH RegistroPivote }
    PosicionPivoteA             := PosicionActual;
    PosicionPivoteB             := PosicionActual;
    DesplazadoFuente            := 0;
    IF NOT( ReescribirOrdenReferenciaTraductorOperadorSintactico
        ( VectorFuente, PosicionPivoteA, PosicionPivoteB, DesplazadoFuente,
          @RegistroPivote, NIL ) ) THEN GOTO SalidaInfructuosa;
  END ELSE BEGIN  { IF ...BuscarSiguienteCadena... ELSE }
    GOTO SalidaFalsa;
  END;            { IF ...BuscarSiguienteCadena... ELSE }
  ReescribirAsignacionOperadorSintactico                := TRUE;
  PosicionActual                := PosicionPivoteA;
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
        ( 'Fallo a ReescribirAsignacionOperadorSintactico' );
SalidaInfructuosa :
  CAFE_IntentoInfructuosoSintactico             := TRUE;
  CAFE_MensajeInfructuosoSintactico             := OperadorAsignacion;
  CAFE_PosicionInfructuosoSintactico            :=
                CAFE_3ErrorSintaxisAsignacionGeneral;
SalidaFalsa :
  PosicionActual                := 0;
  Ocupado                       := 0;
  ReescribirAsignacionOperadorSintactico                := FALSE;
END;   { FUNCTION ...ReescribirAsignacionOperadorSintactico }

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
PROCEDURE   CAFE_CharByte2Sintactico.ReescribirJustificadorTipoWritePascal
  (     VectorFuente            : CAFE_ClassCharByte;
        OperadorTipoWrite       : CAFE_CadenaSintactica                 );
  { Operador con () sin blancos ni en VectorFuente^ }
VAR
  RegistroTraductor             : CAFE_RegistroTraductorOperadorSintactico;
  OperadorBusqueda              : CAFE_CadenaSintactica;
  PosicionActual,
  PosicionPivote,
  PosicionPivote2,
  PosicionPivote3,
  PosicionPivote4,
  PosicionInicio,
  PosicionFinal,
  DesplazadoFuente              : LongInt;

LABEL
  RepiteOperadorJustificador,
  SiguienteBusqueda,
  SalidaError,
  SalidaInfructuosa;

BEGIN  { PROCEDURE ...ReescribirJustificadorTipoWritePascal }
  IF VectorFuente = NIL THEN GOTO SalidaError;
  OperadorBusqueda              :=
        Copy( OperadorTipoWrite, 1, Length( OperadorTipoWrite )-1 );
  PosicionActual                := 0;
  WHILE VectorFuente.BuscarSiguienteCadena
                ( PosicionActual, OperadorBusqueda, TRUE ) DO BEGIN
    PosicionPivote              := PosicionActual;
    Dec( PosicionPivote );
    IF PosicionPivote > 0 THEN BEGIN
      IF VectorFuente[ PosicionPivote ] IN
         CAFE_ConjuntoConfundibleIdentificadorSintactico
      THEN GOTO SiguienteBusqueda;
    END;  { IF PosicionPivote > 0 }
    PosicionPivote              :=
                        PosicionActual+Length( OperadorBusqueda )-1;
    PosicionPivote2             := PosicionPivote;
    PosicionPivote4             := PosicionPivote;
    IF NOT( CAFE_BuscarParejaPareadaCharByteSintactico
        ( VectorFuente, PosicionPivote, CAFE_ByteParentesisAbrirSintactico,
          CAFE_ByteParentesisCerrarSintactico, TRUE ) )
    THEN GOTO SalidaInfructuosa;
    PosicionActual              := PosicionPivote;
RepiteOperadorJustificador :
    IF NOT( VectorFuente.BuscarSiguienteByte
       ( PosicionPivote2,
         CAFE_ByteExcepcionDescriptorWritePascal, TRUE, TRUE ) )
    THEN Exit;
    IF PosicionPivote2 > PosicionPivote THEN GOTO SiguienteBusqueda;
    PosicionPivote3             := PosicionPivote2;
    IF NOT( CAFE_BuscarParejaPareadaCharByteSintactico
        ( VectorFuente, PosicionPivote3, CAFE_ByteParentesisAbrirSintactico,
          CAFE_ByteParentesisCerrarSintactico, FALSE ) )
    THEN GOTO SalidaInfructuosa;
    IF PosicionPivote3 <> PosicionPivote4 THEN
    GOTO RepiteOperadorJustificador;
    WITH RegistroTraductor DO BEGIN
      OperadorSimpleReconocido  := CAFE_CharExcepcionDescriptorWritePascal;
      OperadorNuevoBasico       := CAFE_OperadorJustificadorTipoWrite;
      ConjuntoControlRegistroTraductor                  :=
                                [ ActivoRTS, OperadorBinarioRTS ];
    END;  { WITH RegistroTraductor }
    PosicionInicio              := PosicionPivote2;
    PosicionFinal               := PosicionPivote2;
    DesplazadoFuente            := 0;
    IF NOT( ReescribirOrdenReferenciaTraductorOperadorSintactico
        ( VectorFuente, PosicionInicio, PosicionFinal, DesplazadoFuente,
                @RegistroTraductor, NIL ) ) THEN GOTO SalidaInfructuosa;
    Inc( PosicionActual, DesplazadoFuente );
    Inc( PosicionPivote, DesplazadoFuente );
    PosicionPivote2             := PosicionInicio;
    GOTO RepiteOperadorJustificador;
SiguienteBusqueda :
  END;  { WHILE ...BuscarSiguienteCadena... }
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
                ( 'Fallo en ReescribirJustificadorTipoWritePascal' );
SalidaInfructuosa :
  CAFE_IntentoInfructuosoSintactico             := TRUE;
  CAFE_MensajeInfructuosoSintactico             := OperadorTipoWrite;
  CAFE_PosicionInfructuosoSintactico            :=
                CAFE_3ErrorSintaxisJustificadoresWrite;
END;   { PROCEDURE ...ReescribirJustificadorTipoWritePascal }
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }

FUNCTION    CAFE_CharByte2Sintactico.BuscarSiguienteIdentificador
  ( VAR PosicionActual          : LongInt;
    CONST
        Cadena                  : ShortString ;
        Direccion               : Boolean                       ) : Boolean;
VAR
  PosicionPivote                : LongInt;

LABEL
  CicloBusqueda;

BEGIN  { FUNCTION ...BuscarSiguienteIdentificador }
CicloBusqueda :
  IF BuscarSiguienteCadena( PosicionActual, Cadena, Direccion ) THEN BEGIN
    PosicionPivote              := PosicionActual-1;
    IF PosicionPivote > 1 THEN BEGIN
      IF Self[ PosicionPivote ] IN
                CAFE_ConjuntoConfundibleIdentificadorSintactico
      THEN GOTO CicloBusqueda;
    END;  { IF PosicionPivote > 1 }
    PosicionPivote              := PosicionActual+Length( Cadena );
    IF PosicionPivote <= Ocupado THEN BEGIN
      IF Self[ PosicionPivote ] IN
                CAFE_ConjuntoConfundibleIdentificadorSintactico
      THEN GOTO CicloBusqueda;
      Dec( PosicionPivote );
      IF BuscarSiguienteByte( PosicionPivote, CAFE_ByteBlancoSintactico,
          Direccion, FALSE )
      THEN BEGIN
        IF Self[ PosicionPivote ] = CAFE_ByteParentesisAbrirSintactico
        THEN GOTO CicloBusqueda;
      END;  { IF BuscarSiguienteByte }
    END;  { IF PosicionPivote <= Ocupado }
    BuscarSiguienteIdentificador        := TRUE;
  END ELSE BEGIN
    BuscarSiguienteIdentificador        := FALSE;
  END;
END;   { FUNCTION ...BuscarSiguienteIdentificador }

FUNCTION    CAFE_CharByte2Sintactico.BuscarSiguienteIdentificadorEnmascarado
  ( VAR PosicionActual          : LongInt;
    CONST
        Cadena                  : ShortString;
        ByteDuplicado           : Byte                          ) : Boolean;
VAR
  PivoteLargo,
  PosicionPivote                : LongInt;

LABEL
  RepiteCiclo,
  RepiteCicloString;

BEGIN  { FUNCTION ...BuscarSiguienteIdentificadorEnmascarado }
  PosicionPivote                := PosicionActual;
RepiteCiclo :
  PosicionActual                := PosicionPivote;
  IF BuscarSiguienteIdentificador( PosicionActual, Cadena, TRUE ) THEN BEGIN
RepiteCicloString :
    REPEAT
      PivoteLargo               := ConteoBuscarSiguienteByte
        ( PosicionPivote, ByteDuplicado, TRUE, FALSE );
    UNTIL Odd( PivoteLargo ) OR ( PivoteLargo = 0 );
    IF ( PivoteLargo <> 0 ) AND ( PosicionPivote < PosicionActual ) THEN BEGIN
      REPEAT
        PivoteLargo               := ConteoBuscarSiguienteByte
          ( PosicionPivote, ByteDuplicado, TRUE, FALSE );
      UNTIL Odd( PivoteLargo ) OR ( PivoteLargo = 0 );
      IF ( PivoteLargo <> 0 ) THEN BEGIN
        IF PosicionPivote > PosicionActual
        THEN GOTO RepiteCiclo
        ELSE GOTO RepiteCicloString;
      END;  { IF ( PivoteLargo <> 0 ) }
    END;  { IF PosicionPivote < PosicionActual }
    BuscarSiguienteIdentificadorEnmascarado     := TRUE;
  END ELSE BEGIN  { IF BuscarSiguienteIdentificador... ELSE }
    BuscarSiguienteIdentificadorEnmascarado     := FALSE;
  END;            { IF BuscarSiguienteIdentificador... ELSE }
END;   { FUNCTION ...BuscarSiguienteIdentificadorEnmascarado }

PROCEDURE   CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible
  (     VectorFuente            : CAFE_ClassCharByte;
        PalabraReservada        : CAFE_CadenaSintactica                 );
VAR
  PosicionActual,
  PosicionPivote                : LongInt;

LABEL
  SalidaError;

BEGIN  { PROCEDURE CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible }
  IF VectorFuente = NIL THEN GOTO SalidaError;
  PosicionActual                := 0;
  WHILE VectorFuente.BuscarSiguienteCadena
        ( PosicionActual, PalabraReservada, TRUE ) DO BEGIN
    PosicionPivote              := PosicionActual-1;
    IF PosicionPivote <> 0 THEN BEGIN
      IF NOT( VectorFuente[ PosicionPivote ]
                IN CAFE_ConjuntoConfundibleIdentificadorSintactico )
      THEN BEGIN
        PosicionPivote          := PosicionActual+Length( PalabraReservada );
        IF PosicionPivote <= VectorFuente.Ocupado THEN BEGIN
          IF NOT( VectorFuente[ PosicionPivote ] IN
                ( CAFE_ConjuntoConfundibleIdentificadorSintactico+
                        [ CAFE_ByteBlancoSintactico ] ) )
          THEN BEGIN
            VectorFuente.InsertarString
                ( Chr( CAFE_ByteBlancoSintactico ), PosicionPivote );
          END;  { IF NOT( ... ConjuntoConfundibleIdentificadorSintactico... }
        END;  { IF PosicionPivote <= VectorFuente.Ocupado }
      END;  { IF NOT( ...VectorFuente[ PosicionPivote ]... IN ... }
    END;  { IF PosicionPivote <> 0 }
  END;  { WHILE ...BuscarSiguienteCadena( ..., PalabraReservada,... ) }
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create
        ( 'Fallo en AgregarEspacioIzquierdoPalabraReservadaConfundible' );
END;   { PROCEDURE CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible }

PROCEDURE   CAFE_AgregarEspacioIzquierdoOperadorConfundiblePrecedencia
  (     VectorFuente            : CAFE_ClassCharByte;
        PunteroPrecedencia      :
            CAFE_PointerRegistroPrecedenciaOperadorSintactico           );
VAR
  RecorreNiveles,
  RecorreOperador,
  TotalOperadores               : Byte;

LABEL
  SalidaError;

BEGIN  { PROCEDURE CAFE_AgregarEspacioIzquierdoOperador... }
  IF PunteroPrecedencia = NIL THEN GOTO SalidaError;
  FOR RecorreNiveles := 1 TO PunteroPrecedencia^.TotalNivelesPrecedencia
  DO BEGIN
    TotalOperadores             := PunteroPrecedencia^.
        PunteroArregloRegistroNivel^[ RecorreNiveles ].TotalOperadoresNivel;
    FOR RecorreOperador := 1 TO TotalOperadores DO BEGIN
      IF ( [ ActivoRTS, ConfundibleIdentificadorRTS ] <= PunteroPrecedencia^.
                PunteroArregloRegistroNivel^[ RecorreNiveles ].
                PunteroArregloOperador^[ RecorreOperador ].
                ConjuntoControlRegistroTraductor ) THEN BEGIN
        CAFE_AgregarEspacioIzquierdoPalabraReservadaConfundible( VectorFuente,
                PunteroPrecedencia^.
                PunteroArregloRegistroNivel^[ RecorreNiveles ].
                PunteroArregloOperador^[ RecorreOperador ].
                OperadorSimpleReconocido );
      END;  { IF [ ActivoRTS, ConfundibleIdentificadorRTS ] IN ... }
    END;  { FOR RecorreOperadores }
  END;  { FOR RecorreNiveles }
  Exit;
SalidaError :
  RAISE CAFE_Exception.Create( 'Fallo en AgregarEspacioIzquierdoOperador' );
END;   { PROCEDURE CAFE_AgregarEspacioIzquierdoOperador... }

INITIALIZATION
  CAFE_ComentarioIzquierda1Sintactico                :=
                                CAFE_ComentarioIzquierda1Pascal;
  CAFE_ComentarioIzquierda2Sintactico                :=
                                CAFE_ComentarioIzquierda2Pascal;
  CAFE_ComentarioIzquierda3Sintactico                :=
                                CAFE_ComentarioIzquierda3Pascal;
  CAFE_ComentarioDerecha1Sintactico                  :=
                                CAFE_ComentarioDerecha1Pascal;
  CAFE_ComentarioDerecha2Sintactico                  :=
                                CAFE_ComentarioDerecha2Pascal;
  CAFE_ComentarioDerecha3Sintactico                  :=
                                CAFE_ComentarioDerecha3Pascal;
  CAFE_ByteStringSintactico                          := CAFE_ByteStringPascal;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  CAFE_BanderaEnmascararStringSintactico             := TRUE;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
  CAFE_UltimoIdentificadorStringSintactico           := 0;
  CAFE_IncrementoIdentificadorStringSintactico       := 1;
  CAFE_ConjuntoConfundibleIdentificadorSintactico    :=
                CAFE_PrimerByteIdentificadorSintactico+
                CAFE_MedioByteIdentificadorSintactico+
                CAFE_UltimoByteIdentificadorSintactico;
FINALIZATION
END.


