Projekt

Obecné

Profil

Stáhnout (3.51 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2

    
3
var use = require('use');
4
var define = require('define-property');
5
var debug = require('debug')('snapdragon:compiler');
6
var utils = require('./utils');
7

    
8
/**
9
 * Create a new `Compiler` with the given `options`.
10
 * @param {Object} `options`
11
 */
12

    
13
function Compiler(options, state) {
14
  debug('initializing', __filename);
15
  this.options = utils.extend({source: 'string'}, options);
16
  this.state = state || {};
17
  this.compilers = {};
18
  this.output = '';
19
  this.set('eos', function(node) {
20
    return this.emit(node.val, node);
21
  });
22
  this.set('noop', function(node) {
23
    return this.emit(node.val, node);
24
  });
25
  this.set('bos', function(node) {
26
    return this.emit(node.val, node);
27
  });
28
  use(this);
29
}
30

    
31
/**
32
 * Prototype methods
33
 */
34

    
35
Compiler.prototype = {
36

    
37
  /**
38
   * Throw an error message with details including the cursor position.
39
   * @param {String} `msg` Message to use in the Error.
40
   */
41

    
42
  error: function(msg, node) {
43
    var pos = node.position || {start: {column: 0}};
44
    var message = this.options.source + ' column:' + pos.start.column + ': ' + msg;
45

    
46
    var err = new Error(message);
47
    err.reason = msg;
48
    err.column = pos.start.column;
49
    err.source = this.pattern;
50

    
51
    if (this.options.silent) {
52
      this.errors.push(err);
53
    } else {
54
      throw err;
55
    }
56
  },
57

    
58
  /**
59
   * Define a non-enumberable property on the `Compiler` instance.
60
   *
61
   * ```js
62
   * compiler.define('foo', 'bar');
63
   * ```
64
   * @name .define
65
   * @param {String} `key` propery name
66
   * @param {any} `val` property value
67
   * @return {Object} Returns the Compiler instance for chaining.
68
   * @api public
69
   */
70

    
71
  define: function(key, val) {
72
    define(this, key, val);
73
    return this;
74
  },
75

    
76
  /**
77
   * Emit `node.val`
78
   */
79

    
80
  emit: function(str, node) {
81
    this.output += str;
82
    return str;
83
  },
84

    
85
  /**
86
   * Add a compiler `fn` with the given `name`
87
   */
88

    
89
  set: function(name, fn) {
90
    this.compilers[name] = fn;
91
    return this;
92
  },
93

    
94
  /**
95
   * Get compiler `name`.
96
   */
97

    
98
  get: function(name) {
99
    return this.compilers[name];
100
  },
101

    
102
  /**
103
   * Get the previous AST node.
104
   */
105

    
106
  prev: function(n) {
107
    return this.ast.nodes[this.idx - (n || 1)] || { type: 'bos', val: '' };
108
  },
109

    
110
  /**
111
   * Get the next AST node.
112
   */
113

    
114
  next: function(n) {
115
    return this.ast.nodes[this.idx + (n || 1)] || { type: 'eos', val: '' };
116
  },
117

    
118
  /**
119
   * Visit `node`.
120
   */
121

    
122
  visit: function(node, nodes, i) {
123
    var fn = this.compilers[node.type];
124
    this.idx = i;
125

    
126
    if (typeof fn !== 'function') {
127
      throw this.error('compiler "' + node.type + '" is not registered', node);
128
    }
129
    return fn.call(this, node, nodes, i);
130
  },
131

    
132
  /**
133
   * Map visit over array of `nodes`.
134
   */
135

    
136
  mapVisit: function(nodes) {
137
    if (!Array.isArray(nodes)) {
138
      throw new TypeError('expected an array');
139
    }
140
    var len = nodes.length;
141
    var idx = -1;
142
    while (++idx < len) {
143
      this.visit(nodes[idx], nodes, idx);
144
    }
145
    return this;
146
  },
147

    
148
  /**
149
   * Compile `ast`.
150
   */
151

    
152
  compile: function(ast, options) {
153
    var opts = utils.extend({}, this.options, options);
154
    this.ast = ast;
155
    this.parsingErrors = this.ast.errors;
156
    this.output = '';
157

    
158
    // source map support
159
    if (opts.sourcemap) {
160
      var sourcemaps = require('./source-maps');
161
      sourcemaps(this);
162
      this.mapVisit(this.ast.nodes);
163
      this.applySourceMaps();
164
      this.map = opts.sourcemap === 'generator' ? this.map : this.map.toJSON();
165
      return this;
166
    }
167

    
168
    this.mapVisit(this.ast.nodes);
169
    return this;
170
  }
171
};
172

    
173
/**
174
 * Expose `Compiler`
175
 */
176

    
177
module.exports = Compiler;
(1-1/5)