var tokenize = require('../tokenizer'); var TokenStream = require('../common/TokenStream'); var tokenStream = new TokenStream(); var astToTokens = { decorator: function(handlers) { var curNode = null; var prev = { len: 0, node: null }; var nodes = [prev]; var buffer = ''; return { children: handlers.children, node: function(node) { var tmp = curNode; curNode = node; handlers.node.call(this, node); curNode = tmp; }, chunk: function(chunk) { buffer += chunk; if (prev.node !== curNode) { nodes.push({ len: chunk.length, node: curNode }); } else { prev.len += chunk.length; } }, result: function() { return prepareTokens(buffer, nodes); } }; } }; function prepareTokens(str, nodes) { var tokens = []; var nodesOffset = 0; var nodesIndex = 0; var currentNode = nodes ? nodes[nodesIndex].node : null; tokenize(str, tokenStream); while (!tokenStream.eof) { if (nodes) { while (nodesIndex < nodes.length && nodesOffset + nodes[nodesIndex].len <= tokenStream.tokenStart) { nodesOffset += nodes[nodesIndex++].len; currentNode = nodes[nodesIndex].node; } } tokens.push({ type: tokenStream.tokenType, value: tokenStream.getTokenValue(), index: tokenStream.tokenIndex, // TODO: remove it, temporary solution balance: tokenStream.balance[tokenStream.tokenIndex], // TODO: remove it, temporary solution node: currentNode }); tokenStream.next(); // console.log({ ...tokens[tokens.length - 1], node: undefined }); } return tokens; } module.exports = function(value, syntax) { if (typeof value === 'string') { return prepareTokens(value, null); } return syntax.generate(value, astToTokens); };