Separar Cadenas por caracteres
Que tal tenia un buen sin pasar por aqui pero debido a que siempre encuentro las soluciones regrese.... jejeje :)
Bueno Resulta que estoy realizando un analizador léxico para un lenguaje que definí (en sintesis es la sintaxis del lenguaje java al español con palabras reservadas y esas cosas obvio no todas solo algunas) pero tengo problemas a la hora de separar las cadenas por caracteres, pues mi idea es leer el archivo de texto, después ya que tenga su contenido ahora si separar las cadenas de entrada por caracteres especiales para realizar los tokens necesarios. El detalle es que realizo bien la lectura de cada linea del archivo pero cuando trato de separar la cadena no logro hacer que funcione(si la separo con espacio si funciona pero lee la linea completa por eje: System.out.print()). Esto es lo que llevo:
Sintesis de como funciona: en archivos .txt separo lo que son palabras reservadas,caracteres especiales, de esa manera comparo el contenido del .txt de reservadas para palabras reservadas y el .txt de caracteres especiales los caract. esp.
public void get_Cadenas(String cadena[],String caracter[])
{
String cadenas_Aux[] = new String[cadena.length];
String cadenaAux="";
for(int i=0;i<cadena.length;i++)
{
cadenas_Aux = cadena[i].split(caracter[i]);
cadenaAux+=cadenas_Aux[i];
}
}
Pero truena igual si trato de hacer esto pasa lo mismo:
{
for(int x=0;x<caracter.length;x++)
{
cadenas_Aux = cadena[i].split(caracter[i]);
cadenaAux+=cadenas_Aux[i];
}
}
Con esto si funciona pero toma toda la linea porque separo por espacios:
String unir = "";
for (int z = 0; z < str.length; z++) {
unir += str[z] + " ";
}
String re = "";
StringTokenizer cadena = new StringTokenizer(unir);
while (cadena.hasMoreTokens()) {
re += " " + cadena.nextToken().trim();
}
return re;
}
La idea es que yo lea esta cadena: Pantalla.Imprime("hola");
y separé la cadena así: Pantalla, . , Imprime , (, "hola", ) , ;
Lo que yo hago es que el contenido del programa fuente lo recibo como el 1er parametro y el 2° parametro es el de los caracteres especiales para comparar de uno en uno y así separar las cadenas cuando encuentre un caracter especial.
Espero no haberlos confundido tanto con la solución que quiero tener.
Que esten de lo mejor y espero sus respuestas!
Saludos y gracias!...
- Inicie sesión o regístrese para enviar comentarios
No se entiende que quieres
No se entiende que quieres lograr, pero puedes utilizar el metodo toCharArray que trae el objeto String.
Sobres
pues...
depende qué tan correcto quieres que sea el análisis. El ejemplo concreto de separar
Pantalla.Imprime("hola");
lo resuelves fácil con una expresión regular o bien recorriendo caracter por caracter la cadena, para separar un nuevo elemento cada que encuentras un caracter especial. Pero te falta algo muy importante: contexto.Porque el programa que únicamente separa por los caracteres especiales, te va a dar igual una lista para cadenas inválidas. Si estás pensando en hacer la validación de los tokens posteriormente entonces no tienes tanta bronca. Pero así como te puede devolver una lista de
Pantalla, ., imprime, (, "hola", )
igual te puede devolver los elementos paracad)enas.(invali;das.)
Tok tok, ¿Quién e(n)s?
Hola pues aquí de pasada te dejo un pequeño ejemplo de lo que entendí que quieres hacer. No es la mejor ni la más óptima de las formas pero es la más sencilla que se me ocurre, y tronaría si primero se comparara ‘=’ que ‘==’ vale : ).
Seguro algún compañeros de la comunidad te dirán que tema de compiladores o XXX cosa es la que debes de estudiar para que tu programa sea algo decente.
Bueno pues te dejo mi ejemplo:
import org.junit.Test;
/**
*
* @author rodrigo.salado
*/
public class LexTest {
/**
* Test of scann method, of class Lex.
*/
@Test
public void testScann() {
Lex lex = new Lex();
String codigo = ""
+ "a=13;"
+ "b = 14;"
+ "r =a+b- 23+ 45;"
+ "imprime r;"
+ "System.out.println('hola');";
lex.escanea(codigo);
}
}
import java.util.ArrayList;
import java.util.List;
/**
*
* @author rodrigo.salado
*/
public class Lex {
private List<String[]> listaTokens = new ArrayList<String[]>();
private String[] FUNCIONES = {
"System",
"out",
"println",
"imprime",
"mayusculas",
"==",
"=",
"+",
"-",
".",
"(",
")",
"'"
};
public void escanea(String codigo) {
for (String sentencia : codigo.split(";")) {
separaFunciones(sentencia);
}
for (String[] tokens : listaTokens) {
for (String token : tokens) {
System.out.print("[" + token + "]");
}
System.out.println("");
}
}
private void separaFunciones(String sentencia) {
for (String funcion : FUNCIONES) {
if (sentencia.contains(funcion)) {
sentencia = sentencia.replace(funcion, " " + funcion + " ");
}
}
String[] tokens = sentencia.replaceAll("\\s+", " ").trim().split(" ");
listaTokens.add(tokens);
}
}
Salida
[b][=][14]
[r][=][a][+][b][-][23][+][45]
[imprime][r]
[System][.][out][.][println][(]['][hola]['][)]
Te agradecería una retroalimentación para ver cómo quedo al final.
Saludos a todos : )
Re: Tok tok, ¿Quién es?, Es Groovy
Estoy estudiando Groovy en mis pocos ratos libres y decidí ver cómo hacer mi ejemplo más chido (groovy).
Sé que esto iría en otro hilo, pero… ¿Qué opinan del código en Groovy?, algunos consejos.
También me lo eche en Haskell, pero no me salió nada bonito para mostrar, eso de plano no viene al caso aquí. (: S)
funciones = ["System","out","println","imprime","mayusculas","==","=","+","-",".","(",")","'"]
codigo = """a = 3;
b = 14;
r =a+b- 23+ 45;
imprime r;
System.out.println('hola');"""
def escanea(String codigo){
codigo.split(";").each({sentencia -> separaFunciones sentencia})
listaTokens.each({tokens -> tokens.each({token -> print "[" + token + "]"}) println ""})
}
def separaFunciones(String sentencia){
funciones.each({funcion -> sentencia = sentencia.replace(funcion, " " + funcion + " ")});
listaTokens.add sentencia.replaceAll("\\s+", " ").trim().split(" ")
}
escanea codigo
Saludos a todos. : )
paréntesis
Rodrigo, aprovecha la azúcar sintáctica de Groovy que te permite omitir los paréntesis cuando sólo pasas un argumento a un método (de hecho esa veo que sí la usas), y la que te permite poner un closure afuera de los paréntesis cuando es el último argumento de un método. Es decir:
objeto.metodo(Object a, Object b, Closure c)
//los puedes llamar así
objeto.metodo parametro
objeto.metodo(parm1, parm2) { closure }
Y recuerda que si tienes closures donde no declaras parámetros, por default son de un parámetro sin tipo llamado
it
. Aprovecha también los Gstrings, y los strings especiales para regex... Ah y recuerda algunos métodos adicionales que simulan sobrecarga de operadores, como +, << etc (aunque ya es cuestión de gustos). Entonces:codigo.split(";").each { separaFunciones it }
listaTokens.each { it.each { token -> print "[$token]" } println() }
}
void separaFunciones(String sentencia){
funciones.each { sentencia = sentencia.replace(it, " $it ") }
listaTokens << sentencia.replaceAll(/\s+/, " ").trim().split(" ")
}
Epifanía Groovy.
Jajaja bueno no para tanto. Muchas gracias por los consejos, y que fumadas están unas cosas, como <<, también jugando un poco le quite el tipo a los métodos (los infiere, que padre), eso me gustó mucho, lo del ‘it’ en los closures es algo muy útil, también me gustó mucho, no sé si Haskell lo tenga… hoy lo investigo. En fin que bonito lenguaje.
codigo.split(";").each { sentencia ->
funciones.each {sentencia = sentencia.replace(it, " $it ")};
listaTokens << sentencia.replaceAll(/\s+/, " ").trim().split(" ")
}
listaTokens.each {it.each {token -> print "[$token]"} println()}
}
@JEMZ Disculpa por agárrame de tu hilo y espero que te sirva de algo todo lo anterior.
no los infiere
Groovy no infiere los tipos. Simplemente le valen madres, recuerda que es un lenguaje de tipado dinámico. Le puedes pedir intValue o substring a un arreglo o un Object o lo que quieras, en runtime resuelve si contesta o no.
Duck typing
Cierto olvide eso, solo para ejemplificar esto:
def aulla(){def sonido = 'Guauuuu!!!'}
}
class Lobo{
def aulla(){def sonido = 'Auuuuuu!!!'}
}
class Gato{
def maulla(){def sonido = 'Miauuuu!!!'}
}
animales = [new Perro(), new Lobo(), new Gato()]
animales.each {
println it.metaClass.respondsTo(it, "aulla").isEmpty() == false?
it.aulla():
it.maulla()
};
/*
animales.each { //El gato truena
println it.aulla()
};
*/
Guauuuu!!!
Auuuuuu!!!
Miauuuu!!!
Ejemplo de cómo crear y redefinir métodos dinámicos:
def foo(){}
}
gato = new Gato()
assert gato.metaClass.respondsTo("maulla").isEmpty()
gato.metaClass."maulla" = {-> "Miauuuu!!!"}
assert !gato.metaClass.respondsTo(gato, "maulla").isEmpty()
println gato.maulla()
gato.foo()
gato.metaClass."foo" = {-> "fooMensaje!!!"} // Esto es una fregonería :)
println gato.foo()
Miauuuu!!!
fooMensaje!!!
Fuentes:
http://en.wikipedia.org/wiki/Duck_typing
http://groovyconsole.appspot.com/script/135001
http://groovy.codehaus.org/ExpandoMetaClass+-+Dynamic+Method+Names