es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Gramática PEG para coincidir con una lista separada por espacios o separada por comas.

Estoy tratando de crear una gramática PEG (pegjs) simple para analizar una lista separada por espacios o una lista separada por comas de números, pero claramente me falta algo fundamental. Es decir, quiero que coincida con cadenas como “1 2 3” o “1,2,3”, pero no con una expresión mixta “1 2,3”.

Mi gramática intentada es (que se puede ejecutar en https://pegjs.org/online):

start = seq

seq = num (" " n:num {return n})*
    / num ("," n:num {return n})*

num = a:$[0-9]+ {return parseInt(a, 10)}

EOL = !.

Sin embargo, esta gramática solo analizará una lista separada por espacios. Si la modifico de la siguiente manera:

start = seq

seq = num (" " n:num {return n})* EOL
    / num ("," n:num {return n})* EOL

num = a:$[0-9]+ {return parseInt(a, 10)}

EOL = !.

analizará una lista separada por espacios o una lista separada por comas. Sin embargo, siento que no debería necesitar agregar `EOL al final de cada una de mis expresiones… Pensé que cuando se le proporciona una lista separada por comas, pegjs intentaría coincidir con una lista separada por espacios, fallaría y luego coincidiría con la regla de la lista separada por comas.

¿Qué me estoy perdiendo?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que el problema está con el orden de las alternativas en la regla seq. En la gramática actual, primero se prueba la lista separada por espacios, y solo cuando no coincide, se prueba la lista separada por comas. Esto significa que si la entrada coincide con ambas opciones (como en la expresión mixta “1 2,3”), elegirá la primera y ignorará el resto.

    Una solución a esto es modificar la regla seq para que primero intente coincidir con una lista separada por comas y, si eso falla, intente con una lista separada por espacios:

    seq = num ("," num)*
          / num (" " num)*
    

    De esta manera, si la entrada coincide con una lista separada por comas, no intentará coincidir con la regla de lista separada por espacios. Si la lista separada por comas falla, el analizador intentará con la lista separada por espacios en su lugar.

    Ten en cuenta que en esta versión no es necesario la regla EOL, ya que la regla seq coincide con toda la entrada. Además, las partes { return n } se pueden eliminar, ya que solo duplican el comportamiento predeterminado de PEG.js de devolver el texto coincidente.

    Aquí está la gramática actualizada:

    start = seq
    
    seq = num ("," num)*
          / num (" " num)*
    
    num = $[0-9]+ {
      return parseInt(text(), 10)
    }
    

    ¡Espero que esto ayude! Avísame si tienes alguna otra pregunta.

Comments are closed.