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.
104 lines
2.7 KiB
104 lines
2.7 KiB
2 years ago
|
'use strict';
|
||
|
|
||
|
const index = require('../tokenizer/index.cjs');
|
||
|
const sourceMap = require('./sourceMap.cjs');
|
||
|
const tokenBefore = require('./token-before.cjs');
|
||
|
const types = require('../tokenizer/types.cjs');
|
||
|
|
||
|
const REVERSESOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
|
||
|
|
||
|
function processChildren(node, delimeter) {
|
||
|
if (typeof delimeter === 'function') {
|
||
|
let prev = null;
|
||
|
|
||
|
node.children.forEach(node => {
|
||
|
if (prev !== null) {
|
||
|
delimeter.call(this, prev);
|
||
|
}
|
||
|
|
||
|
this.node(node);
|
||
|
prev = node;
|
||
|
});
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
node.children.forEach(this.node, this);
|
||
|
}
|
||
|
|
||
|
function processChunk(chunk) {
|
||
|
index.tokenize(chunk, (type, start, end) => {
|
||
|
this.token(type, chunk.slice(start, end));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function createGenerator(config) {
|
||
|
const types$1 = new Map();
|
||
|
|
||
|
for (let name in config.node) {
|
||
|
const item = config.node[name];
|
||
|
const fn = item.generate || item;
|
||
|
|
||
|
if (typeof fn === 'function') {
|
||
|
types$1.set(name, item.generate || item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return function(node, options) {
|
||
|
let buffer = '';
|
||
|
let prevCode = 0;
|
||
|
let handlers = {
|
||
|
node(node) {
|
||
|
if (types$1.has(node.type)) {
|
||
|
types$1.get(node.type).call(publicApi, node);
|
||
|
} else {
|
||
|
throw new Error('Unknown node type: ' + node.type);
|
||
|
}
|
||
|
},
|
||
|
tokenBefore: tokenBefore.safe,
|
||
|
token(type, value) {
|
||
|
prevCode = this.tokenBefore(prevCode, type, value);
|
||
|
|
||
|
this.emit(value, type, false);
|
||
|
|
||
|
if (type === types.Delim && value.charCodeAt(0) === REVERSESOLIDUS) {
|
||
|
this.emit('\n', types.WhiteSpace, true);
|
||
|
}
|
||
|
},
|
||
|
emit(value) {
|
||
|
buffer += value;
|
||
|
},
|
||
|
result() {
|
||
|
return buffer;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if (options) {
|
||
|
if (typeof options.decorator === 'function') {
|
||
|
handlers = options.decorator(handlers);
|
||
|
}
|
||
|
|
||
|
if (options.sourceMap) {
|
||
|
handlers = sourceMap.generateSourceMap(handlers);
|
||
|
}
|
||
|
|
||
|
if (options.mode in tokenBefore) {
|
||
|
handlers.tokenBefore = tokenBefore[options.mode];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const publicApi = {
|
||
|
node: (node) => handlers.node(node),
|
||
|
children: processChildren,
|
||
|
token: (type, value) => handlers.token(type, value),
|
||
|
tokenize: processChunk
|
||
|
};
|
||
|
|
||
|
handlers.node(node);
|
||
|
|
||
|
return handlers.result();
|
||
|
};
|
||
|
}
|
||
|
|
||
|
exports.createGenerator = createGenerator;
|