mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Remove seenFor in favor of a safe scanLineBack.
This commit is contained in:
parent
f9a0bbbc20
commit
9395d58669
3 changed files with 62 additions and 19 deletions
|
@ -51,6 +51,31 @@
|
|||
}
|
||||
return i - 1;
|
||||
};
|
||||
Rewriter.prototype.scanLineBack = function(i, condition) {
|
||||
var levels, token, tokens, _ref, _ref2, _ref3;
|
||||
tokens = this.tokens;
|
||||
levels = 0;
|
||||
while (token = tokens[i--]) {
|
||||
if ((_ref = token[0], __indexOf.call(LINEBREAKS, _ref) >= 0) && !token.generated) {
|
||||
return false;
|
||||
}
|
||||
if (_ref2 = token[0], __indexOf.call(EXPRESSION_START, _ref2) >= 0) {
|
||||
levels -= 1;
|
||||
} else if (_ref3 = token[0], __indexOf.call(EXPRESSION_END, _ref3) >= 0) {
|
||||
levels += 1;
|
||||
}
|
||||
if (levels > 0) {
|
||||
continue;
|
||||
}
|
||||
if (levels < 0) {
|
||||
return false;
|
||||
}
|
||||
if (condition.call(this, token, i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, tag, _len, _ref;
|
||||
_ref = this.tokens;
|
||||
|
@ -151,8 +176,8 @@
|
|||
});
|
||||
};
|
||||
Rewriter.prototype.addImplicitParentheses = function() {
|
||||
var action, noCall, seenFor;
|
||||
noCall = seenFor = false;
|
||||
var action, noCall;
|
||||
noCall = false;
|
||||
action = function(token, i) {
|
||||
var idx;
|
||||
idx = token[0] === 'OUTDENT' ? i + 1 : i;
|
||||
|
@ -164,28 +189,27 @@
|
|||
if (tag === 'CLASS' || tag === 'IF') {
|
||||
noCall = true;
|
||||
}
|
||||
if (tag === 'FOR') {
|
||||
seenFor = true;
|
||||
}
|
||||
_ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
|
||||
seenSingle = false;
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
noCall = seenFor = false;
|
||||
noCall = false;
|
||||
}
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0) && !(seenFor && (tag === '->' || tag === '=>') && next && next[0] === 'INDENT'))) {
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
if ((tag === '->' || tag === '=>') && this.scanLineBack(i, function(token, i) {
|
||||
return token[0] === 'FOR';
|
||||
})) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
this.detectEnd(i + 1, function(token, i) {
|
||||
var post, _ref, _ref2;
|
||||
var post, _ref;
|
||||
tag = token[0];
|
||||
if (seenFor && (tag === '->' || tag === '=>') && ((_ref = this.tokens[i + 1]) != null ? _ref[0] : void 0) === 'INDENT') {
|
||||
return true;
|
||||
}
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
|
@ -195,7 +219,7 @@
|
|||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && __indexOf.call(IMPLICIT_END, tag) >= 0 && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref2 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref2) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
return !token.generated && this.tag(i - 1) !== ',' && __indexOf.call(IMPLICIT_END, tag) >= 0 && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
}, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
|
|
|
@ -54,6 +54,20 @@ class exports.Rewriter
|
|||
i += 1
|
||||
i - 1
|
||||
|
||||
scanLineBack: (i, condition) ->
|
||||
{tokens} = this
|
||||
levels = 0
|
||||
while token = tokens[i--]
|
||||
return no if token[0] in LINEBREAKS and not token.generated
|
||||
if token[0] in EXPRESSION_START
|
||||
levels -= 1
|
||||
else if token[0] in EXPRESSION_END
|
||||
levels += 1
|
||||
continue if levels > 0
|
||||
return no if levels < 0
|
||||
return yes if condition.call this, token, i
|
||||
no
|
||||
|
||||
# Leading newlines would introduce an ambiguity in the grammar, so we
|
||||
# dispatch them here.
|
||||
removeLeadingNewlines: ->
|
||||
|
@ -129,30 +143,28 @@ class exports.Rewriter
|
|||
# Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
# deal with them.
|
||||
addImplicitParentheses: ->
|
||||
noCall = seenFor = no
|
||||
noCall = no
|
||||
action = (token, i) ->
|
||||
idx = if token[0] is 'OUTDENT' then i + 1 else i
|
||||
@tokens.splice idx, 0, ['CALL_END', ')', token[2]]
|
||||
@scanTokens (token, i, tokens) ->
|
||||
tag = token[0]
|
||||
noCall = yes if tag in ['CLASS', 'IF']
|
||||
seenFor = yes if tag is 'FOR'
|
||||
[prev, current, next] = tokens[i - 1 .. i + 1]
|
||||
callObject = not noCall and tag is 'INDENT' and
|
||||
next and next.generated and next[0] is '{' and
|
||||
prev and prev[0] in IMPLICIT_FUNC
|
||||
seenSingle = no
|
||||
if tag in LINEBREAKS
|
||||
noCall = seenFor = no
|
||||
noCall = no if tag in LINEBREAKS
|
||||
token.call = yes if prev and not prev.spaced and tag is '?'
|
||||
return 1 unless callObject or
|
||||
prev?.spaced and (prev.call or prev[0] in IMPLICIT_FUNC) and
|
||||
(tag in IMPLICIT_CALL or not (token.spaced or token.newLine) and tag in IMPLICIT_UNSPACED_CALL) and
|
||||
not (seenFor and tag in ['->', '=>'] and next and next[0] is 'INDENT')
|
||||
(tag in IMPLICIT_CALL or not (token.spaced or token.newLine) and tag in IMPLICIT_UNSPACED_CALL)
|
||||
if tag in ['->', '=>'] and @scanLineBack(i, (token, i) -> token[0] is 'FOR')
|
||||
return 1
|
||||
tokens.splice i, 0, ['CALL_START', '(', token[2]]
|
||||
@detectEnd i + 1, (token, i) ->
|
||||
[tag] = token
|
||||
return yes if seenFor and tag in ['->', '=>'] and @tokens[i + 1]?[0] is 'INDENT'
|
||||
return yes if not seenSingle and token.fromThen
|
||||
seenSingle = yes if tag in ['IF', 'ELSE', '->', '=>']
|
||||
return yes if tag in ['.', '?.', '::'] and @tag(i - 1) is 'OUTDENT'
|
||||
|
|
|
@ -286,3 +286,10 @@ arrayEq (break for [1..10]), []
|
|||
|
||||
# Comprehensions over continue.
|
||||
arrayEq (break for [1..10]), []
|
||||
|
||||
|
||||
# Comprehensions over function literals.
|
||||
a = 0
|
||||
for f in [-> a = 1] -> f()
|
||||
|
||||
eq a, 1
|
||||
|
|
Loading…
Reference in a new issue