raising the precedence level of delete, instanceof, and typeof

This commit is contained in:
Jeremy Ashkenas 2010-02-09 22:20:04 -05:00
parent 8e3e06a6e9
commit 9339058fc3
7 changed files with 722 additions and 657 deletions

View File

@ -27,10 +27,10 @@ prechigh
left '+' '-'
left '<<' '>>' '>>>' '&' '|' '^'
left '<=' '<' '>' '>='
right DELETE INSTANCEOF TYPEOF
right '==' '!=' IS ISNT
left '&&' '||' AND OR
right '-=' '+=' '/=' '*=' '%=' '||=' '&&=' '?='
right DELETE INSTANCEOF TYPEOF
right INDENT
left OUTDENT
right WHEN LEADING_WHEN IN OF BY

View File

@ -1,5 +1,5 @@
(function(){
var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, Expressions, ExtendsNode, IndexNode, LiteralNode, Node, ObjectNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ValueNode, WhileNode, any, compact, del, dup, flatten, inherit, merge, statement;
var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, Expressions, ExtendsNode, IndexNode, LiteralNode, Node, ObjectNode, OpNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ValueNode, WhileNode, any, compact, del, dup, flatten, inherit, merge, statement;
var __hasProp = Object.prototype.hasOwnProperty;
process.mixin(require('./scope'));
// The abstract base class for all CoffeeScript nodes.
@ -1030,4 +1030,37 @@
}
}));
statement(WhileNode);
// Simple Arithmetic and logical operations. Performs some conversion from
// CoffeeScript operations into their JavaScript equivalents.
OpNode = (exports.OpNode = inherit(Node, {
CONVERSIONS: {
'==': '===',
'!=': '!==',
'and': '&&',
'or': '||',
'is': '===',
'isnt': '!==',
'not': '!'
},
CHAINABLE: ['<', '>', '>=', '<=', '===', '!=='],
ASSIGNMENT: ['||=', '&&=', '?='],
PREFIX_OPERATORS: ['typeof', 'delete'],
constructor: function constructor(operator, first, second, flip) {
this.children = [(this.first = first), (this.second = second)];
this.operator = this.CONVERSIONS[operator] || operator;
this.flip = !!flip;
return this;
},
is_unary: function is_unary() {
return !this.second;
},
is_chainable: function is_chainable() {
return this.CHAINABLE.indexOf(this.operator) >= 0;
},
compile_node: function compile_node(o) {
if (this.is_chainable() && (this.first.unwrap() instanceof OpNode) && this.first.unwrap().is_chainable()) {
return this.compile_chain(o);
}
}
}));
})();

View File

@ -747,7 +747,7 @@ module CoffeeScript
:isnt => "!==",
:not => '!'
}
CHAINABLE = [:<, :>, :>=, :<=, :===, :'!===']
CHAINABLE = [:<, :>, :>=, :<=, :===, :'!==']
ASSIGNMENT = [:'||=', :'&&=', :'?=']
PREFIX_OPERATORS = [:typeof, :delete]

View File

@ -17,7 +17,7 @@
}
};
// Precedence ===========================================================
operators = [["left", '?'], ["right", 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'], ["right", 'THROW', 'FOR', 'NEW', 'SUPER'], ["left", 'EXTENDS'], ["left", '||=', '&&=', '?='], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
operators = [["left", '?'], ["right", 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY'], ["right", 'THROW', 'FOR', 'NEW', 'SUPER'], ["left", 'EXTENDS'], ["left", '||=', '&&=', '?='], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
// Grammar ==============================================================
grammar = {
// All parsing will end in this rule, being the trunk of the AST.

File diff suppressed because it is too large Load Diff

View File

@ -742,7 +742,41 @@ WhileNode: exports.WhileNode: inherit Node, {
statement WhileNode
# Simple Arithmetic and logical operations. Performs some conversion from
# CoffeeScript operations into their JavaScript equivalents.
OpNode: exports.OpNode: inherit Node, {
CONVERSIONS: {
'==': '==='
'!=': '!=='
'and': '&&'
'or': '||'
'is': '==='
'isnt': '!=='
'not': '!'
}
CHAINABLE: ['<', '>', '>=', '<=', '===', '!==']
ASSIGNMENT: ['||=', '&&=', '?=']
PREFIX_OPERATORS: ['typeof', 'delete']
constructor: (operator, first, second, flip) ->
@children: [@first: first, @second: second]
@operator: @CONVERSIONS[operator] or operator
@flip: !!flip
this
is_unary: ->
not @second
is_chainable: ->
@CHAINABLE.indexOf(@operator) >= 0
compile_node: (o) ->
return @compile_chain(o) if @is_chainable() and (@first.unwrap() instanceof OpNode) and @first.unwrap().is_chainable()
}

View File

@ -24,10 +24,10 @@ operators: [
["left", '<<', '>>', '>>>']
["left", '&', '|', '^']
["left", '<=', '<', '>', '>=']
["right", 'DELETE', 'INSTANCEOF', 'TYPEOF']
["right", '==', '!=', 'IS', 'ISNT']
["left", '&&', '||', 'AND', 'OR']
["right", '-=', '+=', '/=', '*=', '%=']
["right", 'DELETE', 'INSTANCEOF', 'TYPEOF']
["left", '.']
["right", 'INDENT']
["left", 'OUTDENT']