Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > PHP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 12-12-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.114
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,


Cita:
Empezado por Román
(...) No me parece muy atinado tu comentario.
Seguro que Gunman no lo decía por tanto (noté cierta ironía) y comprende perfectamente su posición Román. ¿Eh Gunman?
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #2  
Antiguo 12-12-2005
[Gunman] [Gunman] is offline
Miembro
 
Registrado: dic 2004
Ubicación: Pedreguer.
Posts: 355
Poder: 20
[Gunman] Va por buen camino
Lo siento Román, sé que no has contestado porqué no has visto el post, de haberlo visto estoy seguro de que hubieses contestado. Sólo pretendia que mi post subiera otra vez a la cabeza del subforo para que lo vieras, era una forma de llamar la atención. Quizá, mi comentario no ha estado del todo oportuno, en ningún momento he pensado/queria decir que me ignoras. Tú también tienes derecho a una vida privada en plenas condiciones, y desde ningún punto de vista, estos foros han de superar, en cuanto a primordialidad, a tu vida.
Una vez más, te pido disculpas por el comentario. No pretendia tacharte de pasota, ni de desinteresado.
Mil perdones, que este pequeño incidente no obstaculize nuestra relación de colaboradores (yo siempre que pueda, se que tú tambén, intentaré ayudar a todos los usuarios).
No pretendo ser repetitivo, pero por si no han quedado claras mis disculpas: Mil perdones, compañero Román.
__________________
l2prog.co.nr
Responder Con Cita
  #3  
Antiguo 13-12-2005
[Gunman] [Gunman] is offline
Miembro
 
Registrado: dic 2004
Ubicación: Pedreguer.
Posts: 355
Poder: 20
[Gunman] Va por buen camino
Por favor, Román, no estés molesto. Te pido mil disculpas.
__________________
l2prog.co.nr
Responder Con Cita
  #4  
Antiguo 13-12-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Como ya te comentó David, la implementación específica dependerá del sistema de foros que uses y yo desconozco por completo el que mencionas.

El resaltado en sí se hace mediante un script PHP. Por el momento no tengo pensado publicarlo pero puedo darte la idea general, que, en mi opinión, es mucho mejor que poner el código final.

Dado que estamos hablando de PHP, muevo además este hilo al foro correspondiente.

La base del resaltado es la identificación de los distintos tokens a resaltar mediante el uso de expresiones regulares.

A grandes rasgos, una expresión regular es un patrón que permite identificar porciones de texto. Sin duda todos hemos escrito alguna vez algo como:


Código:
msdos>dir arch.*bk
"arch.*bk" es un patrón que indica que buscamos todas las coincidencias de nombres de archivo que comiencen con "arch." y terminen con "bk". El asterisco * es un comodín que especifica que entre "arch." y "bk" puede haber cualquier cosa.

Sin embargo, el uso de comodines es una aproximación muy limitada a las expresiones regulares. PHP utiliza las expresiones PCRE (Perl Compatible Regular Expressions) que permiten detectar una amplia gama de patrones.

Por ejemplo, la expresión


Código:
[a-z_][a-z0-9_]*
detecta porciones de texto que:
  • comiencen con una letra minúscula o un símbolo de subrayado, es decir, con cualquier caracter del conjunto [a-z_]
  • que esté seguida de cualquier caracter alfanumérico o símbolo de subrayado
  • cualquier número de veces. El asterisco significa 0 o más ocurrencias.

Esto es, el patrón identificará, por ejemplo:


Código:
_hola
h
hola
hola2
pero no identificará


Código:
2hola
En otras palabras, la expresión regular detecta todos los identificadores válidos en la sintaxis de Pascal.

Otro ejemplo de expresión regular:


Código:
'.*'
detecta todo lo que esté entre apóstrofes '. El punto . indica cualquier caracter y el asterico, como antes, indica 0 o más ocurrencias. Como es de esperarse, la expresión detectará todas las cadenas dentro del código Delphi. Pero este caso presenta un problema. Si en el código pascal encontramos algo como:


Código:
Cadena := 'esta es ' + 'una cadena';
se resaltará, según se ve, también el símbolo +, lo cual es incorrecto. Esto es así porque el patrón detecta todo entre los apóstrofes de los extremos, y eso incluye los apóstrofes de enmedio.

Para evitar esto hay que utilizar la directiva ? para indicar que se detecte "lo mínimo posible":


Código:
'.*?'

Con esto, el compilador de expresiones regulares parará en el segundo apóstrofe indicando que la cadena 'esta es ' coincide con el patrón y volverá a comenzar en el tercer apóstrofe deteniéndose nuevamente en el cuarto indicando que 'una cadena' también satisface el patrón.

Una situación similar se presenta con los bloques de comentarios. La expresión regular sería:


Código:
{.*?}
Es decir, sustituyendo los apóstrofes por llaves. Sólo que en este caso hay otra consideración a tener en cuenta. Las llaves tienen un significado especial dentro de una expresión regular- sirven para expresar más precisamente el número de ocurrencias, por ejemplo


Código:
[a-z]{3,4}
es un patrón que detecta porciones de texto con tres o cuatro letras exactamente.

Para poder incluir las llaves (y otros caracteres especiales) como parte de la expresión regular, deben "escaparse" con el símbolo de escape \. Así, la expresión para bloques de comentarios quedaría:


Código:
\{.*?\}
Ahora bien, la sintaxis de Delphi permite otros dos tipos de comentarios, los encerrados entre (* y *) y los comentarios de línea que comienzan con //. Las expresiones regulares serían:


Código:
\(\*.*?\*\)

//.*?\n
Notemos que los paréntesis y asteriscos deben escaparse ya que tienen un significado especial en una expresión regular.

\n, en los comentarios de línea significa "final de línea", de manera que el patrón detectará todo lo que comience con // y termine cuando termine la línea.

Dos expresiones regulares, X y Z, pueden unirse con el operador | de disyunción:


Código:
X|Z
indicando que una porción de texto coincidirá con el patrón si coincide con X O si coincide con Z. Podemos entonces agrupar las distintas clases de comentarios en un sólo patrón:


Código:
\{.*?\}|\(\*.*?\*\)|//.*?\n|//.*$

Aquí agregué


Código:
//.*$
para abarcar el caso especial de un comentario de línea que esté al final del archivo.


Código:
unit Hola;

interface

implementation

end.

// esto es todo amigos
En este caso no se encontrará \n puesto que no hay cambio de línea. El símbolo $ indica "fin de texto".


Con esto detectamos las partes más importantes para el resaltado de código pascal:
  • identificadores
  • cadenas de caracteres
  • bloques de comentarios

PHP incluye varias funciones para el manejo de expresiones regulares tipo Perl. La que usé en el resaltador es preg_replace_callback:


Código PHP:
echo preg_replace_callback("#$reg_exp#si"'replace'$code
El primer parámetro es la expresión regular. Toda expresión regular debe encerrarse entre dos caracteres iguales (# en este caso). Puede ser cualquier caracter que no forme parte de la expresión regular ni sea un caracter especial. Después del caracter de cierre se ponen modificadores de la expresión. Aquí, i significa que las coincidencias son indiferentes a mayúsculas o minúsculas, esto es, da lo mismo procedure que PROCEDURE. Sin este modificador, la expresión regular para los identificadores (ver arriba) sólo serviría para los escritos en minúsculas. El modificador s sirve para detectar los cambios de línea \n.

Ahora bien, lo que yo paso en $reg_exp, es la concatenación de todas las expresiones regulares descritas:


Código PHP:
$reg_exp = ($rgxp_comment)|($rgxp_quote)|($rgxp_ident
donde cada una de las tres variables, $rgxp_comment, $rgxp_quote y $rgxp_ident son las expresiones de comentarios, cadenas e identificadores. Todas están unidas por la disyunción | significando que habrpá una coincidencia si coincide con alguna de esas expresiones. Además, todas están encerradas entre paréntesis. Ya había mencionado que los paréntesis son especiales; sirven para agrupar expresiones. Estas agrupaciones nos servirán al momento de reemplazar las coincidencias ya que es necesario identificar con qué parte (o grupo) de la expresión se encontró una coincidencia.

Básicamente, cada coincidencia se reemplazará con el mismo texto encontrado pero rodeado de etiquetas <span>, por ejemplo, en


Código:
cadena := 'esta es una cadena';
la cadena 'esta es una cadena' se reemplazará con:


Código:
<span class="quote">'esta es una cadena'</span>
Así, el texto final se combinará con una hoja de estilo CSS que indicará de qué color y formato se marcan los distintos <span>.

El tercer parámetro de preg_replace_callback es el texto que deseamos resaltar y el segundo parámetro es el nombre de una función que es la que efectuará los reemplazos:


Código PHP:
function replace($matches)
{
  ...

preg_replace_callback analiza todo el texto pasado en el tercer parámetro y llamará a nuestra función por cada coincidencia que encuentre pasando un arreglo ($matches) como parámetro.

En este arreglo, el primer elemento, $matches[0] contiene la porción de texto que haya coincidido, $matches[1] la parte que haya concidido con el primer grupo, $matches[2] la parte que haya coincidido con el segundo grupo, etc.

En nuestra función de reemplazo tenemos entonces que comparar $matches[0] con cada grupo para saber qué reemplazar:


Código PHP:
function replace($matches)
{
  switch (
$matches[0])
  {
    case 
$matches[1]: // comentario
      
return "<span class='comment'>$matches[0]</span>";
      break;

    case 
$matches[2]: // cadena
      
return "<span class='quote'>$matches[0]</span>";
      break;

    case 
$matches[3]: // identificador
      
...
      break;
  }


Como se ve, la función debe regresar el texto reemplazado. En el caso de identificadores, no todo identificador es una palabara reservada, así que debemos cotejar el identificador contra una lista de palabras reservadas:


Código PHP:
case $matches[3]: // identificador
  
if (in_array($matches[0], $keywords))
    return 
"<span class='keyword'>$matches[0]</span>";
  else
    return 
$matches[0]; 
es decir, reemplazas si el identificador se encuentra en el arreglo $keywords que previamente se llena con todas las palabras reservadas. Si no coincide con ninguna, se devuelve el texto sin reemplazar. También se podría optar por resaltar los identificadores que no son palabras reservadas:


Código PHP:
case $matches[3]: // identificador
  
if (in_array($matches[0], $keywords))
    return 
"<span class='keyword'>$matches[0]</span>";
  else
    return 
"<span class='ident'>$matches[0]</span>"

Esto más o menos cubre todo lo necesario para el resaltado. Cabe notar que podríamos simplificarlo usando preg_replace en lugar de preg_replace_callback. Una vez para los comentarios, otra vez para las cadenas y una tercera vez para las palabras reservadas (preg_replace acepta un areglo como parámetro indicando que han de reemplazarse todos los elementos que encuentre en el arreglo), pero me pareció más flexible así ya que además podemos ampliar la expresión regular para abarcar, por ejemplo:
  • directivas al compilador
  • números (enteros, reales o hexadecimales)
  • símbolos (, ; < > = @ etcétera)
  • código en ensamblador (directiva asm en Delphi)

Obviamente, conviene un mediano entendimiento del uso de expresiones regulares para lo cual, además del mismo manual de PHP, podrás encontrar infinidad de tutoriales en la red. Yo, de hecho aprendí con éste.

// Saludos
Responder Con Cita
  #5  
Antiguo 13-12-2005
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.114
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Enhorabuena Román, explicación y ayuda excelentes.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #6  
Antiguo 13-12-2005
Avatar de ContraVeneno
ContraVeneno ContraVeneno is offline
Miembro
 
Registrado: may 2005
Ubicación: Torreón, México
Posts: 4.738
Poder: 24
ContraVeneno Va por buen camino
Maese Roman, que bárbaro
__________________

Responder Con Cita
  #7  
Antiguo 13-12-2005
Avatar de D-MO
D-MO D-MO is offline
Miembro
 
Registrado: ago 2005
Ubicación: root@debian:/#
Posts: 1.042
Poder: 20
D-MO Va por buen camino
Interesante la información Roman, la verdad es que estoy interesado en tratar de hacer algo asi para una web.


Código PHP:
echo 'saludos';
 
//jejeje 
Responder Con Cita
  #8  
Antiguo 14-12-2005
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 28
jachguate Va por buen camino
Este mensaje de roman me parece un excelente tutorial de expresiones regulares en español. De hecho, será mi punto de referencia dentro y fuera del club para los neófitos en este tema.

Gracias por tan excelente contenido, amigo roman.

Saludos.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #9  
Antiguo 14-12-2005
Migpal Migpal is offline
Miembro
 
Registrado: jul 2005
Ubicación: Colombia
Posts: 91
Poder: 19
Migpal Va por buen camino
Si Gunman sabía quien le responderia la duda, porque no le manda un Mail en lugar de tener que rogar publicamente que le contesten.

Es una sugerencia......
Responder Con Cita
  #10  
Antiguo 14-12-2005
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto


// Saludos
Responder Con Cita
  #11  
Antiguo 14-12-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Cita:
Empezado por Migpal
Si Gunman sabía quien le responderia la duda, porque no le manda un Mail en lugar de tener que rogar publicamente que le contesten.

Es una sugerencia......
Si lo hubiera hecho, hubiesemos perdido el excelente mensaje de roman.

¿Hubieses preferido prescindir de este hilo completo?

saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 14:05:38.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi