2011-03-09 57 views
2

我有一套面具自定义规则解析器

面具看起来像这样

'09 {2,9-} n的(6)”
//读取为09
// [2之间和数字9]
// [随机数] [重复表达6倍]

'029n(7,10)'
//读取为029
// [随机数] [重复表达和10之间的7倍]

'029n(2,5){8,15}(7,10)N'
//读取为029
// [随机数] [重复2至5倍的表达]
// [8和15之间的随机数] [重复之间7个10倍的表达]
// [随机数]

作为一个例子expession 3将工作出作为
“029n(4){4 ,9}(7)n'
'029nnnn {4,9} {4,9} {4,9} {4,9} {4,9} {4,9} {4,9} n
'029nnnn {5} {9} {4} {8} {5} {9} {9} n
“029nnnn5948599n”
“029023559485999”

我需要使用JavaScript编写一个解析器,可以基于这些规则的字符串。 请注意,这是不验证,它是字符串生成。

最好的办法是做什么?

+0

即时通讯思想第一步会做找到所有'(1,10)//(5)'的扩大背后的表达乘以x量? – Hailwood 2011-03-09 03:32:14

+0

接下来的步骤是找到所有'{1,8}''并用1和8之间的数字替换它们? – Hailwood 2011-03-09 03:33:30

+0

最后用随机数 – Hailwood 2011-03-09 03:33:57

回答

3

试用一个自定义分析器。用作,

var generator = new PatternGenerator('09{2,9}n(6)'); 
generator.generate(); // 096555555 
generator.generate(); // 095000000 

结算这example

而且构造函数,

function PatternGenerator(pattern) { 
    var tokens = null; 

    this.generate = function() { 
     var stack = []; 
     tokens = pattern.split(''); 

     // Read each token and add 
     while (tokens.length) { 
      var token = lookahead(); 
      if (isDigit(token)) { 
       stack.push(consumeNumber()); 
      } 
      else if (token == "n") { 
       stack.push(consumeVariableNumber()); 
      } 
      else if (token == "(") { 
       var topObject = stack.pop(); 
       stack.push(consumeRepetition(topObject)); 
      } 
      else if (token == "{") { 
       stack.push(consumeVariableRangeNumber()); 
      } 
      else { 
       throw new Error("Invalid input"); 
      } 
     } 
     return stack.join(''); 
    } 

    // [0-9]+ 
    function consumeNumber() { 
     var number = ""; 
     while (isDigit(lookahead())) { 
      number += consume(); 
     } 
     return number; 
    } 

    // "n" 
    function VariableNumber() { 
     var number = generateRandomNumber(); 

     this.toString = function() { 
      return Number(number); 
     }; 
    } 

    function consumeVariableNumber() { 
     consume(); 
     return new VariableNumber(); 
    } 

    // {x, y} 
    function VariableRangeNumber(start, end) { 
     var number = generateRandomNumberBetween(start, end); 

     this.toString = function() { 
      return Number(number); 
     }; 
    } 

    function consumeVariableRangeNumber() { 
     consume(); // { 
     var firstNumber = consumeNumber(); 
     consume(); // , 
     var secondNumber = consumeNumber(); 
     consume(); // } 
     return new VariableRangeNumber(firstNumber, secondNumber); 
    } 

    // <expression>(x) 
    function Repeat(object, times) { 
     this.toString = function() { 
      var string = ""; 
      for (var i = 0; i < times; i++) { 
       string += object; 
      } 
      return string; 
     }; 
    } 

    // <expression>(x, y) 
    function RepeatWithRange(object, start, end) { 
     var times = generateRandomNumberBetween(start, end); 

     this.toString = function() { 
      return new Repeat(object, times).toString(); 
     }; 
    } 

    function consumeRepetition(object) { 
     consume(); // (
     var firstNumber, secondNumber; 
     var firstNumber = consumeNumber(); 
     if (lookahead() == ",") { 
      consume(); // , 
      secondNumber = consumeNumber(); 
     } 
     consume(); //) 

     if (typeof secondNumber == 'undefined') { 
      return new Repeat(objectToRepeat, firstNumber); 
     } 
     else { 
      return new RepeatWithRange(object, firstNumber, secondNumber); 
     } 
    } 

    // Helpers to generate random integers 
    function generateRandomNumber() { 
     var MAX = Math.pow(2, 52); 
     return generateRandomNumberBetween(0, MAX); 
    } 

    function generateRandomNumberBetween(min, max) { 
     return Math.floor(Math.random() * (max - min + 1)) + min; 
    } 

    function lookahead() { 
     return tokens[0]; 
    } 

    function consume() { 
     return tokens.shift(); 
    } 

    function isDigit(character) { 
     return /\d/.test(character); 
    } 
}