2011-03-09 84 views
5

我想创建解析器,并在peg.js表达式语法,让我做这些事帮助创建peg.js解析器

基本上我希望在一个面具来传递,并有多个输出。

面具有这些能力。

1)生成0-9(字符n用于表达之间的随机数?)
2)生成x和y((X,Y)之间的随机数用于表达?)
3)文字数是有效(希望什么需要expession?)
4)重复先前表达式x倍({X}中表达?)
5)重复(x和y倍之间先前表达式{X,Y}中表达?)

所以一个例子表达式可能是

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

上面提出的表达式语法只是一个例子,它可以改变。

任何人都可以在peg.js中为此创建解析器提供帮助吗?

回答

17

这个想法是让它生成一个JavaScript函数,它在执行时会根据掩码返回一个随机字符串。

文字数字是0到9之间的任何字符,因此使其生成一个返回自身的函数。

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

然后n是一个随机数。同样,这会生成一个返回随机数的函数。我添加了+ ''在返回之前将其转换为字符串。

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

(a,b)语法,ab是数字,所以我们需要让它解析,并返回一个数字。从计算器示例使用声明:

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

然后我们就可以转移到创建一个规则(a,b)语法。

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

因此,这些三件事情(literal_number,RANDOM_NUMBER,random_number_between)组合成生成一个有效的功能的单个表达式。

single_expression 
= random_number 
/random_number_between 
/literal_number 

单个表达,随后{n}{a,b}形式重复表达式。单一表达也是重复表达,重复一次。

重复表达式的思想是,给定一个函数,返回一个调用输入函数N次的函数,收集结果并返回它。

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 

最后,重复的表达式可以放在一起以便连接。

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

最后,您需要一个起点,它定义了一个掩码。最后一位扫描返回的表达式生成一个函数,然后调用它。 将以下内容放在顶部,当您在线试用时,它会根据您的面具生成一串数字。

mask 
= ex:expression 
{ return ex() } 

实施例运行:027n(5,9){4}n12{2,8}(2,4)给出0271568891222224

+1

哇, 这实际上应该在peg.js文档中 这是一个比他们有更好的教程! 非常感谢。 – Hailwood 2011-03-09 20:54:57

+0

顺便说一句,我想你在你的例子答案中有几个流氓'11'。 – Hailwood 2011-03-09 21:03:12

+0

嗯,即时通讯仍然困惑了一下,我试图做出一个规则说,如果它不符合任何其他规则只是返回自己。我怎么能这样做? – Hailwood 2011-03-10 00:55:13