generate.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  2. function isNodeType(node, type) {
  3. return node && node.type === type;
  4. }
  5. function serializeMultiplier(multiplier) {
  6. if (multiplier.min === 0 && multiplier.max === 0) {
  7. return '*';
  8. }
  9. if (multiplier.min === 0 && multiplier.max === 1) {
  10. return '?';
  11. }
  12. if (multiplier.min === 1 && multiplier.max === 0) {
  13. return multiplier.comma ? '#' : '+';
  14. }
  15. if (multiplier.min === 1 && multiplier.max === 1) {
  16. return '';
  17. }
  18. return (
  19. (multiplier.comma ? '#' : '') +
  20. '{' + multiplier.min + (multiplier.min !== multiplier.max ? ',' + (multiplier.max !== 0 ? multiplier.max : '') : '') + '}'
  21. );
  22. }
  23. function generateSequence(node, forceBraces, decorate) {
  24. var result = '';
  25. if (node.explicit || forceBraces) {
  26. result += '[' + (!isNodeType(node.terms[0], 'Comma') ? ' ' : '');
  27. }
  28. result += node.terms.map(function(term) {
  29. return generate(term, forceBraces, decorate);
  30. }).join(node.combinator === ' ' ? ' ' : ' ' + node.combinator + ' ');
  31. if (node.explicit || forceBraces) {
  32. result += ' ]';
  33. }
  34. return result;
  35. }
  36. function generateParentheses(group, forceBraces, decorate) {
  37. if (!group.terms.length) {
  38. return '()';
  39. }
  40. return '( ' + generateSequence(group, forceBraces, decorate) + ' )';
  41. }
  42. function generate(node, forceBraces, decorate) {
  43. var result;
  44. switch (node.type) {
  45. case 'Group':
  46. result =
  47. generateSequence(node, forceBraces, decorate) +
  48. (node.disallowEmpty ? '!' : '') +
  49. serializeMultiplier(node.multiplier);
  50. break;
  51. case 'Keyword':
  52. result = node.name;
  53. break;
  54. case 'Function':
  55. result = node.name + generateParentheses(node.children, forceBraces, decorate);
  56. break;
  57. case 'Parentheses': // replace for seq('(' seq(...node.children) ')')
  58. result = generateParentheses(node.children, forceBraces, decorate);
  59. break;
  60. case 'Type':
  61. result = '<' + node.name + '>';
  62. break;
  63. case 'Property':
  64. result = '<\'' + node.name + '\'>';
  65. break;
  66. case 'Combinator': // remove?
  67. case 'Slash': // replace for String? '/'
  68. case 'Percent': // replace for String? '%'
  69. case 'String':
  70. case 'Comma':
  71. result = node.value;
  72. break;
  73. default:
  74. throw new Error('Unknown node type `' + node.type + '`');
  75. }
  76. if (typeof decorate === 'function') {
  77. result = decorate(result, node);
  78. }
  79. return result;
  80. }
  81. module.exports = generate;