(function(root, factory) { if (typeof module === 'object' && module.exports) { module.exports = factory(require('./nearley')); } else { root.Unparser = factory(root.nearley); } }(this, function(nearley) { var randexp = require('randexp'); function genRandom(grammar, start) { // The first-generation generator. It just spews out stuff randomly, and is // not at all guaranteed to terminate. However, it is extremely performant. var output = ""; var stack = [start]; while (stack.length > 0) { var currentname = stack.pop(); if (typeof(currentname) === 'string') { var goodrules = grammar.rules.filter(function(x) { return x.name === currentname; }); if (goodrules.length > 0) { var chosen = goodrules[ Math.floor(Math.random()*goodrules.length) ]; for (var i=chosen.symbols.length-1; i>=0; i--) { stack.push(chosen.symbols[i]); } } else { throw new Error("Nothing matches rule: "+currentname+"!"); } } else if (currentname.test) { var c = new randexp(currentname).gen(); output += c; continue; } else if (currentname.literal) { output += currentname.literal; continue; } } return output; } function genBounded(grammar, start, depth) { // I guess you could call this the second-generation generator. // All it does is bound its output by a certain depth without having to // backtrack. It doesn't give guarantees on being uniformly random, but // that's doable if we *really* need it (by converting min_depth_rule, a // predicate, into something that counts the number of trees of depth d). var rules = grammar.rules; var min_depths_rule = []; function synth_nt(name, depth) { var good_rules = []; var min_min_depth = Infinity; for (var i=0; i 0) { return genBounded(grammar, start, depth); } else { return genRandom(grammar, start); } } return Unparse; }));