text: // Generated by CoffeeScript 1.9.2
  var deep;
  
  deep = function(i) {
    return JSON.parse(JSON.stringify(i));
  };
  
  module.exports = {
    stringify: function(grammar) {
      var escape, expression, expressions, production;
      escape = function(text) {
        return text.replace(/\\/g, '\\\\').replace(/\"/g, '\"').replace(/\n/g, '\\n').replace(/\t/g, '\\t');
      };
      expression = function(e) {
        var exp, res;
        res = (function() {
          var j, len, results;
          results = [];
          for (j = 0, len = e.length; j < len; j++) {
            exp = e[j];
            if (exp.nt != null) {
              results.push(exp.nt);
            } else {
              results.push("\"" + (escape(exp.t)) + "\"");
            }
          }
          return results;
        })();
        return res.join(' ');
      };
      expressions = function(e) {
        var exp, res;
        res = (function() {
          var j, len, results;
          results = [];
          for (j = 0, len = e.length; j < len; j++) {
            exp = e[j];
            results.push(expression(exp));
          }
          return results;
        })();
        return "" + (res.join(', '));
      };
      production = function(e) {
        var exp, res, term;
        res = (function() {
          var results;
          results = [];
          for (term in e) {
            exp = e[term];
            results.push(term + " -> " + (expressions(exp)));
          }
          return results;
        })();
        return res.join('\n');
      };
      return production(grammar);
    },
    convert: function(root, grammar) {
      var cnf, hasroot, i, index, j, k, key, l, len, len1, len2, len3, m, n, ref, replace, replacementrule, rule, rules, term, visitterms;
      cnf = deep(grammar);
      visitterms = function(fn) {
        var key, results, rule, rules, term;
        results = [];
        for (key in cnf) {
          rules = cnf[key];
          results.push((function() {
            var j, len, results1;
            results1 = [];
            for (j = 0, len = rules.length; j < len; j++) {
              rule = rules[j];
              results1.push((function() {
                var k, len1, results2;
                results2 = [];
                for (k = 0, len1 = rule.length; k < len1; k++) {
                  term = rule[k];
                  results2.push(fn(term));
                }
                return results2;
              })());
            }
            return results1;
          })());
        }
        return results;
      };
      replace = function(source, target) {
        return visitterms(function(term) {
          if ((term.nt != null) && term.nt === source) {
            return term.nt = target;
          }
        });
      };
      index = 0;
      hasroot = false;
      visitterms(function(term) {
        if ((term.nt != null) && term.nt === root) {
          return hasroot = true;
        }
      });
      if (hasroot) {
        cnf["$" + root] = deep(cnf[root]);
        replace(root, "$" + root);
      }
      for (key in cnf) {
        rules = cnf[key];
        for (j = 0, len = rules.length; j < len; j++) {
          rule = rules[j];
          if (rule.length > 1) {
            for (k = 0, len1 = rule.length; k < len1; k++) {
              term = rule[k];
              if (term.t != null) {
                cnf["Lone" + index] = [
                  [
                    {
                      t: term.t
                    }
                  ]
                ];
                delete term.t;
                term.nt = "Lone" + index;
                index++;
              }
            }
          }
        }
      }
      for (key in cnf) {
        rules = cnf[key];
        for (l = 0, len2 = rules.length; l < len2; l++) {
          rule = rules[l];
          if (rule.length > 2) {
            replacementrule = [
              rule[0], {
                nt: "Simple" + index
              }
            ];
            index++;
            for (i = m = 1, ref = rule.length - 2; 1 <= ref ? m < ref : m > ref; i = 1 <= ref ? ++m : --m) {
              cnf["Simple" + (index - 1)] = [
                [
                  rule[i], {
                    nt: "Simple" + index
                  }
                ]
              ];
              index++;
            }
            cnf["Simple" + (index - 1)] = [[rule[rule.length - 2], rule[rule.length - 1]]];
            while (rule.length > 0) {
              rule.pop();
            }
            for (n = 0, len3 = replacementrule.length; n < len3; n++) {
              term = replacementrule[n];
              rule.push(term);
            }
          }
        }
      }
      for (key in cnf) {
        rules = cnf[key];
        if (rules.length !== 1 || rules[0].length !== 1 || (rules[0][0].nt == null)) {
          continue;
        }
        replace(key, rules[0][0].nt);
        delete cnf[key];
      }
      return cnf;
    }
  };
  