2011-03-09 99 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); 
    } 
}