mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Reduced the time it takes to build the grammar from 80 seconds to 15, by consolidating Operation terminals by precedence level.
This commit is contained in:
parent
d704afa0e9
commit
8c45aa480b
7 changed files with 136 additions and 237 deletions
|
@ -537,114 +537,56 @@
|
|||
})
|
||||
],
|
||||
Operation: [
|
||||
o("! Expression", function() {
|
||||
return new OpNode('!', $2);
|
||||
}), o("!! Expression", function() {
|
||||
return new OpNode('!!', $2);
|
||||
o("UNARY Expression", function() {
|
||||
return new OpNode($1, $2);
|
||||
}), o("- Expression", (function() {
|
||||
return new OpNode('-', $2);
|
||||
}), {
|
||||
prec: 'UMINUS'
|
||||
prec: 'UNARY'
|
||||
}), o("+ Expression", (function() {
|
||||
return new OpNode('+', $2);
|
||||
}), {
|
||||
prec: 'UPLUS'
|
||||
}), o("~ Expression", function() {
|
||||
return new OpNode('~', $2);
|
||||
prec: 'UNARY'
|
||||
}), o("-- Expression", function() {
|
||||
return new OpNode('--', $2);
|
||||
}), o("++ Expression", function() {
|
||||
return new OpNode('++', $2);
|
||||
}), o("DELETE Expression", function() {
|
||||
return new OpNode('delete', $2);
|
||||
}), o("TYPEOF Expression", function() {
|
||||
return new OpNode('typeof', $2);
|
||||
}), o("Expression --", function() {
|
||||
return new OpNode('--', $1, null, true);
|
||||
}), o("Expression ++", function() {
|
||||
return new OpNode('++', $1, null, true);
|
||||
}), o("Expression * Expression", function() {
|
||||
return new OpNode('*', $1, $3);
|
||||
}), o("Expression / Expression", function() {
|
||||
return new OpNode('/', $1, $3);
|
||||
}), o("Expression % Expression", function() {
|
||||
return new OpNode('%', $1, $3);
|
||||
}), o("Expression + Expression", function() {
|
||||
return new OpNode('+', $1, $3);
|
||||
}), o("Expression - Expression", function() {
|
||||
return new OpNode('-', $1, $3);
|
||||
}), o("Expression << Expression", function() {
|
||||
return new OpNode('<<', $1, $3);
|
||||
}), o("Expression >> Expression", function() {
|
||||
return new OpNode('>>', $1, $3);
|
||||
}), o("Expression >>> Expression", function() {
|
||||
return new OpNode('>>>', $1, $3);
|
||||
}), o("Expression & Expression", function() {
|
||||
return new OpNode('&', $1, $3);
|
||||
}), o("Expression | Expression", function() {
|
||||
return new OpNode('|', $1, $3);
|
||||
}), o("Expression ^ Expression", function() {
|
||||
return new OpNode('^', $1, $3);
|
||||
}), o("Expression <<= Expression", function() {
|
||||
return new OpNode('<<=', $1, $3);
|
||||
}), o("Expression >>= Expression", function() {
|
||||
return new OpNode('>>=', $1, $3);
|
||||
}), o("Expression >>>= Expression", function() {
|
||||
return new OpNode('>>>=', $1, $3);
|
||||
}), o("Expression &= Expression", function() {
|
||||
return new OpNode('&=', $1, $3);
|
||||
}), o("Expression |= Expression", function() {
|
||||
return new OpNode('|=', $1, $3);
|
||||
}), o("Expression ^= Expression", function() {
|
||||
return new OpNode('^=', $1, $3);
|
||||
}), o("Expression <= Expression", function() {
|
||||
return new OpNode('<=', $1, $3);
|
||||
}), o("Expression < Expression", function() {
|
||||
return new OpNode('<', $1, $3);
|
||||
}), o("Expression > Expression", function() {
|
||||
return new OpNode('>', $1, $3);
|
||||
}), o("Expression >= Expression", function() {
|
||||
return new OpNode('>=', $1, $3);
|
||||
}), o("Expression == Expression", function() {
|
||||
return new OpNode('==', $1, $3);
|
||||
}), o("Expression != Expression", function() {
|
||||
return new OpNode('!=', $1, $3);
|
||||
}), o("Expression && Expression", function() {
|
||||
return new OpNode('&&', $1, $3);
|
||||
}), o("Expression || Expression", function() {
|
||||
return new OpNode('||', $1, $3);
|
||||
}), o("Expression OP? Expression", function() {
|
||||
return new OpNode('?', $1, $3);
|
||||
}), o("Expression -= Expression", function() {
|
||||
return new OpNode('-=', $1, $3);
|
||||
}), o("Expression += Expression", function() {
|
||||
return new OpNode('+=', $1, $3);
|
||||
}), o("Expression /= Expression", function() {
|
||||
return new OpNode('/=', $1, $3);
|
||||
}), o("Expression *= Expression", function() {
|
||||
return new OpNode('*=', $1, $3);
|
||||
}), o("Expression %= Expression", function() {
|
||||
return new OpNode('%=', $1, $3);
|
||||
}), o("Expression ||= Expression", function() {
|
||||
return new OpNode('||=', $1, $3);
|
||||
}), o("Expression &&= Expression", function() {
|
||||
return new OpNode('&&=', $1, $3);
|
||||
}), o("Expression ?= Expression", function() {
|
||||
return new OpNode('?=', $1, $3);
|
||||
}), o("Expression MATH Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression SHIFT Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression COMPARE Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression LOGIC Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression COMPOUND_ASSIGN Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression INSTANCEOF Expression", function() {
|
||||
return new OpNode('instanceof', $1, $3);
|
||||
}), o("Expression IN Expression", function() {
|
||||
return new InNode($1, $3);
|
||||
}), o("Expression OF Expression", function() {
|
||||
return new OpNode('in', $1, $3);
|
||||
}), o("Expression ! IN Expression", function() {
|
||||
return new OpNode('!', new InNode($1, $4));
|
||||
}), o("Expression ! OF Expression", function() {
|
||||
return new OpNode('!', new ParentheticalNode(new OpNode('in', $1, $4)));
|
||||
}), o("Expression UNARY IN Expression", function() {
|
||||
return new OpNode($2, new InNode($1, $4));
|
||||
}), o("Expression UNARY OF Expression", function() {
|
||||
return new OpNode($2, new ParentheticalNode(new OpNode('in', $1, $4)));
|
||||
})
|
||||
]
|
||||
};
|
||||
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&', '|', '^'], ["left", '&&', '||', 'OP?'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']];
|
||||
operators = [["left", '?'], ["nonassoc", '++', '--'], ["right", 'UNARY'], ["left", 'MATH'], ["left", '+', '-'], ["left", 'SHIFT'], ["left", 'COMPARE'], ["left", 'INSTANCEOF'], ["left", '==', '!='], ["left", 'LOGIC'], ["right", 'COMPOUND_ASSIGN'], ["left", '.'], ["nonassoc", 'INDENT', 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS', 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']];
|
||||
tokens = [];
|
||||
_a = grammar;
|
||||
for (name in _a) {
|
||||
|
|
40
lib/lexer.js
40
lib/lexer.js
|
@ -1,5 +1,5 @@
|
|||
(function() {
|
||||
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, _a, _b, _c, compact, count, helpers, include, starts;
|
||||
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, SHIFT, STRING_NEWLINES, UNARY, WHITESPACE, _a, _b, _c, compact, count, helpers, include, starts;
|
||||
var __slice = Array.prototype.slice;
|
||||
if ((typeof process !== "undefined" && process !== null)) {
|
||||
_a = require('./rewriter');
|
||||
|
@ -86,6 +86,9 @@
|
|||
if (id === 'all' && this.tag() === 'FOR') {
|
||||
tag = 'ALL';
|
||||
}
|
||||
if (include(UNARY, tag)) {
|
||||
tag = 'UNARY';
|
||||
}
|
||||
if (include(JS_FORBIDDEN, id)) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'STRING';
|
||||
|
@ -105,6 +108,12 @@
|
|||
if (include(COFFEE_ALIASES, id)) {
|
||||
tag = (id = CONVERSIONS[id]);
|
||||
}
|
||||
if (include(LOGIC, id)) {
|
||||
tag = 'LOGIC';
|
||||
}
|
||||
if (id === '!') {
|
||||
tag = 'UNARY';
|
||||
}
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (close_index) {
|
||||
|
@ -305,7 +314,7 @@
|
|||
return true;
|
||||
};
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var _d, match, prevSpaced, space, tag, value;
|
||||
var _d, match, space, spaced, tag, value;
|
||||
match = this.chunk.match(OPERATOR);
|
||||
value = match && match[1];
|
||||
space = match && match[2];
|
||||
|
@ -314,21 +323,32 @@
|
|||
}
|
||||
value = value || this.chunk.substr(0, 1);
|
||||
this.i += value.length;
|
||||
prevSpaced = this.prev() && this.prev().spaced;
|
||||
spaced = this.prev() && this.prev().spaced;
|
||||
tag = value;
|
||||
if (value === '=') {
|
||||
if (include(JS_FORBIDDEN, this.value())) {
|
||||
this.assignmentError();
|
||||
}
|
||||
if (('or' === (_d = this.value()) || 'and' === _d)) {
|
||||
return this.tag(1, CONVERSIONS[this.value()] + '=');
|
||||
this.tokens.splice(this.tokens.length - 1, 1, ['COMPOUND_ASSIGN', CONVERSIONS[this.value()] + '=', this.prev()[2]]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (value === ';') {
|
||||
tag = 'TERMINATOR';
|
||||
} else if (value === '?' && prevSpaced) {
|
||||
tag = 'OP?';
|
||||
} else if (include(CALLABLE, this.tag()) && !prevSpaced) {
|
||||
} else if ((value === '?' && spaced) || include(LOGIC, value)) {
|
||||
tag = 'LOGIC';
|
||||
} else if (include(MATH, value)) {
|
||||
tag = 'MATH';
|
||||
} else if (include(COMPARE, value)) {
|
||||
tag = 'COMPARE';
|
||||
} else if (include(COMPOUND_ASSIGN, value)) {
|
||||
tag = 'COMPOUND_ASSIGN';
|
||||
} else if (include(UNARY, value)) {
|
||||
tag = 'UNARY';
|
||||
} else if (include(SHIFT, value)) {
|
||||
tag = 'SHIFT';
|
||||
} else if (include(CALLABLE, this.tag()) && !spaced) {
|
||||
if (value === '(') {
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[') {
|
||||
|
@ -597,6 +617,12 @@
|
|||
HEREDOC_INDENT = /(\n+([ \t]*)|^([ \t]+))/g;
|
||||
ASSIGNED = /^\s*(([a-zA-Z\$_@]\w*|["'][^\r\n]+?["']|\d+)[ \t]*?[:=][^=])/;
|
||||
NEXT_CHARACTER = /^\s*(\S)/;
|
||||
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
|
||||
UNARY = ['UMINUS', 'UPLUS', '!', '!!', '~', 'TYPEOF', 'DELETE'];
|
||||
LOGIC = ['&', '|', '^', '&&', '||'];
|
||||
SHIFT = ['<<', '>>', '>>>'];
|
||||
COMPARE = ['<=', '<', '>', '>='];
|
||||
MATH = ['*', '/', '%'];
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
|
||||
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
|
|
110
lib/parser.js
110
lib/parser.js
File diff suppressed because one or more lines are too long
|
@ -181,7 +181,7 @@
|
|||
return this.scanTokens(function(token, i) {
|
||||
var _c, action, condition, prev;
|
||||
prev = this.tokens[i - 1];
|
||||
if (prev && prev.spaced && include(IMPLICIT_FUNC, prev[0]) && include(IMPLICIT_CALL, token[0]) && !(token[0] === '!' && (('IN' === (_c = this.tag(i + 1)) || 'OF' === _c)))) {
|
||||
if (prev && prev.spaced && include(IMPLICIT_FUNC, prev[0]) && include(IMPLICIT_CALL, token[0]) && !(token[0] === 'UNARY' && (('IN' === (_c = this.tag(i + 1)) || 'OF' === _c)))) {
|
||||
this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
condition = function(token, i) {
|
||||
return (!token.generated && this.tokens[i - 1][0] !== ',' && include(IMPLICIT_END, token[0]) && !(token[0] === 'INDENT' && (include(IMPLICIT_BLOCK, this.tag(i - 1)) || this.tag(i - 2) === 'CLASS'))) || token[0] === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT';
|
||||
|
@ -375,7 +375,7 @@
|
|||
})();
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'THIS', 'NULL', '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', 'YES', 'NO', 'ON', 'OFF', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'];
|
||||
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN'];
|
||||
|
|
|
@ -520,65 +520,31 @@ grammar =
|
|||
# -type rule, but in order to make the precedence binding possible, separate
|
||||
# rules are necessary.
|
||||
Operation: [
|
||||
o "! Expression", -> new OpNode '!', $2
|
||||
o "!! Expression", -> new OpNode '!!', $2
|
||||
o("- Expression", (-> new OpNode('-', $2)), {prec: 'UMINUS'})
|
||||
o("+ Expression", (-> new OpNode('+', $2)), {prec: 'UPLUS'})
|
||||
o "~ Expression", -> new OpNode '~', $2
|
||||
o "UNARY Expression", -> new OpNode $1, $2
|
||||
o("- Expression", (-> new OpNode('-', $2)), {prec: 'UNARY'})
|
||||
o("+ Expression", (-> new OpNode('+', $2)), {prec: 'UNARY'})
|
||||
|
||||
o "-- Expression", -> new OpNode '--', $2
|
||||
o "++ Expression", -> new OpNode '++', $2
|
||||
o "DELETE Expression", -> new OpNode 'delete', $2
|
||||
o "TYPEOF Expression", -> new OpNode 'typeof', $2
|
||||
o "Expression --", -> new OpNode '--', $1, null, true
|
||||
o "Expression ++", -> new OpNode '++', $1, null, true
|
||||
|
||||
o "Expression * Expression", -> new OpNode '*', $1, $3
|
||||
o "Expression / Expression", -> new OpNode '/', $1, $3
|
||||
o "Expression % Expression", -> new OpNode '%', $1, $3
|
||||
|
||||
o "Expression + Expression", -> new OpNode '+', $1, $3
|
||||
o "Expression - Expression", -> new OpNode '-', $1, $3
|
||||
|
||||
o "Expression << Expression", -> new OpNode '<<', $1, $3
|
||||
o "Expression >> Expression", -> new OpNode '>>', $1, $3
|
||||
o "Expression >>> Expression", -> new OpNode '>>>', $1, $3
|
||||
o "Expression & Expression", -> new OpNode '&', $1, $3
|
||||
o "Expression | Expression", -> new OpNode '|', $1, $3
|
||||
o "Expression ^ Expression", -> new OpNode '^', $1, $3
|
||||
|
||||
o "Expression <<= Expression", -> new OpNode '<<=', $1, $3
|
||||
o "Expression >>= Expression", -> new OpNode '>>=', $1, $3
|
||||
o "Expression >>>= Expression", -> new OpNode '>>>=', $1, $3
|
||||
o "Expression &= Expression", -> new OpNode '&=', $1, $3
|
||||
o "Expression |= Expression", -> new OpNode '|=', $1, $3
|
||||
o "Expression ^= Expression", -> new OpNode '^=', $1, $3
|
||||
|
||||
o "Expression <= Expression", -> new OpNode '<=', $1, $3
|
||||
o "Expression < Expression", -> new OpNode '<', $1, $3
|
||||
o "Expression > Expression", -> new OpNode '>', $1, $3
|
||||
o "Expression >= Expression", -> new OpNode '>=', $1, $3
|
||||
|
||||
o "Expression == Expression", -> new OpNode '==', $1, $3
|
||||
o "Expression != Expression", -> new OpNode '!=', $1, $3
|
||||
|
||||
o "Expression && Expression", -> new OpNode '&&', $1, $3
|
||||
o "Expression || Expression", -> new OpNode '||', $1, $3
|
||||
o "Expression OP? Expression", -> new OpNode '?', $1, $3
|
||||
|
||||
o "Expression -= Expression", -> new OpNode '-=', $1, $3
|
||||
o "Expression += Expression", -> new OpNode '+=', $1, $3
|
||||
o "Expression /= Expression", -> new OpNode '/=', $1, $3
|
||||
o "Expression *= Expression", -> new OpNode '*=', $1, $3
|
||||
o "Expression %= Expression", -> new OpNode '%=', $1, $3
|
||||
o "Expression ||= Expression", -> new OpNode '||=', $1, $3
|
||||
o "Expression &&= Expression", -> new OpNode '&&=', $1, $3
|
||||
o "Expression ?= Expression", -> new OpNode '?=', $1, $3
|
||||
o "Expression MATH Expression", -> new OpNode $2, $1, $3
|
||||
o "Expression SHIFT Expression", -> new OpNode $2, $1, $3
|
||||
o "Expression COMPARE Expression", -> new OpNode $2, $1, $3
|
||||
o "Expression LOGIC Expression", -> new OpNode $2, $1, $3
|
||||
o "Expression COMPOUND_ASSIGN Expression", -> new OpNode $2, $1, $3
|
||||
|
||||
o "Expression INSTANCEOF Expression", -> new OpNode 'instanceof', $1, $3
|
||||
o "Expression IN Expression", -> new InNode $1, $3
|
||||
o "Expression OF Expression", -> new OpNode 'in', $1, $3
|
||||
o "Expression ! IN Expression", -> new OpNode '!', new InNode $1, $4
|
||||
o "Expression ! OF Expression", -> new OpNode '!', new ParentheticalNode new OpNode 'in', $1, $4
|
||||
o "Expression UNARY IN Expression", -> new OpNode $2, new InNode $1, $4
|
||||
o "Expression UNARY OF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'in', $1, $4
|
||||
]
|
||||
|
||||
|
||||
|
@ -595,22 +561,20 @@ grammar =
|
|||
# (2 + 3) * 4
|
||||
operators = [
|
||||
["left", '?']
|
||||
["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--']
|
||||
["left", '*', '/', '%']
|
||||
["nonassoc", '++', '--']
|
||||
["right", 'UNARY']
|
||||
["left", 'MATH']
|
||||
["left", '+', '-']
|
||||
["left", '<<', '>>', '>>>']
|
||||
["left", '<=', '<', '>', '>=']
|
||||
["right", 'DELETE', 'INSTANCEOF', 'TYPEOF']
|
||||
["left", 'SHIFT']
|
||||
["left", 'COMPARE']
|
||||
["left", 'INSTANCEOF']
|
||||
["left", '==', '!=']
|
||||
["left", '&', '|', '^']
|
||||
["left", '&&', '||', 'OP?']
|
||||
["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']
|
||||
["left", 'LOGIC']
|
||||
["right", 'COMPOUND_ASSIGN']
|
||||
["left", '.']
|
||||
["right", 'INDENT']
|
||||
["left", 'OUTDENT']
|
||||
["nonassoc", 'INDENT', 'OUTDENT']
|
||||
["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW']
|
||||
["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS']
|
||||
["left", 'EXTENDS']
|
||||
["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS', 'EXTENDS']
|
||||
["right", '=', ':', 'RETURN']
|
||||
["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']
|
||||
]
|
||||
|
|
|
@ -88,6 +88,7 @@ exports.Lexer = class Lexer
|
|||
tag = id.toUpperCase() if include(JS_KEYWORDS, id) or (not forcedIdentifier and include(COFFEE_KEYWORDS, id))
|
||||
tag = 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag()
|
||||
tag = 'ALL' if id is 'all' and @tag() is 'FOR'
|
||||
tag = 'UNARY' if include UNARY, tag
|
||||
if include(JS_FORBIDDEN, id)
|
||||
if forcedIdentifier
|
||||
tag = 'STRING'
|
||||
|
@ -100,6 +101,8 @@ exports.Lexer = class Lexer
|
|||
@identifierError id
|
||||
unless forcedIdentifier
|
||||
tag = id = CONVERSIONS[id] if include COFFEE_ALIASES, id
|
||||
tag = 'LOGIC' if include LOGIC, id
|
||||
tag = 'UNARY' if id is '!'
|
||||
@token tag, id
|
||||
@token ']', ']' if close_index
|
||||
true
|
||||
|
@ -269,17 +272,21 @@ exports.Lexer = class Lexer
|
|||
@tagParameters() if value and value.match CODE
|
||||
value or= @chunk.substr 0, 1
|
||||
@i += value.length
|
||||
prevSpaced = @prev() and @prev().spaced
|
||||
spaced = @prev() and @prev().spaced
|
||||
tag = value
|
||||
if value is '='
|
||||
@assignmentError() if include JS_FORBIDDEN, @value()
|
||||
if @value() in ['or', 'and']
|
||||
return @tag 1, CONVERSIONS[@value()] + '='
|
||||
if value is ';'
|
||||
tag = 'TERMINATOR'
|
||||
else if value is '?' and prevSpaced
|
||||
tag = 'OP?'
|
||||
else if include(CALLABLE, @tag()) and not prevSpaced
|
||||
@tokens.splice(@tokens.length - 1, 1, ['COMPOUND_ASSIGN', CONVERSIONS[@value()] + '=', @prev()[2]])
|
||||
return true
|
||||
if value is ';' then tag = 'TERMINATOR'
|
||||
else if (value is '?' and spaced) or include(LOGIC, value) then tag = 'LOGIC'
|
||||
else if include(MATH, value) then tag = 'MATH'
|
||||
else if include(COMPARE, value) then tag = 'COMPARE'
|
||||
else if include(COMPOUND_ASSIGN, value) then tag = 'COMPOUND_ASSIGN'
|
||||
else if include(UNARY, value) then tag = 'UNARY'
|
||||
else if include(SHIFT, value) then tag = 'SHIFT'
|
||||
else if include(CALLABLE, @tag()) and not spaced
|
||||
if value is '('
|
||||
tag = 'CALL_START'
|
||||
else if value is '['
|
||||
|
@ -534,6 +541,24 @@ HEREDOC_INDENT = /(\n+([ \t]*)|^([ \t]+))/g
|
|||
ASSIGNED = /^\s*(([a-zA-Z\$_@]\w*|["'][^\r\n]+?["']|\d+)[ \t]*?[:=][^=])/
|
||||
NEXT_CHARACTER = /^\s*(\S)/
|
||||
|
||||
# Compound assignment tokens.
|
||||
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']
|
||||
|
||||
# Unary tokens.
|
||||
UNARY = ['UMINUS', 'UPLUS', '!', '!!', '~', 'TYPEOF', 'DELETE']
|
||||
|
||||
# Logical tokens.
|
||||
LOGIC = ['&', '|', '^', '&&', '||']
|
||||
|
||||
# Bit-shifting tokens.
|
||||
SHIFT = ['<<', '>>', '>>>']
|
||||
|
||||
# Comparison tokens.
|
||||
COMPARE = ['<=', '<', '>', '>=']
|
||||
|
||||
# Mathmatical tokens.
|
||||
MATH = ['*', '/', '%']
|
||||
|
||||
# Tokens which a regular expression will never immediately follow, but which
|
||||
# a division operator might.
|
||||
#
|
||||
|
|
|
@ -154,7 +154,7 @@ exports.Rewriter = class Rewriter
|
|||
@scanTokens (token, i) ->
|
||||
prev = @tokens[i - 1]
|
||||
if prev and prev.spaced and include(IMPLICIT_FUNC, prev[0]) and include(IMPLICIT_CALL, token[0]) and
|
||||
not (token[0] is '!' and (@tag(i + 1) in ['IN', 'OF']))
|
||||
not (token[0] is 'UNARY' and (@tag(i + 1) in ['IN', 'OF']))
|
||||
@tokens.splice i, 0, ['CALL_START', '(', token[2]]
|
||||
condition = (token, i) ->
|
||||
(not token.generated and @tokens[i - 1][0] isnt ',' and include(IMPLICIT_END, token[0]) and
|
||||
|
@ -316,9 +316,9 @@ 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', 'DELETE', 'TYPEOF', 'SWITCH', 'THIS', 'NULL',
|
||||
'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY'
|
||||
'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF',
|
||||
'!', '!!', '@', '->', '=>', '[', '(', '{'
|
||||
'@', '->', '=>', '[', '(', '{'
|
||||
]
|
||||
|
||||
# Tokens indicating that the implicit call must enclose a block of expressions.
|
||||
|
|
Loading…
Add table
Reference in a new issue