Skip to content
This repository has been archived by the owner on Aug 18, 2021. It is now read-only.

Commit

Permalink
refactoring and comments
Browse files Browse the repository at this point in the history
  • Loading branch information
scastiel committed Nov 10, 2017
1 parent c0658f0 commit 5f29957
Showing 1 changed file with 67 additions and 33 deletions.
100 changes: 67 additions & 33 deletions babylon-to-espree/convertTemplateType.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,89 @@
"use strict";

module.exports = function(tokens, tt) {
const contextStack = [{ inTemplate: false, numBraces: 0 }];
let contextIndex = 0;
const getContext = () => contextStack[contextIndex];
// As long as we will iterate through the tokens array, we'll maintain a stack of
// contexts. This stack will alternate with:
// * template context (for strings): they have `isTemplate` set to `true`, and
// keep in `index` property the index of the token (in the array) that started
// the template;
// * non-template contexts (for JavaScript code): they have `isTemplate` set to
// `false`, and keep a number of opened braces ('{', i.e. the ones that were
// not closed with '}').
// The top (i.e. last) context in the stack is the current one.
const contextStack = [];

// At the beginning, we are not in a template.
pushNewNonTemplateContext();

for (let index = 0; index < tokens.length; index++) {
const token = tokens[index];
const context = getContext();

if (context.inTemplate) {
if (currentContext().inTemplate) {
// We are in a template…
const isTemplateEnder =
token.type === tt.dollarBraceL || token.type === tt.backQuote;
if (isTemplateEnder) {
if (token.type === tt.dollarBraceL) {
contextIndex++;
if (!contextStack[contextIndex]) {
contextStack[contextIndex] = { numBraces: 0, inTemplate: false };
}
} else {
contextIndex--;
}

// We have a complete template token :)
const { index: startIndex } = context;
replaceWithTemplateType(startIndex, index);
index = startIndex;
// If we encounter a '${' or a '`', we go out of template (string) mode and create
// a template token. But the behavior differs depending on '${' or '`'…
if (token.type === tt.dollarBraceL) {
// If '${', then we begin a new expression with its own context. This means that
// we add a new context to the stack, and define it as the current context.
index = createTemplateTokenAndReturnNewIndex(index, token);
pushNewNonTemplateContext();
} else if (token.type === tt.backQuote) {
// If '`', then we go back to the previous expression (the one before the template
// string began). We restore the previous context, with its numOfBraces.
index = createTemplateTokenAndReturnNewIndex(index, token);
popContext();
}

// If not a '${' or a '`', we just keep going.
} else {
// We are out of a template…
const isTemplateStarter =
token.type === tt.backQuote ||
(context.numBraces === 0 && token.type === tt.braceR);

if (isTemplateStarter) {
if (token.type === tt.backQuote) {
contextIndex++;
contextStack[contextIndex] = { index, inTemplate: true };
} else {
contextIndex--;
}
contextStack[contextIndex].index = index;
// If we encounter a '`' or a '}' (and there is no not-closed '{'), we go in template
// (string) mode. Again two cases to handle:
if (token.type === tt.backQuote) {
// If '`', we begin a new template string, so we add a new context to the stack, and
// set it as the current context.
pushNewTemplateContext(index);
} else if (currentContext().numBraces === 0 && token.type === tt.braceR) {
// If '}', then we go back to the previous template string (that was "interrupted" by
// an embedded expression '${...}'), so we go back to the previous context.
popContext();
currentContext().startIndex = index;
// Note that `contextStack[contextIndex].isTemplate` is already `true`.
} else if (token.type === tt.braceL) {
context.numBraces++;
// In the case we encounter a '{', we increment the current number of openened braces.
currentContext().numBraces++;
} else if (token.type === tt.braceR) {
context.numBraces--;
// And if '}' (and it's not been identified as the end of an embedded expression), we
// decrement the current number of opened braces.
currentContext().numBraces--;
}
}
}

function createTemplateTokenAndReturnNewIndex(index, token) {
const { startIndex } = currentContext();
replaceWithTemplateType(startIndex, index);
return startIndex;
}

function currentContext() {
return contextStack[contextStack.length - 1];
}

function pushNewTemplateContext(startIndex) {
contextStack.push({ startIndex, inTemplate: true });
}

function pushNewNonTemplateContext() {
contextStack.push({ numBraces: 0, inTemplate: false });
}

function popContext() {
contextStack.pop();
}

// append the values between start and end
function createTemplateValue(start, end) {
var value = "";
Expand Down

0 comments on commit 5f29957

Please sign in to comment.