Issue #958. Removing UNLESS tokens to make them just inverted IFs.
This commit is contained in:
parent
7ba0573702
commit
53363e6b80
|
@ -474,13 +474,13 @@
|
|||
],
|
||||
IfBlock: [
|
||||
o('IF Expression Block', function() {
|
||||
return new If($2, $3);
|
||||
}), o('UNLESS Expression Block', function() {
|
||||
return new If($2, $3, {
|
||||
invert: true
|
||||
type: $1
|
||||
});
|
||||
}), o('IfBlock ELSE IF Expression Block', function() {
|
||||
return $1.addElse(new If($4, $5));
|
||||
return $1.addElse(new If($4, $5, {
|
||||
type: $3
|
||||
}));
|
||||
}), o('IfBlock ELSE Block', function() {
|
||||
return $1.addElse($3);
|
||||
})
|
||||
|
@ -488,22 +488,14 @@
|
|||
If: [
|
||||
o('IfBlock'), o('Statement POST_IF Expression', function() {
|
||||
return new If($3, Expressions.wrap([$1]), {
|
||||
type: $2,
|
||||
statement: true
|
||||
});
|
||||
}), o('Expression POST_IF Expression', function() {
|
||||
return new If($3, Expressions.wrap([$1]), {
|
||||
type: $2,
|
||||
statement: true
|
||||
});
|
||||
}), o('Statement POST_UNLESS Expression', function() {
|
||||
return new If($3, Expressions.wrap([$1]), {
|
||||
statement: true,
|
||||
invert: true
|
||||
});
|
||||
}), o('Expression POST_UNLESS Expression', function() {
|
||||
return new If($3, Expressions.wrap([$1]), {
|
||||
statement: true,
|
||||
invert: true
|
||||
});
|
||||
})
|
||||
],
|
||||
Operation: [
|
||||
|
@ -556,7 +548,7 @@
|
|||
})
|
||||
]
|
||||
};
|
||||
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF', 'POST_UNLESS']];
|
||||
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
|
||||
tokens = [];
|
||||
for (name in grammar) {
|
||||
alternatives = grammar[name];
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
} else if (tag === 'UNLESS') {
|
||||
tag = 'IF';
|
||||
} else if (__indexOf.call(UNARY, tag) >= 0) {
|
||||
tag = 'UNARY';
|
||||
} else if (__indexOf.call(RELATION, tag) >= 0) {
|
||||
|
|
|
@ -1952,7 +1952,7 @@
|
|||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
this.condition = options.invert ? condition.invert() : condition;
|
||||
this.condition = options.type === 'unless' ? condition.invert() : condition;
|
||||
this.elseBody = null;
|
||||
this.isChain = false;
|
||||
this.soak = options.soak;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -161,7 +161,7 @@
|
|||
return this.scanTokens(function(token, i, tokens) {
|
||||
var callObject, current, next, prev, seenSingle, tag, _ref, _ref2, _ref3;
|
||||
tag = token[0];
|
||||
if (tag === 'CLASS' || tag === 'IF' || tag === 'UNLESS') {
|
||||
if (tag === 'CLASS' || tag === 'IF') {
|
||||
noCall = true;
|
||||
}
|
||||
_ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
|
@ -183,7 +183,7 @@
|
|||
return true;
|
||||
}
|
||||
tag = token[0];
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'UNLESS' || tag === '->' || tag === '=>') {
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === '->' || tag === '=>') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
|
@ -244,8 +244,8 @@
|
|||
return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
var original, _ref;
|
||||
if ((_ref = token[0]) !== 'IF' && _ref !== 'UNLESS') {
|
||||
var original;
|
||||
if (token[0] !== 'IF') {
|
||||
return 1;
|
||||
}
|
||||
original = token;
|
||||
|
@ -343,10 +343,10 @@
|
|||
}
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR', 'INDENT'];
|
||||
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR', 'INDENT'];
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
|
|
|
@ -483,9 +483,8 @@ grammar =
|
|||
# if-related rules are broken up along these lines in order to avoid
|
||||
# ambiguity.
|
||||
IfBlock: [
|
||||
o 'IF Expression Block', -> new If $2, $3
|
||||
o 'UNLESS Expression Block', -> new If $2, $3, invert: true
|
||||
o 'IfBlock ELSE IF Expression Block', -> $1.addElse new If $4, $5
|
||||
o 'IF Expression Block', -> new If $2, $3, type: $1
|
||||
o 'IfBlock ELSE IF Expression Block', -> $1.addElse new If $4, $5, type: $3
|
||||
o 'IfBlock ELSE Block', -> $1.addElse $3
|
||||
]
|
||||
|
||||
|
@ -493,10 +492,8 @@ grammar =
|
|||
# *if* and *unless*.
|
||||
If: [
|
||||
o 'IfBlock'
|
||||
o 'Statement POST_IF Expression', -> new If $3, Expressions.wrap([$1]), statement: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, Expressions.wrap([$1]), statement: true
|
||||
o 'Statement POST_UNLESS Expression', -> new If $3, Expressions.wrap([$1]), statement: true, invert: true
|
||||
o 'Expression POST_UNLESS Expression', -> new If $3, Expressions.wrap([$1]), statement: true, invert: true
|
||||
o 'Statement POST_IF Expression', -> new If $3, Expressions.wrap([$1]), type: $2, statement: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, Expressions.wrap([$1]), type: $2, statement: true
|
||||
]
|
||||
|
||||
# Arithmetic and logical operators, working on one or more operands.
|
||||
|
@ -565,8 +562,8 @@ operators = [
|
|||
['nonassoc', 'INDENT', 'OUTDENT']
|
||||
['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
|
||||
['right', 'FORIN', 'FOROF', 'BY', 'WHEN']
|
||||
['right', 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS']
|
||||
['right', 'POST_IF', 'POST_UNLESS']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS']
|
||||
['right', 'POST_IF']
|
||||
]
|
||||
|
||||
# Wrapping Up
|
||||
|
|
|
@ -89,6 +89,8 @@ exports.Lexer = class Lexer
|
|||
tag = 'LEADING_WHEN'
|
||||
else if tag is 'FOR'
|
||||
@seenFor = yes
|
||||
else if tag is 'UNLESS'
|
||||
tag = 'IF'
|
||||
else if tag in UNARY
|
||||
tag = 'UNARY'
|
||||
else if tag in RELATION
|
||||
|
|
|
@ -1552,7 +1552,7 @@ exports.Switch = class Switch extends Base
|
|||
# because ternaries are already proper expressions, and don't need conversion.
|
||||
exports.If = class If extends Base
|
||||
constructor: (condition, @body, options = {}) ->
|
||||
@condition = if options.invert then condition.invert() else condition
|
||||
@condition = if options.type is 'unless' then condition.invert() else condition
|
||||
@elseBody = null
|
||||
@isChain = false
|
||||
{@soak} = options
|
||||
|
|
|
@ -135,7 +135,7 @@ class exports.Rewriter
|
|||
@tokens.splice idx, 0, ['CALL_END', ')', token[2]]
|
||||
@scanTokens (token, i, tokens) ->
|
||||
tag = token[0]
|
||||
noCall = yes if tag in ['CLASS', 'IF', 'UNLESS']
|
||||
noCall = yes if tag in ['CLASS', 'IF']
|
||||
[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
|
||||
|
@ -150,7 +150,7 @@ class exports.Rewriter
|
|||
@detectEnd i + 1, (token, i) ->
|
||||
return yes if not seenSingle and token.fromThen
|
||||
[tag] = token
|
||||
seenSingle = yes if tag in ['IF', 'ELSE', 'UNLESS', '->', '=>']
|
||||
seenSingle = yes if tag in ['IF', 'ELSE', '->', '=>']
|
||||
return yes if tag in ['.', '?.', '::'] and @tag(i - 1) is 'OUTDENT'
|
||||
not token.generated and @tag(i - 1) isnt ',' and tag in IMPLICIT_END and
|
||||
(tag isnt 'INDENT' or
|
||||
|
@ -198,7 +198,7 @@ class exports.Rewriter
|
|||
tagPostfixConditionals: ->
|
||||
condition = (token, i) -> token[0] in ['TERMINATOR', 'INDENT']
|
||||
@scanTokens (token, i) ->
|
||||
return 1 unless token[0] in ['IF', 'UNLESS']
|
||||
return 1 unless token[0] is 'IF'
|
||||
original = token
|
||||
@detectEnd i + 1, condition, (token, i) ->
|
||||
original[0] = 'POST_' + original[0] if token[0] isnt 'INDENT'
|
||||
|
@ -305,7 +305,7 @@ IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@
|
|||
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL = [
|
||||
'IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS'
|
||||
'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY',
|
||||
'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY',
|
||||
'@', '->', '=>', '[', '(', '{', '--', '++'
|
||||
]
|
||||
|
||||
|
@ -315,7 +315,7 @@ IMPLICIT_UNSPACED_CALL = ['+', '-']
|
|||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']
|
||||
|
||||
# Tokens that always mark the end of an implicit call for single-liners.
|
||||
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR', 'INDENT']
|
||||
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR', 'INDENT']
|
||||
|
||||
# Single-line flavors of block expressions that have unclosed endings.
|
||||
# The grammar can't disambiguate them, so we insert the implicit indentation.
|
||||
|
|
Loading…
Reference in New Issue