1 | function noop(value) {
|
---|
2 | return value;
|
---|
3 | }
|
---|
4 |
|
---|
5 | function generateMultiplier(multiplier) {
|
---|
6 | if (multiplier.min === 0 && multiplier.max === 0) {
|
---|
7 | return '*';
|
---|
8 | }
|
---|
9 |
|
---|
10 | if (multiplier.min === 0 && multiplier.max === 1) {
|
---|
11 | return '?';
|
---|
12 | }
|
---|
13 |
|
---|
14 | if (multiplier.min === 1 && multiplier.max === 0) {
|
---|
15 | return multiplier.comma ? '#' : '+';
|
---|
16 | }
|
---|
17 |
|
---|
18 | if (multiplier.min === 1 && multiplier.max === 1) {
|
---|
19 | return '';
|
---|
20 | }
|
---|
21 |
|
---|
22 | return (
|
---|
23 | (multiplier.comma ? '#' : '') +
|
---|
24 | (multiplier.min === multiplier.max
|
---|
25 | ? '{' + multiplier.min + '}'
|
---|
26 | : '{' + multiplier.min + ',' + (multiplier.max !== 0 ? multiplier.max : '') + '}'
|
---|
27 | )
|
---|
28 | );
|
---|
29 | }
|
---|
30 |
|
---|
31 | function generateTypeOpts(node) {
|
---|
32 | switch (node.type) {
|
---|
33 | case 'Range':
|
---|
34 | return (
|
---|
35 | ' [' +
|
---|
36 | (node.min === null ? '-∞' : node.min) +
|
---|
37 | ',' +
|
---|
38 | (node.max === null ? '∞' : node.max) +
|
---|
39 | ']'
|
---|
40 | );
|
---|
41 |
|
---|
42 | default:
|
---|
43 | throw new Error('Unknown node type `' + node.type + '`');
|
---|
44 | }
|
---|
45 | }
|
---|
46 |
|
---|
47 | function generateSequence(node, decorate, forceBraces, compact) {
|
---|
48 | var combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' ';
|
---|
49 | var result = node.terms.map(function(term) {
|
---|
50 | return generate(term, decorate, forceBraces, compact);
|
---|
51 | }).join(combinator);
|
---|
52 |
|
---|
53 | if (node.explicit || forceBraces) {
|
---|
54 | result = (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]');
|
---|
55 | }
|
---|
56 |
|
---|
57 | return result;
|
---|
58 | }
|
---|
59 |
|
---|
60 | function generate(node, decorate, forceBraces, compact) {
|
---|
61 | var result;
|
---|
62 |
|
---|
63 | switch (node.type) {
|
---|
64 | case 'Group':
|
---|
65 | result =
|
---|
66 | generateSequence(node, decorate, forceBraces, compact) +
|
---|
67 | (node.disallowEmpty ? '!' : '');
|
---|
68 | break;
|
---|
69 |
|
---|
70 | case 'Multiplier':
|
---|
71 | // return since node is a composition
|
---|
72 | return (
|
---|
73 | generate(node.term, decorate, forceBraces, compact) +
|
---|
74 | decorate(generateMultiplier(node), node)
|
---|
75 | );
|
---|
76 |
|
---|
77 | case 'Type':
|
---|
78 | result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>';
|
---|
79 | break;
|
---|
80 |
|
---|
81 | case 'Property':
|
---|
82 | result = '<\'' + node.name + '\'>';
|
---|
83 | break;
|
---|
84 |
|
---|
85 | case 'Keyword':
|
---|
86 | result = node.name;
|
---|
87 | break;
|
---|
88 |
|
---|
89 | case 'AtKeyword':
|
---|
90 | result = '@' + node.name;
|
---|
91 | break;
|
---|
92 |
|
---|
93 | case 'Function':
|
---|
94 | result = node.name + '(';
|
---|
95 | break;
|
---|
96 |
|
---|
97 | case 'String':
|
---|
98 | case 'Token':
|
---|
99 | result = node.value;
|
---|
100 | break;
|
---|
101 |
|
---|
102 | case 'Comma':
|
---|
103 | result = ',';
|
---|
104 | break;
|
---|
105 |
|
---|
106 | default:
|
---|
107 | throw new Error('Unknown node type `' + node.type + '`');
|
---|
108 | }
|
---|
109 |
|
---|
110 | return decorate(result, node);
|
---|
111 | }
|
---|
112 |
|
---|
113 | module.exports = function(node, options) {
|
---|
114 | var decorate = noop;
|
---|
115 | var forceBraces = false;
|
---|
116 | var compact = false;
|
---|
117 |
|
---|
118 | if (typeof options === 'function') {
|
---|
119 | decorate = options;
|
---|
120 | } else if (options) {
|
---|
121 | forceBraces = Boolean(options.forceBraces);
|
---|
122 | compact = Boolean(options.compact);
|
---|
123 | if (typeof options.decorate === 'function') {
|
---|
124 | decorate = options.decorate;
|
---|
125 | }
|
---|
126 | }
|
---|
127 |
|
---|
128 | return generate(node, decorate, forceBraces, compact);
|
---|
129 | };
|
---|