Pegjs: ¿Cómo conservar los separadores de espacios en blanco?

Creado en 3 oct. 2019  ·  6Comentarios  ·  Fuente: pegjs/pegjs

Tipo de problema

  • Informe de error: _no_
  • Solicitud de función: _no_
  • Pregunta: _sí_
  • No es un problema: _no_

requisitos previos

  • ¿Puedes reproducir el problema?: _sí_
  • ¿Buscaste los problemas del repositorio?: _sí_
  • ¿Revisaste los foros?: _sí_
  • ¿Hiciste una búsqueda en la web (google, yahoo, etc.)?: _sí_

Estoy luchando para hacer que el analizador PEG.js mantenga los espacios en blanco originales de la ecuación.

Comportamiento actual: 2 * 5 + SUM(1, 2, 3)

[
   "2",
   "*",
   "5",
   "+",
   "SUM",
   "(",
   [
      "1",
      ",",
      "2",
      ",",
      "3"
   ],
   ")"
]

Comportamiento deseado : 2 * 5 + SUM(1, 2, 3)

[
   "2",
   " ",
   "*",
   " ",
   "5",
   " ",
   "+",
   " ",
   "SUM",
   "(",
   [
      "1",
      ",",
      " ",
      "2",
      ",",
      " ",
      "3"
   ],
   ")"
]

Gramática para copiar: https://pastebin.com/zpwqT6Uw
Zona de juegos de PEG.js https://pegjs.org/online

¿Qué me estoy perdiendo?

Comentario más útil

@marek-baranowski Otro suave ping :smiley_cat:

Además, escribí un complemento de PEG.js pegjs-syntactic-actions para facilitar la depuración de gramáticas y ver específicamente qué caracteres son capturados por qué regla independientemente de las acciones, lo que probablemente sea su problema aquí, como lo explica @StoneCypher.

El razonamiento de este complemento es: a menudo/a veces es difícil entender el resultado global cuando no es lo que esperamos, porque resulta de la combinación de muchas acciones pequeñas, y encontrar la acción que se comporta mal/extrañamente podría ser pérdida de tiempo. Con este complemento, vemos qué regla captura qué carácter y proporciona el nombre de la acción sobre la que actuar.

Todos 6 comentarios

@futagoza siento mucho molestarlo, pero es la primera vez que trato con PEG.js y este problema es fundamental para mí. ¿Puedo pedirte una pequeña pista?

Atentamente,
Marek

Traté de revisar su gramática (ayer y ahora) pero debido a que es realmente difícil de entender (dejando de lado las convenciones de nombres, el formato, para ser honesto, está por todas partes), me tomó un tiempo encontrar una solución:

  1. Las reglas que consumen espacio y datos lo devuelven (por ejemplo const devuelve [left_space, cnst, right_space] )
  2. Cualquier regla/acción que tome el resultado debe hacer algo como esto: [].concat.apply([], con)

Aún así, para ser honesto contigo, esto me parece una solución engañosa. ¿Tienes un enlace a una especificación o algo así? Sería útil saber qué reglas puedo y no puedo cambiar para obtener el resultado deseado sin la solución hacky anterior.

Si no, mientras esté dispuesto a dedicar tiempo y ordenar la gramática y cambiar el nombre de algunas reglas (para que sea más fácil descubrir lo que quiere), entonces con gusto intentaré intentarlo de nuevo 😉

@marek-baranowski - Lo siento, no vi esto hasta ahora. Espero que esto todavía te sea útil.

Si desea mantener los espacios, simplemente trátelos como contenido compatible.

No está muy claro exactamente lo que querrías para dos espacios. Puede tener una cadena de dos espacios o una matriz de dos cadenas de un espacio. Normalmente esperaría lo primero, pero... todo lo tuyo es por personaje.

Además ... ¿por qué querrías personajes perdidos como esos, excepto por la llamada a la función? El analizador debería estar resumiéndolos por ti.

De todos modos

Esto es lo que pediste:

Document = Expression*

Whitespace
  = tx:[ \r\n]+ { return tx.join(''); }

Number
  = str:[0-9]+ { return str.join(''); }

Oper
  = '+'
  / '-'
  / '/'
  / '*'
  / ','

Label
  = l:[a-zA-Z]+ { return l.join(''); }

Parens 
  = '(' Whitespace? ex:Expression* Whitespace? ')' { return ex; }

Expression 
  = Number 
  / Oper
  / Whitespace
  / Label
  / Parens
  / [^()]+

image

La cosa es que no estoy muy convencido de que sea realmente lo que quieres. Por ejemplo, en su lugar, podría analizar los números y operadores, y devolver una forma de nodo estandarizada para cada uno:

Document = Expression*

Whitespace
  = tx:[ \r\n]+ { return { 
    ast: 'whitespace', value: tx.join('') 
  }; }

Number
  = str:[0-9]+ { return {
    ast: 'number', value: parseInt(str,10)
  }; }

Oper
  = '+' { return { ast: 'oper', value: 'add' }}
  / '-' { return { ast: 'oper', value: 'subtract' }}
  / '/' { return { ast: 'oper', value: 'divide' }}
  / '*' { return { ast: 'oper', value: 'multiply' }}
  / ',' { return { ast: 'oper', value: 'sequence' }}

Label
  = l:[a-zA-Z]+ { return { 
    ast: 'label', value: l.join('') 
  }; }

Parens 
  = '(' Whitespace? ex:Expression* Whitespace? ')' { 
    return { ast: 'parens', value: ex 
  }; }

Expression 
  = Number 
  / Oper
  / Whitespace
  / Label
  / Parens
  / [^()]+

Ahora todavía tiene su espacio en blanco, pero también tiene un árbol analizado adecuado, y no necesita escribir un analizador para analizar la salida de su analizador, y ahora también es muy fácil comenzar a agregar funciones regularizadas como números de línea, etc.

image

@marek-baranowski: me gustaría reducir un poco el tamaño de este rastreador de problemas

Si lo anterior es lo que necesita, ¿consideraría cerrar este problema? Gracias 😄

Si no es así, dígame por qué y lo intentaré de nuevo.

@marek-baranowski Otro suave ping :smiley_cat:

Además, escribí un complemento de PEG.js pegjs-syntactic-actions para facilitar la depuración de gramáticas y ver específicamente qué caracteres son capturados por qué regla independientemente de las acciones, lo que probablemente sea su problema aquí, como lo explica @StoneCypher.

El razonamiento de este complemento es: a menudo/a veces es difícil entender el resultado global cuando no es lo que esperamos, porque resulta de la combinación de muchas acciones pequeñas, y encontrar la acción que se comporta mal/extrañamente podría ser pérdida de tiempo. Con este complemento, vemos qué regla captura qué carácter y proporciona el nombre de la acción sobre la que actuar.

oh wow, esto es realmente genial en realidad

¿Fue útil esta página
0 / 5 - 0 calificaciones