mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-02-19 03:44:23 -05:00
disabled interpolations in normal regexes
This commit is contained in:
116
lib/lexer.js
116
lib/lexer.js
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, CONVERSIONS, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_START, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, include, last, starts;
|
||||
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, CONVERSIONS, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, include, last, starts;
|
||||
Rewriter = require('./rewriter').Rewriter;
|
||||
_ref = require('./helpers'), include = _ref.include, count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
|
||||
exports.Lexer = (function() {
|
||||
@@ -49,7 +49,7 @@
|
||||
if (include(JS_FORBIDDEN, id)) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'STRING';
|
||||
id = ("\"" + (id) + "\"");
|
||||
id = ("\"" + id + "\"");
|
||||
if (forcedIdentifier === 'accessor') {
|
||||
closeIndex = true;
|
||||
if (this.tag() !== '@') {
|
||||
@@ -165,60 +165,55 @@
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var _ref2, end, first, flags, match, regex, str;
|
||||
var match;
|
||||
if (this.chunk.charAt(0) !== '/') {
|
||||
return false;
|
||||
}
|
||||
if (match = HEREGEX.exec(this.chunk)) {
|
||||
return this.heregexToken(match);
|
||||
}
|
||||
if (!(first = REGEX_START.exec(this.chunk))) {
|
||||
return false;
|
||||
}
|
||||
if (first[1] === ' ' && !('CALL_START' === (_ref2 = this.tag()) || '=' === _ref2)) {
|
||||
return false;
|
||||
}
|
||||
if (include(NOT_REGEX, this.tag())) {
|
||||
return false;
|
||||
}
|
||||
if (!(regex = this.balancedString(this.chunk, [['/', '/']]))) {
|
||||
if (!(match = REGEX.exec(this.chunk))) {
|
||||
return false;
|
||||
}
|
||||
if (!(end = this.chunk.slice(regex.length).match(REGEX_END))) {
|
||||
return false;
|
||||
}
|
||||
flags = end[0];
|
||||
if (~regex.indexOf('#{')) {
|
||||
str = regex.slice(1, -1);
|
||||
this.tokens.push(['IDENTIFIER', 'RegExp'], ['CALL_START', '(']);
|
||||
this.interpolateString("\"" + (str) + "\"", {
|
||||
regex: true
|
||||
});
|
||||
if (flags) {
|
||||
this.tokens.push([',', ','], ['STRING', ("\"" + (flags) + "\"")]);
|
||||
}
|
||||
this.tokens.push(['CALL_END', ')']);
|
||||
} else {
|
||||
this.token('REGEX', regex + flags);
|
||||
}
|
||||
this.i += regex.length + flags.length;
|
||||
this.token('REGEX', match[0]);
|
||||
this.i += match[0].length;
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.heregexToken = function(match) {
|
||||
var _ref2, body, flags, heregex, re;
|
||||
var _i, _len, _ref2, _ref3, _this, body, flags, heregex, re, tag, tokens, value;
|
||||
_ref2 = match, heregex = _ref2[0], body = _ref2[1], flags = _ref2[2];
|
||||
this.i += heregex.length;
|
||||
if (!(~body.indexOf('#{'))) {
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
|
||||
this.token('REGEX', "/" + (re || '(?:)') + "/" + (flags));
|
||||
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
|
||||
return true;
|
||||
}
|
||||
this.token('IDENTIFIER', 'RegExp');
|
||||
this.tokens.push(['CALL_START', '(']);
|
||||
this.interpolateString("\"" + (body) + "\"", {
|
||||
regex: true,
|
||||
heregex: true
|
||||
tokens = [];
|
||||
_ref2 = this.interpolateString('"' + body + '"', {
|
||||
regex: true
|
||||
});
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
_ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];
|
||||
if (tag === 'TOKENS') {
|
||||
tokens.push.apply(tokens, value);
|
||||
} else {
|
||||
if (!(value = value.slice(1, -1).replace(HEREGEX_OMIT, ''))) {
|
||||
continue;
|
||||
}
|
||||
tokens.push(['STRING', '"' + value.replace(/[\\\"]/g, '\\$&') + '"']);
|
||||
}
|
||||
tokens.push(['+', '+']);
|
||||
}
|
||||
tokens.pop();
|
||||
if ((((_ref2 = tokens[0]) != null) ? _ref2[0] !== 'STRING' : undefined)) {
|
||||
this.tokens.push(['STRING', '""'], ['+', '+']);
|
||||
}
|
||||
(_this = this.tokens).push.apply(_this, tokens);
|
||||
if (flags) {
|
||||
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
}
|
||||
@@ -404,7 +399,7 @@
|
||||
}
|
||||
}
|
||||
if (indent) {
|
||||
doc = doc.replace(RegExp("\\n" + (indent), "g"), '\n');
|
||||
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
}
|
||||
if (herecomment) {
|
||||
return doc;
|
||||
@@ -414,7 +409,7 @@
|
||||
doc = doc.replace(/\\([\s\S])/g, function(m, c) {
|
||||
return ('\n' === c || quote === c) ? c : m;
|
||||
});
|
||||
doc = doc.replace(RegExp("" + (quote), "g"), '\\$&');
|
||||
doc = doc.replace(RegExp("" + quote, "g"), '\\$&');
|
||||
if (quote === "'") {
|
||||
doc = this.escapeLines(doc, true);
|
||||
}
|
||||
@@ -448,15 +443,14 @@
|
||||
return this.outdentToken(this.indent);
|
||||
};
|
||||
Lexer.prototype.identifierError = function(word) {
|
||||
throw new Error("SyntaxError: Reserved word \"" + (word) + "\" on line " + (this.line + 1));
|
||||
throw new Error("SyntaxError: Reserved word \"" + word + "\" on line " + (this.line + 1));
|
||||
};
|
||||
Lexer.prototype.assignmentError = function() {
|
||||
throw new Error("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
|
||||
};
|
||||
Lexer.prototype.balancedString = function(str, delimited, options) {
|
||||
var _i, _len, _ref2, close, i, levels, open, pair, slash, slen;
|
||||
var _i, _len, _ref2, close, i, levels, open, pair, slen;
|
||||
options || (options = {});
|
||||
slash = delimited[0][0] === '/';
|
||||
levels = [];
|
||||
i = 0;
|
||||
slen = str.length;
|
||||
@@ -482,21 +476,18 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!levels.length || slash && str.charAt(i) === '\n') {
|
||||
if (!levels.length) {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if (levels.length) {
|
||||
if (slash) {
|
||||
return false;
|
||||
}
|
||||
throw new Error("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1));
|
||||
}
|
||||
return !i ? false : str.slice(0, i);
|
||||
};
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var _i, _len, _ref2, char, expr, heredoc, i, inner, interpolated, lexer, nested, pi, push, regex, s, tag, tok, tokens, value;
|
||||
var _i, _len, _ref2, _this, char, expr, heredoc, i, inner, interpolated, lexer, nested, pi, regex, tag, tok, tokens, value;
|
||||
if (str.length < 5) {
|
||||
return this.token('STRING', this.escapeLines(str, heredoc));
|
||||
}
|
||||
@@ -514,14 +505,14 @@
|
||||
continue;
|
||||
}
|
||||
if (pi < i) {
|
||||
tokens.push(['STRING', '"' + this.escapeLines(str.slice(pi, i), heredoc) + '"']);
|
||||
tokens.push(['STRING', '"' + str.slice(pi, i) + '"']);
|
||||
}
|
||||
inner = expr.slice(1, -1).replace(LEADING_SPACES, '').replace(TRAILING_SPACES, '');
|
||||
if (inner.length) {
|
||||
if (heredoc) {
|
||||
inner = inner.replace(/\\\"/g, '"');
|
||||
}
|
||||
nested = lexer.tokenize("(" + (inner) + ")", {
|
||||
nested = lexer.tokenize("(" + inner + "\n)", {
|
||||
line: this.line
|
||||
});
|
||||
for (_i = 0, _len = nested.length; _i < _len; _i++) {
|
||||
@@ -531,43 +522,38 @@
|
||||
}
|
||||
}
|
||||
nested.pop();
|
||||
if (nested.length < 5) {
|
||||
nested.pop();
|
||||
nested.shift();
|
||||
}
|
||||
tokens.push(['TOKENS', nested]);
|
||||
} else {
|
||||
tokens.push(['STRING', '""']);
|
||||
}
|
||||
i += expr.length;
|
||||
pi = i + 1;
|
||||
}
|
||||
if ((i > pi) && (pi < str.length - 1)) {
|
||||
s = this.escapeLines(str.slice(pi, -1), heredoc);
|
||||
tokens.push(['STRING', '"' + s + '"']);
|
||||
tokens.push(['STRING', '"' + str.slice(pi)]);
|
||||
}
|
||||
if (tokens[0][0] !== 'STRING') {
|
||||
if (regex) {
|
||||
return tokens;
|
||||
}
|
||||
interpolated = tokens.length > 1;
|
||||
if ((((_ref2 = tokens[0]) != null) ? _ref2[0] !== 'STRING' : undefined)) {
|
||||
tokens.unshift(['STRING', '""']);
|
||||
}
|
||||
interpolated = !regex && tokens.length > 1;
|
||||
if (interpolated) {
|
||||
this.token('(', '(');
|
||||
}
|
||||
push = tokens.push;
|
||||
for (i = 0, _len = tokens.length; i < _len; i++) {
|
||||
_ref2 = tokens[i], tag = _ref2[0], value = _ref2[1];
|
||||
if (i) {
|
||||
this.token('+', '+');
|
||||
}
|
||||
if (tag === 'TOKENS') {
|
||||
push.apply(this.tokens, value);
|
||||
continue;
|
||||
(_this = this.tokens).push.apply(_this, value);
|
||||
} else {
|
||||
this.token(tag, this.escapeLines(value, heredoc));
|
||||
}
|
||||
if (regex) {
|
||||
value = value.slice(1, -1);
|
||||
value = value.replace(/[\\\"]/g, '\\$&');
|
||||
if (options.heregex) {
|
||||
value = value.replace(HEREGEX_OMIT, '');
|
||||
}
|
||||
value = '"' + value + '"';
|
||||
}
|
||||
this.token(tag, value);
|
||||
}
|
||||
if (interpolated) {
|
||||
this.token(')', ')');
|
||||
@@ -615,9 +601,7 @@
|
||||
MULTI_DENT = /^(?:\n[ \t]*)+/;
|
||||
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
|
||||
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
|
||||
REGEX_START = /^\/([^\/])/;
|
||||
REGEX_END = /^[imgy]{0,4}(?![a-zA-Z])/;
|
||||
REGEX_ESCAPE = /\\[^#]/g;
|
||||
REGEX = /^\/(?!\s)(?:[^[\/\n\\]+|\\.|\[([^\\\]]+|\\.)*])+\/[imgy]{0,4}(?![A-Za-z])/;
|
||||
HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?![A-Za-z])/;
|
||||
HEREGEX_OMIT = /\s+(?:#.*)?/g;
|
||||
MULTILINER = /\n/g;
|
||||
|
||||
Reference in New Issue
Block a user