2011-03-09 8 views
5

Estoy queriendo crear el programa de análisis y de sintaxis expresión en peg.js ayuda para crear peg.js que permitirían que haga estas cosasanalizador

básicamente quiero pasar en una máscara y tener una salida de número.

la máscara tiene estas habilidades.

1) generar un número aleatorio entre 0-9 (carácter n para la expresión?)
2) generar un número aleatorio entre x e y ((x, y) para la expresión?)
3) números literales están válida (esperemos nada necesario para expession?)
4) repetir anteriores veces la expresión x ({x} para la expresión?)
5) expresión de repetición previa entre x e y tiempos ({x, y} para la expresión?)

por lo que una expresión de ejemplo podría ser

027n(5,9){4}n12{2,8}(2,4)

la sintaxis de expresión propuesta más arriba es solo un ejemplo, puede cambiar.

¿Alguien puede ayudarnos a crear el analizador para esto en peg.js?

Respuesta

17

La idea es hacer que genere una función de JavaScript, que cuando se ejecuta, devolverá una cadena aleatoria de acuerdo con la máscara.

Un número literal es cualquier carácter entre 0 y 9, por lo tanto, genere una función que se devuelve a sí misma.

literal_number 
= num:[0-9] 
{ return function() { 
    return num; 
}; } 

Luego n es para un número al azar. De nuevo, esto genera una función para devolver un número aleatorio. Agregué + '' para convertirlo en una cadena antes de volver.

random_number 
= "n" 
{ return function() { 
    return Math.floor(Math.random() * 10) + ''; 
}; } 

En la sintaxis (a,b), a y b son números, por lo que tenemos que hacer es analizar y devolver un número. El uso de la declaración de la calculadora ejemplo:

number 
= digits:[0-9]+ { return parseInt(digits.join(""), 10); } 

Entonces podemos pasar a crear una regla para (a,b) sintaxis.

random_number_between 
= "(" a:number "," b:number ")" 
{ return function() { 
    return a + Math.floor(Math.random() * (b - a + 1)) + '' 
}; } 

Así, estas 3 cosas (literal_number, random_number, random_number_between) se combinan en una sola expresión que genera una función válida.

single_expression 
= random_number 
/random_number_between 
/literal_number 

una sola expresión, seguido por {n} o {a,b} formas una expresión repetida. Una sola expresión también es una expresión repetida, repetida una vez.

La idea de una expresión repetida es, dada una función, devolver una función que llama a la función de entrada N veces, recoger el resultado y devolverlo.

repeated_expression 
= ex:single_expression "{" n:number "}" { 
     return function() { 
      var result = ''; 
      for (var i = 0; i < n; i ++) { 
       result += ex(); 
      } 
      return result; 
     }; 
    } 
/ex:single_expression "{" a:number "," b:number "}" { 
     return function() { 
      var result = ''; 
      var n = a + Math.floor(Math.random() * (b - a + 1)) 
      for (var i = 0; i < n; i ++) { 
       result += ex(); 
      } 
      return result; 
     }; 
    } 
/ex:single_expression 

Finalmente, las expresiones repetidas se pueden poner una al lado de la otra para concatenar.

expression 
= list:repeated_expression* { 
     return function() { 
      var result = ''; 
      for (var i = 0; i < list.length; i ++) { 
       result += list[i](); 
      } 
      return result; 
     }; 
    } 

Finalmente, necesita un punto de inicio, que define una máscara. Este último bit escanea la expresión que devuelve a genera una función y la llama. Ponga lo siguiente en la parte superior, y cuando lo intente en línea, generará una cadena de números según su máscara.

mask 
= ex:expression 
{ return ex() } 

Ejemplo ejecute: 027n(5,9){4}n12{2,8}(2,4) da 0271568891222224.

+1

Wow, Esto debería estar en la documentación para peg.js ¡Es un tutorial mejor que el que tienen! muy apreciado. – Hailwood

+0

Por cierto, creo que tienes un par de '11' pícaros en tu respuesta de ejemplo. – Hailwood

+0

Hmm, todavía estoy un poco confundido, estoy tratando de establecer una regla que diga que, si no coincide con otras reglas, solo se devuelve. ¿Cómo podría hacer eso? – Hailwood