Permalink
Browse files

more simplifications to operators

  • Loading branch information...
1 parent 2d7adc2 commit 956637dbece15cddfdf586dd9cf7ce121c95cbef @jashkenas jashkenas committed Mar 22, 2010
Showing with 78 additions and 58 deletions.
  1. +11 −11 lib/grammar.js
  2. +6 −8 lib/lexer.js
  3. +3 −8 lib/nodes.js
  4. +7 −7 lib/parser.js
  5. +22 −1 lib/rewriter.js
  6. +8 −8 src/grammar.coffee
  7. +6 −8 src/lexer.coffee
  8. +2 −7 src/nodes.coffee
  9. +13 −0 src/rewriter.coffee
View
@@ -519,8 +519,8 @@
return new OpNode('+', $2);
}), {
prec: 'UPLUS'
- }), o("NOT Expression", function() {
- return new OpNode('not', $2);
+ }), o("! Expression", function() {
+ return new OpNode('!', $2);
}), o("~ Expression", function() {
return new OpNode('~', $2);
}), o("-- Expression", function() {
@@ -565,14 +565,14 @@
return new OpNode('>', $1, $3);
}), o("Expression >= Expression", function() {
return new OpNode('>=', $1, $3);
- }), o("Expression IS Expression", function() {
- return new OpNode('is', $1, $3);
- }), o("Expression ISNT Expression", function() {
- return new OpNode('isnt', $1, $3);
- }), o("Expression AND Expression", function() {
- return new OpNode('and', $1, $3);
- }), o("Expression OR Expression", function() {
- return new OpNode('or', $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() {
@@ -605,7 +605,7 @@
// 2 + (3 * 4)
// And not:
// (2 + 3) * 4
- operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', 'NOT', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", 'IS', 'ISNT'], ["left", 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', '<-', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
+ operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', '<-', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
// Wrapping Up
// -----------
// Finally, now what we have our **grammar** and our **operators**, we can create
View
@@ -131,6 +131,7 @@
if (include(KEYWORDS, id) && !(include(ACCESSORS, this.tag(0)) && !this.prev().spaced)) {
tag = id.toUpperCase();
}
+ tag = CONVERSIONS[tag] || tag;
if (include(RESERVED, id)) {
this.identifier_error(id);
}
@@ -366,7 +367,6 @@
tag = 'INDEX_START';
}
}
- tag = CONVERSIONS[tag] || tag;
this.token(tag, value);
this.i = this.i + value.length;
return true;
@@ -632,12 +632,10 @@
// Translations from JS aliases into CoffeeScript operators:
// The map of conversions from CoffeeScript to JavaScript symbols.
CONVERSIONS = {
- '==': 'IS',
- '!=': 'ISNT',
- '&&': 'AND',
- '||': 'OR',
- '===': 'IS',
- '!==': 'ISNT',
- '!': 'NOT'
+ 'IS': '==',
+ 'ISNT': '!=',
+ 'AND': '&&',
+ 'OR': '||',
+ 'NOT': '!'
};
})();
View
@@ -1226,12 +1226,7 @@
// The map of conversions from CoffeeScript to JavaScript symbols.
OpNode.prototype.CONVERSIONS = {
'==': '===',
- '!=': '!==',
- 'and': '&&',
- 'or': '||',
- 'is': '===',
- 'isnt': '!==',
- 'not': '!'
+ '!=': '!=='
};
// The list of operators for which we perform
// [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin).
@@ -1585,11 +1580,11 @@
_a = []; _b = this.condition;
for (i = 0, _c = _b.length; i < _c; i++) {
cond = _b[i];
- _a.push(new OpNode('is', (i === 0 ? assigner : this.switcher), cond));
+ _a.push(new OpNode('===', (i === 0 ? assigner : this.switcher), cond));
}
return _a;
} else {
- return new OpNode('is', assigner, this.condition);
+ return new OpNode('===', assigner, this.condition);
}
}).call(this);
if (this.is_chain()) {
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -1,5 +1,5 @@
(function(){
- var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, helpers, include, pair;
+ var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, OPERATORS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, helpers, include, pair;
var __hasProp = Object.prototype.hasOwnProperty;
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
// and shorthand syntax. This can greatly complicate a grammar and bloat
@@ -30,6 +30,7 @@
this.adjust_comments();
this.remove_leading_newlines();
this.remove_mid_expression_newlines();
+ this.rewrite_half_assignments();
this.close_open_calls_and_indexes();
this.add_implicit_indentation();
this.add_implicit_parentheses();
@@ -106,6 +107,24 @@
});
})(this));
};
+ // Assignment to half-expressions `value: or default` is transformed into a
+ // real JS token, depending on whitespace.
+ Rewriter.prototype.rewrite_half_assignments = function rewrite_half_assignments() {
+ return this.scan_tokens((function(__this) {
+ var __func = function(prev, token, post, i) {
+ var op;
+ if (!(post && post.spaced && token[0] === 'ASSIGN' && include(OPERATORS, post[0]))) {
+ return 1;
+ }
+ op = post[1] + '=';
+ this.tokens.splice(i, 2, [op, op, token[2]]);
+ return 1;
+ };
+ return (function() {
+ return __func.apply(__this, arguments);
+ });
+ })(this));
+ };
// The lexer has tagged the opening parenthesis of a method call, and the
// opening bracket of an indexing operation. Match them with their paired
// close.
@@ -388,4 +407,6 @@
// The grammar can't disambiguate them, so we insert the implicit indentation.
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN'];
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
+ // List of the operations that can be used as half-assignments.
+ OPERATORS = ['-', '+', '/', '*', '%', 'OR', 'AND', '?'];
})();
View
@@ -464,7 +464,7 @@ grammar: {
o "!! Expression", -> new OpNode '!!', $2
o("- Expression", (-> new OpNode('-', $2)), {prec: 'UMINUS'})
o("+ Expression", (-> new OpNode('+', $2)), {prec: 'UPLUS'})
- o "NOT Expression", -> new OpNode 'not', $2
+ o "! Expression", -> new OpNode '!', $2
o "~ Expression", -> new OpNode '~', $2
o "-- Expression", -> new OpNode '--', $2
o "++ Expression", -> new OpNode '++', $2
@@ -492,11 +492,11 @@ grammar: {
o "Expression > Expression", -> new OpNode '>', $1, $3
o "Expression >= Expression", -> new OpNode '>=', $1, $3
- o "Expression IS Expression", -> new OpNode 'is', $1, $3
- o "Expression ISNT Expression", -> new OpNode 'isnt', $1, $3
+ o "Expression == Expression", -> new OpNode '==', $1, $3
+ o "Expression != Expression", -> new OpNode '!=', $1, $3
- o "Expression AND Expression", -> new OpNode 'and', $1, $3
- o "Expression OR Expression", -> new OpNode 'or', $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
@@ -527,15 +527,15 @@ grammar: {
# (2 + 3) * 4
operators: [
["left", '?']
- ["nonassoc", 'UMINUS', 'UPLUS', 'NOT', '!!', '~', '++', '--']
+ ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--']
["left", '*', '/', '%']
["left", '+', '-']
["left", '<<', '>>', '>>>']
["left", '&', '|', '^']
["left", '<=', '<', '>', '>=']
["right", 'DELETE', 'INSTANCEOF', 'TYPEOF']
- ["left", 'IS', 'ISNT']
- ["left", 'AND', 'OR']
+ ["left", '==', '!=']
+ ["left", '&&', '||']
["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=']
["left", '.']
["right", 'INDENT']
View
@@ -97,6 +97,7 @@ exports.Lexer: class Lexer
tag: 'IDENTIFIER'
tag: id.toUpperCase() if include(KEYWORDS, id) and
not (include(ACCESSORS, @tag(0)) and not @prev().spaced)
+ tag: CONVERSIONS[tag] or tag
@identifier_error id if include RESERVED, id
tag: 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag()
@token(tag, id)
@@ -267,7 +268,6 @@ exports.Lexer: class Lexer
else if include(CALLABLE, @tag()) and not_spaced
tag: 'CALL_START' if value is '('
tag: 'INDEX_START' if value is '['
- tag: CONVERSIONS[tag] or tag
@token tag, value
@i: @i + value.length
true
@@ -512,11 +512,9 @@ LINE_BREAK: ['INDENT', 'OUTDENT', 'TERMINATOR']
# Translations from JS aliases into CoffeeScript operators:
# The map of conversions from CoffeeScript to JavaScript symbols.
CONVERSIONS: {
- '==': 'IS'
- '!=': 'ISNT'
- '&&': 'AND'
- '||': 'OR'
- '===': 'IS'
- '!==': 'ISNT'
- '!': 'NOT'
+ 'IS': '=='
+ 'ISNT': '!='
+ 'AND': '&&'
+ 'OR': '||'
+ 'NOT': '!'
}
View
@@ -911,11 +911,6 @@ exports.OpNode: class OpNode extends BaseNode
CONVERSIONS: {
'==': '==='
'!=': '!=='
- 'and': '&&'
- 'or': '||'
- 'is': '==='
- 'isnt': '!=='
- 'not': '!'
}
# The list of operators for which we perform
@@ -1196,9 +1191,9 @@ exports.IfNode: class IfNode extends BaseNode
@switcher: variable
@condition: if @multiple
for cond, i in @condition
- new OpNode('is', (if i is 0 then assigner else @switcher), cond)
+ new OpNode('===', (if i is 0 then assigner else @switcher), cond)
else
- new OpNode('is', assigner, @condition)
+ new OpNode('===', assigner, @condition)
@else_body.rewrite_condition(@switcher) if @is_chain()
this
Oops, something went wrong.

0 comments on commit 956637d

Please sign in to comment.