123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- 'use strict';
- var use = require('use');
- var define = require('define-property');
- var debug = require('debug')('snapdragon:compiler');
- var utils = require('./utils');
- 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);
- }
- Compiler.prototype = {
-
- 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: function(key, val) {
- define(this, key, val);
- return this;
- },
-
- emit: function(str, node) {
- this.output += str;
- return str;
- },
-
- set: function(name, fn) {
- this.compilers[name] = fn;
- return this;
- },
-
- get: function(name) {
- return this.compilers[name];
- },
-
- prev: function(n) {
- return this.ast.nodes[this.idx - (n || 1)] || { type: 'bos', val: '' };
- },
-
- next: function(n) {
- return this.ast.nodes[this.idx + (n || 1)] || { type: 'eos', val: '' };
- },
-
- 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);
- },
-
- 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: function(ast, options) {
- var opts = utils.extend({}, this.options, options);
- this.ast = ast;
- this.parsingErrors = this.ast.errors;
- this.output = '';
-
- 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;
- }
- };
- module.exports = Compiler;
|