1
0
Fork 0
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:
Jeremy Ashkenas 2010-12-23 11:22:01 -08:00
parent f9a0bbbc20
commit 9395d58669
3 changed files with 62 additions and 19 deletions

View file

@ -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';

View file

@ -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'

View file

@ -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