0

Estoy elaborando un intérprete con expresiones regulares, ahorita estoy trabado, el problema es que quiero recordar un patrón más de 1 vez:

^(${name})${descrip.rules.skip}+(${descrip.rules.assig})${descrip.rules.skip}*(${name}|${type.decimal}|${type.num}|${type.vof}|${type.texto})${descrip.rules.skip}*(?:(\\+|-|\\/|%)${descrip.rules.skip}*(${name}|${type.decimal}|${type.num}|${type.vof}|${type.texto}))*${descrip.rules.skip}*!$

Al final uso 3 paréntesis:

  1. es todo el patrón que quiero recordar pero le puse ?: para que no sea así
  2. el puro operador
  3. el valor

Ahora quiero recordar una operaciín así: 5+4/2

Pero lo que me recuerda sólo es : 5/2

¿alguna idea de como hacer que recuerde lo demás?

DevCodeG
  • 583
  • 1
  • 7
  • 24
  • Entiendo que cosas como esta: `${type.texto}` son variables o subpatrones. Hay alguna manera de que nos puedas escribir la expresión regular completa, una vez se han interpolado estos subpatrones o variables? – Julio Oct 18 '18 at 15:12
  • `/\s*(\b[A-Za-z][A-Za-z0-9_]*\b)\s*(->)\s*(\b[A-Za-z][A-Za-z0-9_]*\b|\b[0-9]+\.[0-9]+\b|\b[0-9]+\b|verdadero|falso|".*"|'.*')\s*(?:(\+|-|\/|%)\s*(\b[A-Za-z][A-Za-z0-9_]*\b|\b[0-9]+\.[0-9]+\b|\b[0-9]+\b|verdadero|falso|".*"|'.*'))+\s*!$/g` – Salvador Miron Ramos Oct 18 '18 at 19:43
  • espero que se entienda, es para validar la asignacion a una variable, pero quiero que se puedan hacer multiples operaciones – Salvador Miron Ramos Oct 18 '18 at 19:44
  • Efectivamente es lo que imaginaba. Revisa mi respuesta, ahí detallo el problema que tienes – Julio Oct 19 '18 at 06:31
  • ¿Puedes poner casos de prueba? – Ruslan López Dec 28 '18 at 05:13

1 Answers1

1

Para explicarme lo haré con un ejemplo más sencillo.

El problema es que estás machacando los grupos de captura con búsquedas posteriores.

Por ejemplo, considera la siguiente entrada 5-4-2 y la expresión regular: (\d)(?:(-)(\d))+ que solo buscaría números y signo de restar (pero que funciona de la misma manera que tu expresión)

  • El primer grupo es el primer número
  • El segundo grupo es la operación (para simplificar, siempre resta)
  • El tercer grupo es el siguiente número

El problema es que con esta expresión: (?:(-)(\d))+ capturas -4, pero como se puede repetir por el +, luego capturas -2 y machacas los valores que tenías en el segundo y tercer grupo de captura. Siempre te quedas con lo último.

Así pues, después de ejecutarlo, el primer grupo tendría 5, el segundo - y el tercero 2

Ejemplo

Una posible alternativa sería capturar el conjunto completo de operaciones y luego ir realizando búsquedas con un bucle. Por ejemplo, para el ejemplo simplificado:

Buscaríamos: (\d)((?:-\d)+)

Ahora el segundo grupo tiene -4-2, que guardaremos en una variable. Ahora realizaremos una nueva búsqueda en esa nueva variable por (-)(\d) (con flag global g) y para cada iteración guardaremos el grupo 1 y 2 en alguna variable (como un array)

Aquí tienes todo el proceso (simplificado) con javascript:

let match = '5-4-2'.match(/(\d)((?:-\d)+)/);

let primero = match[1];
let segundo = match[2];

console.log('La segunda parte es: ' + segundo + ', Vamos a procesarla');

let operaciones = [];
let index_operaciones = 0;

const regexsegundo = /(-)(\d)/g;

while ((m = regexsegundo.exec(segundo)) !== null) {
    // Para evitar bucles infinitos con búsquedas de longitud 0
    // Si no es tu caso, puedes quitar este IF
    if (m.index === regexsegundo.lastIndex) {
        regexsegundo.lastIndex++;
    }
    
    operaciones[index_operaciones] = [];
    operaciones[index_operaciones][0] = m[1];
    operaciones[index_operaciones][1] = m[2];
    index_operaciones++
}

console.log('Resultados_________________');
console.log('Primero = ' + primero);
console.log('Luego = ');
console.log(operaciones);
Julio
  • 3,173
  • 1
  • 7
  • 23