mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
removed YES/NO/ON/OFF from rewriter/parser
This commit is contained in:
@@ -68,14 +68,8 @@
|
||||
return new Literal(true);
|
||||
}), o("FALSE", function() {
|
||||
return new Literal(false);
|
||||
}), o("YES", function() {
|
||||
return new Literal(true);
|
||||
}), o("NO", function() {
|
||||
return new Literal(false);
|
||||
}), o("ON", function() {
|
||||
return new Literal(true);
|
||||
}), o("OFF", function() {
|
||||
return new Literal(false);
|
||||
}), o("NULL", function() {
|
||||
return new Literal('null');
|
||||
})
|
||||
],
|
||||
Assign: [
|
||||
@@ -178,9 +172,7 @@
|
||||
return new Value($1);
|
||||
}), o("Range", function() {
|
||||
return new Value($1);
|
||||
}), o("This"), o("NULL", function() {
|
||||
return new Value(new Literal('null'));
|
||||
})
|
||||
}), o("This")
|
||||
],
|
||||
Accessor: [
|
||||
o("PROPERTY_ACCESS Identifier", function() {
|
||||
|
||||
@@ -577,13 +577,17 @@
|
||||
return Lexer;
|
||||
})();
|
||||
JS_KEYWORDS = ['if', 'else', 'true', 'false', 'new', 'return', 'try', 'catch', 'finally', 'throw', 'break', 'continue', 'for', 'in', 'while', 'delete', 'instanceof', 'typeof', 'switch', 'super', 'extends', 'class', 'this', 'null', 'debugger'];
|
||||
COFFEE_KEYWORDS = ['then', 'unless', 'until', 'loop', 'yes', 'no', 'on', 'off', 'of', 'by', 'when'];
|
||||
COFFEE_KEYWORDS = ['then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
|
||||
for (op in (COFFEE_ALIASES = {
|
||||
and: '&&',
|
||||
or: '||',
|
||||
is: '==',
|
||||
isnt: '!=',
|
||||
not: '!'
|
||||
not: '!',
|
||||
yes: 'TRUE',
|
||||
no: 'FALSE',
|
||||
on: 'TRUE',
|
||||
off: 'FALSE'
|
||||
})) {
|
||||
COFFEE_KEYWORDS.push(op);
|
||||
}
|
||||
|
||||
364
lib/parser.js
364
lib/parser.js
File diff suppressed because one or more lines are too long
@@ -146,27 +146,28 @@
|
||||
return this.tokens.splice(i, 0, ['}', '}', token[2]]);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var idx, last, tag, tok;
|
||||
var idx, tag, tok;
|
||||
if (include(EXPRESSION_START, tag = token[0])) {
|
||||
stack.push(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag);
|
||||
return 1;
|
||||
}
|
||||
if (include(EXPRESSION_END, tag)) {
|
||||
stack.pop();
|
||||
return 1;
|
||||
}
|
||||
last = stack[stack.length - 1];
|
||||
if (tag === ':' && !(last && last[0] === '{')) {
|
||||
stack.push('{');
|
||||
idx = this.tag(i - 2) === '@' ? i - 2 : i - 1;
|
||||
if (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
tok = ['{', '{', token[2]];
|
||||
tok.generated = true;
|
||||
tokens.splice(idx, 0, tok);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
return 2;
|
||||
if (!(tag === ':' && stack[stack.length - 1] !== '{')) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
stack.push('{');
|
||||
idx = this.tag(i - 2) === '@' ? i - 2 : i - 1;
|
||||
if (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
tok = ['{', '{', token[2]];
|
||||
tok.generated = true;
|
||||
tokens.splice(idx, 0, tok);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
exports.Rewriter.prototype.addImplicitParentheses = function() {
|
||||
@@ -178,18 +179,14 @@
|
||||
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var _ref, callObject, condition, idx, next, prev, seenSingle, tag;
|
||||
var callObject, next, prev, seenSingle, tag;
|
||||
tag = token[0];
|
||||
if (tag === 'CLASS') {
|
||||
classLine = true;
|
||||
}
|
||||
prev = tokens[i - 1];
|
||||
next = tokens[i + 1];
|
||||
idx = 1;
|
||||
callObject = !classLine && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && include(IMPLICIT_FUNC, prev[0]);
|
||||
if (callObject) {
|
||||
idx = 2;
|
||||
}
|
||||
seenSingle = false;
|
||||
if (include(LINEBREAKS, tag)) {
|
||||
classLine = false;
|
||||
@@ -197,29 +194,28 @@
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (callObject || prev && prev.spaced && (prev.call || include(IMPLICIT_FUNC, prev[0])) && include(IMPLICIT_CALL, tag) && !(tag === 'UNARY' && ('IN' === (_ref = this.tag(i + 1)) || 'OF' === _ref || 'INSTANCEOF' === _ref))) {
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
condition = function(token, i) {
|
||||
var post;
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
tag = token[0];
|
||||
if (('IF' === tag || 'ELSE' === tag || 'UNLESS' === tag || '->' === tag || '=>' === tag)) {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && include(IMPLICIT_END, tag) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && !include(IMPLICIT_BLOCK, this.tag(i - 1)) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
};
|
||||
this.detectEnd(i + idx, condition, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
return 2;
|
||||
if (!(callObject || ((prev != null) ? prev.spaced : undefined) && (prev.call || include(IMPLICIT_FUNC, prev[0])) && include(IMPLICIT_CALL, tag))) {
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
this.detectEnd(i + (callObject ? 2 : 1), function(token, i) {
|
||||
var post;
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
tag = token[0];
|
||||
if (('IF' === tag || 'ELSE' === tag || 'UNLESS' === tag || '->' === tag || '=>' === tag)) {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && include(IMPLICIT_END, tag) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && !include(IMPLICIT_BLOCK, this.tag(i - 1)) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
}, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
exports.Rewriter.prototype.addImplicitIndentation = function() {
|
||||
@@ -369,7 +365,7 @@
|
||||
}
|
||||
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', 'NULL', 'UNARY', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY', 'TRUE', 'FALSE', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'];
|
||||
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
|
||||
|
||||
@@ -132,10 +132,7 @@ grammar =
|
||||
o "REGEX", -> new Literal $1
|
||||
o "TRUE", -> new Literal true
|
||||
o "FALSE", -> new Literal false
|
||||
o "YES", -> new Literal true
|
||||
o "NO", -> new Literal false
|
||||
o "ON", -> new Literal true
|
||||
o "OFF", -> new Literal false
|
||||
o "NULL", -> new Literal 'null'
|
||||
]
|
||||
|
||||
# Assignment of a variable, property, or index to a value.
|
||||
@@ -238,7 +235,6 @@ grammar =
|
||||
o "Parenthetical", -> new Value $1
|
||||
o "Range", -> new Value $1
|
||||
o "This"
|
||||
o "NULL", -> new Value new Literal 'null'
|
||||
]
|
||||
|
||||
# The general group of accessors into an object, by property, by prototype
|
||||
|
||||
@@ -518,17 +518,17 @@ JS_KEYWORDS = [
|
||||
]
|
||||
|
||||
# CoffeeScript-only keywords.
|
||||
COFFEE_KEYWORDS = [
|
||||
'then', 'unless', 'until', 'loop'
|
||||
'yes', 'no', 'on', 'off'
|
||||
'of', 'by', 'when'
|
||||
]
|
||||
COFFEE_KEYWORDS = ['then', 'unless', 'until', 'loop', 'of', 'by', 'when']
|
||||
COFFEE_KEYWORDS.push op for all op of COFFEE_ALIASES =
|
||||
and : '&&'
|
||||
or : '||'
|
||||
is : '=='
|
||||
isnt : '!='
|
||||
not : '!'
|
||||
yes : 'TRUE'
|
||||
no : 'FALSE'
|
||||
on : 'TRUE'
|
||||
off : 'FALSE'
|
||||
COFFEE_ALIASES['==='] = '=='
|
||||
|
||||
# The list of keywords that are reserved by JavaScript, but not used, or are
|
||||
|
||||
@@ -132,20 +132,20 @@ class exports.Rewriter
|
||||
action = (token, i) -> @tokens.splice i, 0, ['}', '}', token[2]]
|
||||
@scanTokens (token, i, tokens) ->
|
||||
if include EXPRESSION_START, tag = token[0]
|
||||
stack.push(if tag is 'INDENT' and @tag(i - 1) is '{' then '{' else tag)
|
||||
stack.push if tag is 'INDENT' and @tag(i - 1) is '{' then '{' else tag
|
||||
return 1
|
||||
if include EXPRESSION_END, tag
|
||||
stack.pop()
|
||||
last = stack[stack.length - 1]
|
||||
if tag is ':' and not (last and last[0] is '{')
|
||||
stack.push '{'
|
||||
idx = if @tag(i - 2) is '@' then i - 2 else i - 1
|
||||
idx -= 2 if @tag(idx - 2) is 'HERECOMMENT'
|
||||
tok = ['{', '{', token[2]]
|
||||
tok.generated = yes
|
||||
tokens.splice idx, 0, tok
|
||||
@detectEnd i + 2, condition, action
|
||||
return 2
|
||||
1
|
||||
return 1
|
||||
return 1 unless tag is ':' and stack[stack.length - 1] isnt '{'
|
||||
stack.push '{'
|
||||
idx = if @tag(i - 2) is '@' then i - 2 else i - 1
|
||||
idx -= 2 if @tag(idx - 2) is 'HERECOMMENT'
|
||||
tok = ['{', '{', token[2]]
|
||||
tok.generated = yes
|
||||
tokens.splice idx, 0, tok
|
||||
@detectEnd i + 2, condition, action
|
||||
2
|
||||
|
||||
# Methods may be optionally called without parentheses, for simple cases.
|
||||
# Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
@@ -160,31 +160,28 @@ class exports.Rewriter
|
||||
classLine = yes if tag is 'CLASS'
|
||||
prev = tokens[i - 1]
|
||||
next = tokens[i + 1]
|
||||
idx = 1
|
||||
callObject = not classLine and tag is 'INDENT' and
|
||||
next and next.generated and next[0] is '{' and
|
||||
prev and include(IMPLICIT_FUNC, prev[0])
|
||||
idx = 2 if callObject
|
||||
seenSingle = no
|
||||
classLine = no if include LINEBREAKS, tag
|
||||
token.call = yes if prev and not prev.spaced and tag is '?'
|
||||
if callObject or
|
||||
prev and prev.spaced and (prev.call or include(IMPLICIT_FUNC, prev[0])) and include(IMPLICIT_CALL, tag) and
|
||||
not (tag is 'UNARY' and @tag(i + 1) in ['IN', 'OF', 'INSTANCEOF'])
|
||||
tokens.splice i, 0, ['CALL_START', '(', token[2]]
|
||||
condition = (token, i) ->
|
||||
return yes if not seenSingle and token.fromThen
|
||||
[tag] = token
|
||||
seenSingle = yes if tag in ['IF', 'ELSE', 'UNLESS', '->', '=>']
|
||||
return yes if tag is 'PROPERTY_ACCESS' and @tag(i - 1) is 'OUTDENT'
|
||||
not token.generated and @tag(i - 1) isnt ',' and include(IMPLICIT_END, tag) and
|
||||
(tag isnt 'INDENT' or
|
||||
(@tag(i - 2) isnt 'CLASS' and not include(IMPLICIT_BLOCK, @tag(i - 1)) and
|
||||
not ((post = @tokens[i + 1]) and post.generated and post[0] is '{')))
|
||||
@detectEnd i + idx, condition, action
|
||||
prev[0] = 'FUNC_EXIST' if prev[0] is '?'
|
||||
return 2
|
||||
1
|
||||
return 1 unless callObject or
|
||||
prev?.spaced and (prev.call or include(IMPLICIT_FUNC, prev[0])) and
|
||||
include(IMPLICIT_CALL, tag)
|
||||
tokens.splice i, 0, ['CALL_START', '(', token[2]]
|
||||
@detectEnd i + (if callObject then 2 else 1), (token, i) ->
|
||||
return yes if not seenSingle and token.fromThen
|
||||
[tag] = token
|
||||
seenSingle = yes if tag in ['IF', 'ELSE', 'UNLESS', '->', '=>']
|
||||
return yes if tag is 'PROPERTY_ACCESS' and @tag(i - 1) is 'OUTDENT'
|
||||
not token.generated and @tag(i - 1) isnt ',' and include(IMPLICIT_END, tag) and
|
||||
(tag isnt 'INDENT' or
|
||||
(@tag(i - 2) isnt 'CLASS' and not include(IMPLICIT_BLOCK, @tag(i - 1)) and
|
||||
not ((post = @tokens[i + 1]) and post.generated and post[0] is '{')))
|
||||
, action
|
||||
prev[0] = 'FUNC_EXIST' if prev[0] is '?'
|
||||
2
|
||||
|
||||
# Because our grammar is LALR(1), it can't handle some single-line
|
||||
# expressions that lack ending delimiters. The **Rewriter** adds the implicit
|
||||
@@ -331,8 +328,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', 'NULL', 'UNARY'
|
||||
'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF'
|
||||
'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY', 'TRUE', 'FALSE'
|
||||
'@', '->', '=>', '[', '(', '{'
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user