Autor Tema: [Reto] Parser  (Leído 2604 veces)

Desconectado good

  • PHPerit@
  • *
  • Mensajes: 49
  • Karma: 0
  • Nuev@ PHPer@
    • Ver Perfil
[Reto] Parser
« en: 13 de Agosto de 2011, 18:17:00 pm »
Hola
La idea es crear un script que parsee un string

la idea es crear como un pequeño lenguaje de programación. Las normas son:

Siempre que el script detecte un comentario (una linea que empieza con el carácter #) no la imprime
Si el programa encuentra un texto en forma $abc (donde abc es una secuencia no vacía de letras mayúsculas [A-Z], minúsculas [a-z], dígitos [0-9] o el carácter _ (subrayado)), entonces sabremos que estamos hablando de una variable, siempre que empiece con el carácter $.
Cada vez que el programa encuentre una variable ésta se substituirá por el valor de la variable, que por defecto será "nil" (en este problema no se dan valores a las variables, simplemente tienen un valor fijo)

En cualquier otro caso, el programa no substituye la secuencia

EJEMPLO DE ENTRADA:
# hola soy un comentario $variable $$hola
EJEMPLo DE SALIDA:
NADA (no se imprime nada, una linea en blanc)

EJEMPLO DE ENTRADA:
    $soy_variable $$$ $y_yo_123
EJEMPLo DE SALIDA:
    nil $$$ nil

EJEMPLO DE ENTRADA:
    $$$ $ $$$ $ $asd $343_34-holamundohola
EJEMPLo DE SALIDA:
    $$$ $ $$$ $ nil nil-holamundohola



No se pueden usar expresiones regulares
la solución puede ser por ejemplo una función, o un código con una variable con el string, eso no importa

fuente: olimpiada informática española
« Última modificación: 13 de Agosto de 2011, 18:25:18 pm por good »

Comunidad PHPeros

[Reto] Parser
« en: 13 de Agosto de 2011, 18:17:00 pm »

Desconectado Farresito

  • PHPero Avanzado
  • ****
  • Mensajes: 385
  • Karma: 5
  • Sexo: Masculino
  • PimPamTomaC++
    • Ver Perfil
    • Farresito
Re:[Reto] Parser
« Respuesta #1 en: 13 de Agosto de 2011, 18:25:48 pm »
Hombre, lenguaje de programación está lejos lejos. Esto es sencillo de hacer con cualquier lenguaje. Si me animo, lo hago en C y a ver que tal queda.

Por cierto, la idea es buena :)
“Lo mejor de los booleanos es que si te equivocas estás a un sólo bit de la solución correcta.”

-- Anónimo

"No temo a los ordenadores; lo que temo es quedarme sin ellos"

-- Isaac Asimov

Desconectado good

  • PHPerit@
  • *
  • Mensajes: 49
  • Karma: 0
  • Nuev@ PHPer@
    • Ver Perfil
Re:[Reto] Parser
« Respuesta #2 en: 13 de Agosto de 2011, 18:33:07 pm »
Hombre, lenguaje de programación está lejos lejos. Esto es sencillo de hacer con cualquier lenguaje. Si me animo, lo hago en C y a ver que tal queda.

Por cierto, la idea es buena :)

quizás php no sea el lenguaje más sencillo de usar para esto, yo recomiendo usar c++

Desconectado Farresito

  • PHPero Avanzado
  • ****
  • Mensajes: 385
  • Karma: 5
  • Sexo: Masculino
  • PimPamTomaC++
    • Ver Perfil
    • Farresito
Re:[Reto] Parser
« Respuesta #3 en: 13 de Agosto de 2011, 18:41:18 pm »
Me refiero a que dices que vamos a crear un pequeño lenguaje de programación, cuando esto no es más que un programa que lee un archivo y lo modifica ;)
“Lo mejor de los booleanos es que si te equivocas estás a un sólo bit de la solución correcta.”

-- Anónimo

"No temo a los ordenadores; lo que temo es quedarme sin ellos"

-- Isaac Asimov

Desconectado good

  • PHPerit@
  • *
  • Mensajes: 49
  • Karma: 0
  • Nuev@ PHPer@
    • Ver Perfil
Re:[Reto] Parser
« Respuesta #4 en: 13 de Agosto de 2011, 18:45:33 pm »
simplemente pido un script o programa que lea un string y la parsee, no quiero que sea muy complicado, esa es la idea

Desconectado Farresito

  • PHPero Avanzado
  • ****
  • Mensajes: 385
  • Karma: 5
  • Sexo: Masculino
  • PimPamTomaC++
    • Ver Perfil
    • Farresito
Re:[Reto] Parser
« Respuesta #5 en: 13 de Agosto de 2011, 18:49:53 pm »
Por cierto, confío en que tengas la solución. Yo no voy a postear y haber hecho el trabajo que otro tenía que hacer hasta que haya alguna prueba.
“Lo mejor de los booleanos es que si te equivocas estás a un sólo bit de la solución correcta.”

-- Anónimo

"No temo a los ordenadores; lo que temo es quedarme sin ellos"

-- Isaac Asimov

Desconectado good

  • PHPerit@
  • *
  • Mensajes: 49
  • Karma: 0
  • Nuev@ PHPer@
    • Ver Perfil
Re:[Reto] Parser
« Respuesta #6 en: 13 de Agosto de 2011, 21:26:43 pm »
tengo una solución de coste lineal en c++

Desconectado nmartin021

  • PHPero Avanzado
  • ****
  • Mensajes: 250
  • Karma: 9
    • Ver Perfil
Re:[Reto] Parser
« Respuesta #7 en: 23 de Septiembre de 2011, 02:35:51 am »
Mañana editare este mensaje con la solucion porque la tengo pensada, pero ahora no puedo decirla porque estoy en el mobil :P
Pero basicamente primero borro los comentarios, luego busco las variables caracter a caracter de un array hecho con explode('$')
Pd: espero que esto sea un reto de verdad y no alguien que necesita un script ;)
EDIT:
Dejo el código por la mitad, porque la verdad es que sin expresiones regulares se me hace imposible :S
EDIT 2:
Te dejo el código usando una expresiones regulares (una sóla vez) para dar alguna idea a los demás y que se animen a hacerlo sin expresiones regulares :D

<?php
/*** Parser ****/
function showVars($string){
	
return 
preg_replace(&#39;/\$([a-z0-9_]+)/si&#39;, &#39;nil&#39;, $string); //sustituir variables por &#39;nil&#39;
}
$string = &#39;
#############################
#comentarios $algo $nil
#### asdasd \#adasd asd
Hola $nombreespero que te sientas comodo en nuestro nuevo lenguaje de programacion :D
Se llama $nombre
#esto es un comentario&#39;;
$string trim($string); //que los espacios no causen problemas
$ex explode("\r\n"$string); //obtenemos cada linea en un array
$ac count($ex);
for(
$i=0;$i<$ac;$i++){ // recorrer el array para eliminar los comentarios
	
if(
substr($ex[$i],0,1)==&#39;#&#39;){ unset($ex[$i]); }
//ya tenemos el code sin comentarios
$s implode(&#39;<br />&#39;, $ex); //ponemos los saltos de linea en si sitio
$s showVars($s); //obtenemos variables
echo $s//y mostramos el resultado
?>
« Última modificación: 23 de Septiembre de 2011, 15:30:30 pm por nmartin021 »

Desconectado good

  • PHPerit@
  • *
  • Mensajes: 49
  • Karma: 0
  • Nuev@ PHPer@
    • Ver Perfil
Re:[Reto] Parser
« Respuesta #8 en: 30 de Septiembre de 2011, 14:29:01 pm »
no es correcto, ten en cuenta que los comentarios no solo se declaran en el primer caracter, puede ser "         #   comentario"

además, creo haber dejado bien claro que no hay que usar expresiones regulares! XDD

Desconectado nmartin021

  • PHPero Avanzado
  • ****
  • Mensajes: 250
  • Karma: 9
    • Ver Perfil
Re:[Reto] Parser
« Respuesta #9 en: 07 de Septiembre de 2012, 21:28:04 pm »
Siento revivir esto, pero... tengo la solución: (hecho por mi desde cero)
<?

// $nil - Lenguaje creado con PHP

/*

  - Reglas:

 * $[algo] se reemplaza con "nil"

 * Sin expresiones regulares

 * Los comentarios empiezan con # y pueden estar al principio o al final (o en medio) de una línea

  - NOTA:

 * Hay un bug - no te acepta la variable si es el primer caracter del código...

*/

class Nil{

        private 
$code// code to parse

        
private $vars = array(); // code variables

        
var $anv false// true para aceptar $123, false para no aceptarlo



        // definir codigo

        
function __construct($code){

                if(!
$code){ return false; }

                
$this->code $code;

        }

        

        
// devolver codigo; al ser protected no se puede acceder públicamente

        
function getCode(){ return $this->code; }

        

        
// procesar otro codigo

        
function setCode($code){ $this->code $code; }

        

        
// borrar comentarios

        
function removeComments(){

                
$e explode("\n"$this->code);

                for(
$i=0,$c=count($e);$i<$c;$i++){

                        if(
$e[$i][0] == &#39;#&#39;){

                                
unset($e[$i]);

                        }elseif((
$s strpos($e[$i], &#39;#&#39;)) !== false){

                                
$e[$i] = substr($e[$i], 0$s);

                        }

                }

                
$this->code implode("\n"$e);

        }

        

        
// reemplazar variables

        
function parseVars(){

                if(
strpos($this->code, &#39;$&#39;) === false){ return; }

                
$v 0;

                while((
$v strpos($this->code, &#39;$&#39;, $v + 1)) !== false){

                        
$i $v 1;

                        if(!
$this->anv && ctype_digit($this->code[$i])) continue;

                        while(
ctype_alpha($this->code[$i]) || ctype_digit($this->code[$i]) || $this->code[$i] == &#39;_&#39;) $i++;

                        
$var substr($this->code$v$i);

                        
$this->code substr($this->code0$v).&#39;nil&#39;.substr($this->code, $i);

                
}

        }

        

        
// devolver resultado final

        
function process(){

                
$this->removeComments();

                
$this->parseVars();

                return 
$this->code;

        }

}

echo &
#39;<pre>&#39;;

// variables normales

$nil = new Nil(&#39;Test de variables: $var&#39;); // output: "Test de variables: $var"

echo $nil->process();



echo 
"\n\n\n";



echo 
"variables que empiezan por numeros - no permitidas:\n";

$nil->setCode(&#39;myVar: $123var&#39;); // output: "myVar: $123var"

echo $nil->process();



echo 
"\n\n\n";



echo 
"variables que empiezan por numeros - permitidas:\n";

$nil->anv true;

$nil->setCode(&#39;myVar: $123var&#39;); // output: "myVar: nil"

echo $nil->process();



echo 
"\n\n\n";



echo 
"comentarios:\n";

$nil->setCode(&#39;#soy un comentario de una linea&#39;); // output: ""

echo $nil->process();



echo 
"\n\n\n";



echo 
"comentarios en medio de la linea:\n";

$nil->setCode(&#39;hi bitches#comentario alone&#39;); // output: "hi bitches"

echo $nil->process();



echo &
#39;</pre>&#39;;

?>

Desconectado Physlet

  • PHPero Experto
  • *****
  • Mensajes: 822
  • Karma: 41
  • Sexo: Masculino
  • Todo es posible con esfuerzo, dedicación e interés
    • Ver Perfil
    • PanamaDev
Re:[Reto] Parser
« Respuesta #10 en: 06 de Noviembre de 2012, 17:25:47 pm »
nmartin, un dato sobre POO. Los constructores no deben retornan valores. Si ese false que retorna tu constructor es sinónimo de "error", mejor arroja una Exception.

Desconectado Animus

  • PHPero Avanzado
  • ****
  • Mensajes: 273
  • Karma: 1
  • Sexo: Masculino
  • Aprende a aprender, el resto vendrá solo.
    • Ver Perfil
Re:[Reto] Parser
« Respuesta #11 en: 28 de Enero de 2013, 09:54:24 am »
Es tan sencillo como utilizar ob_start, si me animo hago luego una Parser.


La red social de tus sueños.


Desconectado ilovepixel

  • PHPer@ Fijo
  • ***
  • Mensajes: 149
  • Karma: 9
  • Sexo: Masculino
  • Game Artist & Developer
    • Ver Perfil
    • i ■ pixel
Re:[Reto] Parser
« Respuesta #12 en: 28 de Enero de 2013, 20:33:12 pm »
No sé si será la solución más optima pero llegué a esto en js:

var s1 "  $ $$$   $Variable_3213-321         # hola soy un comentario $variable $$hola";
var 
s2 "$soy_variable $$$ $y_yo_123";
var 
s3 "$$$ $ $$$ $ $asd $343_34-holamundohola";

//Sin Regex
function nrTrace(str) {
	

	
var 
r="",
	
	
g=str.split("\n");
	
for(var 
i=0;i<g.length;i++) {
	
	
var 
l=g[i].split(" ");
	
	
for(var 
j=0;j<l.length;j++) {
	
	
	

	
	
	
if(
l[j].length>0) {
	
	
	
	
if(
l[j].indexOf("#")>=0) break;
	
	
	
	
else if(
l[j].indexOf("$")>=0) {
	

	
	
	
	
	
var 
l[j].indexOf("$");
	
	
	
	
	
if(
l[j].charAt(n+1)!="$" "-" && l[j].length>1) {
	
	
	
	
	
	
var 
l[j].split("-");
	
	
	
	
	
	
for(var 
u=0;u<y.length;u++) {
	
	
	
	
	
	
	
if(
y[u].charAt(0)=="$"r+="nil";
	
	
	
	
	
	
	
else 
r+="-"+y[u];
	
	
	
	
	
	
}
	
	
	
	
	
}else 
r+=l[j];
	
	
	
	
}
	
	
	
}
	
	
	
r+=" ";
	
	
}
	
}
	
return 
r;
}

//Con Regex
function trace(str) {
	
var 
r="",
	
	
str.split(/\n/g);
	
for(var 
i=0;i<g.length;i++) {
	
	
var 
g[i].split(/\s/g);
	
	
for(var 
j=0;j<l.length;j++) {
	
	
	
if(
l[j].indexOf("#")>=0) break;
	
	
	
else {
	
	
	
	
var 
l[j].replace(/\$[^$][0-9_a-z]+/,"nil");
	
	
	
	
r+=v+" ";
	
	
	
}
	
	
}
	
}
	
return 
r;
}

console.log("Sin Regex");
console.log(nrTrace(s1));
console.log(nrTrace(s2));
console.log(nrTrace(s3));
console.log("---------");
console.log("Con Regex");
console.log(trace(s1));
console.log(trace(s2));
console.log(trace(s3));


Lo probé en node.js y me devuelve:
Código: [Seleccionar]
Sin Regex
  $ $$$   nil-321
nil $$$ nil
$$$ $ $$$ $ nil nil-holamundohola
---------
Con Regex
  $ $$$   nil-321
nil $$$ nil
$$$ $ $$$ $ nil nil-holamundohola
« Última modificación: 28 de Enero de 2013, 20:39:20 pm por ilovepixel »

Desconectado Nasty35

  • PHPer@
  • **
  • Mensajes: 60
  • Karma: 0
  • Sexo: Masculino
  • Intento aprender
    • Ver Perfil
    • LioMet ~ Tu mejor opción
Re:[Reto] Parser
« Respuesta #13 en: 26 de Febrero de 2013, 16:34:39 pm »
Lo he hecho en Java:
package parser;

public class 
Parser {
	

	
public static 
void main(String[] args) {
	
	
System.out.println(analize("esto $mola #mazo"));
	
}
	

	
public static 
String analize(String text) {
	
	
String analized "";
	
	
if(
text.startsWith("#")) {
	
	
	
// Nada
	
	
} else {
	
	
	
for(
String linea text.split(" ")) {
	
	
	
	
if(
linea.startsWith("$")) {
	
	
	
	
	
String a "";
	
	
	
	
	
if(
linea.contains("-")) {
	
	
	
	
	
	
"-".concat(linea.split("-")[1]);
	
	
	
	
	
}
	
	
	
	
	
if(
linea.replace("$""").isEmpty()) {
	
	
	
	
	
	
analized += linea;
	
	
	
	
	
} else {
	
	
	
	
	
	
analized += "nil";
	
	
	
	
	
}
	
	
	
	
	
analized += a.concat(" ");
	
	
	
	
} else if(!
linea.startsWith("#")) {
	
	
	
	
	
analized += linea.concat(" ");
	
	
	
	
}
	
	
	
}
	
	
}
	
	
return 
analized;
	
}
	

}



<?php
class Phperos {
    
$private name;
    public static function 
setName($name) { self::name $name;  }
	
public static function 
getName() {  return self::name; }
}
Phperos::setName(&#39;Nasty35&#39;);
echo &#39;Soy &#39; . Phperos::getName();
?>