generate.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. function noop(value) {
  2. return value;
  3. }
  4. function generateMultiplier(multiplier) {
  5. if (multiplier.min === 0 && multiplier.max === 0) {
  6. return '*';
  7. }
  8. if (multiplier.min === 0 && multiplier.max === 1) {
  9. return '?';
  10. }
  11. if (multiplier.min === 1 && multiplier.max === 0) {
  12. return multiplier.comma ? '#' : '+';
  13. }
  14. if (multiplier.min === 1 && multiplier.max === 1) {
  15. return '';
  16. }
  17. return (
  18. (multiplier.comma ? '#' : '') +
  19. (multiplier.min === multiplier.max
  20. ? '{' + multiplier.min + '}'
  21. : '{' + multiplier.min + ',' + (multiplier.max !== 0 ? multiplier.max : '') + '}'
  22. )
  23. );
  24. }
  25. function generateSequence(node, forceBraces, decorate) {
  26. var result = node.terms.map(function(term) {
  27. return generate(term, forceBraces, decorate);
  28. }).join(node.combinator === ' ' ? ' ' : ' ' + node.combinator + ' ');
  29. if (node.explicit || forceBraces) {
  30. result = (result[0] !== ',' ? '[ ' : '[') + result + ' ]';
  31. }
  32. return result;
  33. }
  34. function generate(node, forceBraces, decorate) {
  35. var result;
  36. switch (node.type) {
  37. case 'Group':
  38. result =
  39. generateSequence(node, forceBraces, decorate) +
  40. (node.disallowEmpty ? '!' : '');
  41. break;
  42. case 'Multiplier':
  43. // return since node is a composition
  44. return (
  45. generate(node.term, forceBraces, decorate) +
  46. decorate(generateMultiplier(node), node)
  47. );
  48. case 'Type':
  49. result = '<' + node.name + '>';
  50. break;
  51. case 'Property':
  52. result = '<\'' + node.name + '\'>';
  53. break;
  54. case 'Keyword':
  55. result = node.name;
  56. break;
  57. case 'AtKeyword':
  58. result = '@' + node.name;
  59. break;
  60. case 'Function':
  61. result = node.name + '(';
  62. break;
  63. case 'String':
  64. case 'Token':
  65. result = node.value;
  66. break;
  67. case 'Comma':
  68. result = ',';
  69. break;
  70. default:
  71. throw new Error('Unknown node type `' + node.type + '`');
  72. }
  73. return decorate(result, node);
  74. }
  75. module.exports = function(node, options) {
  76. var decorate = noop;
  77. var forceBraces = false;
  78. if (typeof options === 'function') {
  79. decorate = options;
  80. } else if (options) {
  81. forceBraces = Boolean(options.forceBraces);
  82. if (typeof options.decorate === 'function') {
  83. decorate = options.decorate;
  84. }
  85. }
  86. return generate(node, forceBraces, decorate);
  87. };