babel-core
Version:
Turn ES6 code into readable vanilla ES5 with source maps
105 lines (84 loc) • 3.37 kB
JavaScript
;
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
exports.__esModule = true;
// The algorithm used to determine whether a regexp can appear at a
// given point in the program is loosely based on sweet.js' approach.
// See https://github.com/mozilla/sweet.js/wiki/design
var Parser = require("./state").Parser;
var tt = require("./tokentype").types;
var lineBreak = require("./whitespace").lineBreak;
var TokContext = exports.TokContext = function TokContext(token, isExpr, preserveSpace, override) {
_classCallCheck(this, TokContext);
this.token = token;
this.isExpr = isExpr;
this.preserveSpace = preserveSpace;
this.override = override;
};
var types = {
b_stat: new TokContext("{", false),
b_expr: new TokContext("{", true),
b_tmpl: new TokContext("${", true),
p_stat: new TokContext("(", false),
p_expr: new TokContext("(", true),
q_tmpl: new TokContext("`", true, true, function (p) {
return p.readTmplToken();
}),
f_expr: new TokContext("function", true)
};
exports.types = types;
var pp = Parser.prototype;
pp.initialContext = function () {
return [types.b_stat];
};
pp.braceIsBlock = function (prevType) {
var parent = undefined;
if (prevType === tt.colon && (parent = this.curContext()).token == "{") return !parent.isExpr;
if (prevType === tt._return) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start));
if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof) return true;
if (prevType == tt.braceL) return this.curContext() === types.b_stat;
return !this.exprAllowed;
};
pp.updateContext = function (prevType) {
var update = undefined,
type = this.type;
if (type.keyword && prevType == tt.dot) this.exprAllowed = false;else if (update = type.updateContext) update.call(this, prevType);else this.exprAllowed = type.beforeExpr;
};
// Token-specific context update code
tt.parenR.updateContext = tt.braceR.updateContext = function () {
if (this.context.length == 1) {
this.exprAllowed = true;
return;
}
var out = this.context.pop();
if (out === types.b_stat && this.curContext() === types.f_expr) {
this.context.pop();
this.exprAllowed = false;
} else if (out === types.b_tmpl) {
this.exprAllowed = true;
} else {
this.exprAllowed = !out.isExpr;
}
};
tt.braceL.updateContext = function (prevType) {
this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr);
this.exprAllowed = true;
};
tt.dollarBraceL.updateContext = function () {
this.context.push(types.b_tmpl);
this.exprAllowed = true;
};
tt.parenL.updateContext = function (prevType) {
var statementParens = prevType === tt._if || prevType === tt._for || prevType === tt._with || prevType === tt._while;
this.context.push(statementParens ? types.p_stat : types.p_expr);
this.exprAllowed = true;
};
tt.incDec.updateContext = function () {};
tt._function.updateContext = function () {
if (this.curContext() !== types.b_stat) this.context.push(types.f_expr);
this.exprAllowed = false;
};
tt.backQuote.updateContext = function () {
if (this.curContext() === types.q_tmpl) this.context.pop();else this.context.push(types.q_tmpl);
this.exprAllowed = false;
};
// tokExprAllowed stays unchanged