You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
3.3 KiB
129 lines
3.3 KiB
function noop(value) { |
|
return value; |
|
} |
|
|
|
function generateMultiplier(multiplier) { |
|
if (multiplier.min === 0 && multiplier.max === 0) { |
|
return '*'; |
|
} |
|
|
|
if (multiplier.min === 0 && multiplier.max === 1) { |
|
return '?'; |
|
} |
|
|
|
if (multiplier.min === 1 && multiplier.max === 0) { |
|
return multiplier.comma ? '#' : '+'; |
|
} |
|
|
|
if (multiplier.min === 1 && multiplier.max === 1) { |
|
return ''; |
|
} |
|
|
|
return ( |
|
(multiplier.comma ? '#' : '') + |
|
(multiplier.min === multiplier.max |
|
? '{' + multiplier.min + '}' |
|
: '{' + multiplier.min + ',' + (multiplier.max !== 0 ? multiplier.max : '') + '}' |
|
) |
|
); |
|
} |
|
|
|
function generateTypeOpts(node) { |
|
switch (node.type) { |
|
case 'Range': |
|
return ( |
|
' [' + |
|
(node.min === null ? '-∞' : node.min) + |
|
',' + |
|
(node.max === null ? '∞' : node.max) + |
|
']' |
|
); |
|
|
|
default: |
|
throw new Error('Unknown node type `' + node.type + '`'); |
|
} |
|
} |
|
|
|
function generateSequence(node, decorate, forceBraces, compact) { |
|
var combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' '; |
|
var result = node.terms.map(function(term) { |
|
return generate(term, decorate, forceBraces, compact); |
|
}).join(combinator); |
|
|
|
if (node.explicit || forceBraces) { |
|
result = (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]'); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
function generate(node, decorate, forceBraces, compact) { |
|
var result; |
|
|
|
switch (node.type) { |
|
case 'Group': |
|
result = |
|
generateSequence(node, decorate, forceBraces, compact) + |
|
(node.disallowEmpty ? '!' : ''); |
|
break; |
|
|
|
case 'Multiplier': |
|
// return since node is a composition |
|
return ( |
|
generate(node.term, decorate, forceBraces, compact) + |
|
decorate(generateMultiplier(node), node) |
|
); |
|
|
|
case 'Type': |
|
result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>'; |
|
break; |
|
|
|
case 'Property': |
|
result = '<\'' + node.name + '\'>'; |
|
break; |
|
|
|
case 'Keyword': |
|
result = node.name; |
|
break; |
|
|
|
case 'AtKeyword': |
|
result = '@' + node.name; |
|
break; |
|
|
|
case 'Function': |
|
result = node.name + '('; |
|
break; |
|
|
|
case 'String': |
|
case 'Token': |
|
result = node.value; |
|
break; |
|
|
|
case 'Comma': |
|
result = ','; |
|
break; |
|
|
|
default: |
|
throw new Error('Unknown node type `' + node.type + '`'); |
|
} |
|
|
|
return decorate(result, node); |
|
} |
|
|
|
module.exports = function(node, options) { |
|
var decorate = noop; |
|
var forceBraces = false; |
|
var compact = false; |
|
|
|
if (typeof options === 'function') { |
|
decorate = options; |
|
} else if (options) { |
|
forceBraces = Boolean(options.forceBraces); |
|
compact = Boolean(options.compact); |
|
if (typeof options.decorate === 'function') { |
|
decorate = options.decorate; |
|
} |
|
} |
|
|
|
return generate(node, decorate, forceBraces, compact); |
|
};
|
|
|