UNPKG

luhn-generator

Version:

A generator of numbers that passes the validation of Luhn algorithm or Luhn formula, also known as the 'modulus 10' or 'mod 10' algorithm

178 lines (145 loc) 3.59 kB
'use strict'; var use = require('use'); var define = require('define-property'); var debug = require('debug')('snapdragon:compiler'); var utils = require('./utils'); /** * Create a new `Compiler` with the given `options`. * @param {Object} `options` */ function Compiler(options, state) { debug('initializing', __filename); this.options = utils.extend({source: 'string'}, options); this.state = state || {}; this.compilers = {}; this.output = ''; this.set('eos', function(node) { return this.emit(node.val, node); }); this.set('noop', function(node) { return this.emit(node.val, node); }); this.set('bos', function(node) { return this.emit(node.val, node); }); use(this); } /** * Prototype methods */ Compiler.prototype = { /** * Throw an error message with details including the cursor position. * @param {String} `msg` Message to use in the Error. */ error: function(msg, node) { var pos = node.position || {start: {column: 0}}; var message = this.options.source + ' column:' + pos.start.column + ': ' + msg; var err = new Error(message); err.reason = msg; err.column = pos.start.column; err.source = this.pattern; if (this.options.silent) { this.errors.push(err); } else { throw err; } }, /** * Define a non-enumberable property on the `Compiler` instance. * * ```js * compiler.define('foo', 'bar'); * ``` * @name .define * @param {String} `key` propery name * @param {any} `val` property value * @return {Object} Returns the Compiler instance for chaining. * @api public */ define: function(key, val) { define(this, key, val); return this; }, /** * Emit `node.val` */ emit: function(str, node) { this.output += str; return str; }, /** * Add a compiler `fn` with the given `name` */ set: function(name, fn) { this.compilers[name] = fn; return this; }, /** * Get compiler `name`. */ get: function(name) { return this.compilers[name]; }, /** * Get the previous AST node. */ prev: function(n) { return this.ast.nodes[this.idx - (n || 1)] || { type: 'bos', val: '' }; }, /** * Get the next AST node. */ next: function(n) { return this.ast.nodes[this.idx + (n || 1)] || { type: 'eos', val: '' }; }, /** * Visit `node`. */ visit: function(node, nodes, i) { var fn = this.compilers[node.type]; this.idx = i; if (typeof fn !== 'function') { throw this.error('compiler "' + node.type + '" is not registered', node); } return fn.call(this, node, nodes, i); }, /** * Map visit over array of `nodes`. */ mapVisit: function(nodes) { if (!Array.isArray(nodes)) { throw new TypeError('expected an array'); } var len = nodes.length; var idx = -1; while (++idx < len) { this.visit(nodes[idx], nodes, idx); } return this; }, /** * Compile `ast`. */ compile: function(ast, options) { var opts = utils.extend({}, this.options, options); this.ast = ast; this.parsingErrors = this.ast.errors; this.output = ''; // source map support if (opts.sourcemap) { var sourcemaps = require('./source-maps'); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); this.map = opts.sourcemap === 'generator' ? this.map : this.map.toJSON(); return this; } this.mapVisit(this.ast.nodes); return this; } }; /** * Expose `Compiler` */ module.exports = Compiler;