generate.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 generateTypeOpts(node) {
  26. switch (node.type) {
  27. case 'Range':
  28. return (
  29. ' [' +
  30. (node.min === null ? '-∞' : node.min) +
  31. ',' +
  32. (node.max === null ? '∞' : node.max) +
  33. ']'
  34. );
  35. default:
  36. throw new Error('Unknown node type `' + node.type + '`');
  37. }
  38. }
  39. function generateSequence(node, forceBraces, decorate) {
  40. var result = node.terms.map(function(term) {
  41. return generate(term, forceBraces, decorate);
  42. }).join(node.combinator === ' ' ? ' ' : ' ' + node.combinator + ' ');
  43. if (node.explicit || forceBraces) {
  44. result = (result[0] !== ',' ? '[ ' : '[') + result + ' ]';
  45. }
  46. return result;
  47. }
  48. function generate(node, forceBraces, decorate) {
  49. var result;
  50. switch (node.type) {
  51. case 'Group':
  52. result =
  53. generateSequence(node, forceBraces, decorate) +
  54. (node.disallowEmpty ? '!' : '');
  55. break;
  56. case 'Multiplier':
  57. // return since node is a composition
  58. return (
  59. generate(node.term, forceBraces, decorate) +
  60. decorate(generateMultiplier(node), node)
  61. );
  62. case 'Type':
  63. result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>';
  64. break;
  65. case 'Property':
  66. result = '<\'' + node.name + '\'>';
  67. break;
  68. case 'Keyword':
  69. result = node.name;
  70. break;
  71. case 'AtKeyword':
  72. result = '@' + node.name;
  73. break;
  74. case 'Function':
  75. result = node.name + '(';
  76. break;
  77. case 'String':
  78. case 'Token':
  79. result = node.value;
  80. break;
  81. case 'Comma':
  82. result = ',';
  83. break;
  84. default:
  85. throw new Error('Unknown node type `' + node.type + '`');
  86. }
  87. return decorate(result, node);
  88. }
  89. module.exports = function(node, options) {
  90. var decorate = noop;
  91. var forceBraces = false;
  92. if (typeof options === 'function') {
  93. decorate = options;
  94. } else if (options) {
  95. forceBraces = Boolean(options.forceBraces);
  96. if (typeof options.decorate === 'function') {
  97. decorate = options.decorate;
  98. }
  99. }
  100. return generate(node, forceBraces, decorate);
  101. };