1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

nagated relational operators are now grouped into NOT_RELATED, fixing #720

This commit is contained in:
satyr 2010-10-06 00:43:44 +09:00
parent 1e60c4c4d2
commit 380bee97dd
9 changed files with 39 additions and 35 deletions

View file

@ -59,7 +59,7 @@ task 'build:parser', 'rebuild the Jison parser (run build first)', ->
parser = require('./lib/grammar').parser
js = parser.generate()
# TODO: Remove this when the Jison patch is released.
js = js.replace 'if (require.main === module)', 'if (typeof module !== "undefined" && require.main === module)'
js = js.replace 'if (require.main === module)', "if (typeof module !== 'undefined' && require.main === module)"
fs.writeFile 'lib/parser.js', js

View file

@ -600,19 +600,15 @@
}), o("Expression IN Expression", function() {
return new InNode($1, $3);
}), o("Expression OF Expression", function() {
return new OpNode('in', $1, $3);
return new OpNode($2, $1, $3);
}), o("Expression INSTANCEOF Expression", function() {
return new OpNode('instanceof', $1, $3);
}), 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)));
}), o("Expression UNARY INSTANCEOF Expression", function() {
return new OpNode($2, new ParentheticalNode(new OpNode('instanceof', $1, $4)));
return new OpNode($2, $1, $3);
}), o("Expression NOT_RELATED Expression", function() {
return $2 === 'in' ? new OpNode('!', new InNode($1, $3)) : new OpNode('!', new ParentheticalNode(new OpNode($2, $1, $3)));
})
]
};
operators = [["right", '?'], ["left", 'CALL_START', 'CALL_END'], ["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', 'SUPER', 'CLASS', 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']];
operators = [["right", '?'], ["left", 'CALL_START', 'CALL_END'], ["nonassoc", '++', '--'], ["right", 'UNARY'], ["left", 'MATH'], ["left", '+', '-'], ["left", 'SHIFT'], ["left", 'COMPARE'], ["left", 'INSTANCEOF', 'NOT_RELATED'], ["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', 'SUPER', 'CLASS', 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']];
tokens = [];
for (name in grammar) {
if (!__hasProp.call(grammar, name)) continue;

View file

@ -1,5 +1,5 @@
(function() {
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, CONVERSIONS, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEGATABLE, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, include, last, starts;
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, CONVERSIONS, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, include, last, starts;
Rewriter = require('./rewriter').Rewriter;
_ref = require('./helpers'), include = _ref.include, count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
exports.Lexer = (function() {
@ -28,7 +28,7 @@
return (new Rewriter).rewrite(this.tokens);
};
Lexer.prototype.identifierToken = function() {
var closeIndex, forcedIdentifier, id, match, tag;
var _ref2, closeIndex, forcedIdentifier, id, match, tag;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return false;
}
@ -46,6 +46,9 @@
tag = 'LEADING_WHEN';
} else if (include(UNARY, tag)) {
tag = 'UNARY';
} else if (('not' === (_ref2 = include(RELATION, tag) && this.value()) || '!' === _ref2)) {
this.tokens.pop();
tag = 'NOT_RELATED';
}
}
if (include(JS_FORBIDDEN, id)) {
@ -602,9 +605,9 @@
SHIFT = ['<<', '>>', '>>>'];
COMPARE = ['<=', '<', '>', '>='];
MATH = ['*', '/', '%'];
RELATION = ['IN', 'OF', 'INSTANCEOF'];
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
NEGATABLE = ['IN', 'OF', 'INSTANCEOF'];
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
CONVERSIONS = {
'and': '&&',

View file

@ -1346,7 +1346,8 @@
__extends(OpNode, BaseNode);
OpNode.prototype.CONVERSIONS = {
'==': '===',
'!=': '!=='
'!=': '!==',
of: 'in'
};
OpNode.prototype.INVERSIONS = {
'!==': '===',

File diff suppressed because one or more lines are too long

View file

@ -553,11 +553,13 @@ grammar =
o "Value COMPOUND_ASSIGN INDENT Expression OUTDENT", -> new OpNode $2, $1, $4
o "Expression IN Expression", -> new InNode $1, $3
o "Expression OF Expression", -> new OpNode 'in', $1, $3
o "Expression INSTANCEOF Expression", -> new OpNode 'instanceof', $1, $3
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
o "Expression UNARY INSTANCEOF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'instanceof', $1, $4
o "Expression OF Expression", -> new OpNode $2, $1, $3
o "Expression INSTANCEOF Expression", -> new OpNode $2, $1, $3
o "Expression NOT_RELATED Expression", ->
if $2 is 'in'
new OpNode '!', new InNode $1, $3
else
new OpNode '!', new ParentheticalNode new OpNode $2, $1, $3
]
@ -581,7 +583,7 @@ operators = [
["left", '+', '-']
["left", 'SHIFT']
["left", 'COMPARE']
["left", 'INSTANCEOF']
["left", 'INSTANCEOF', 'NOT_RELATED']
["left", '==', '!=']
["left", 'LOGIC']
["right", 'COMPOUND_ASSIGN']

View file

@ -86,6 +86,9 @@ exports.Lexer = class Lexer
tag = 'LEADING_WHEN'
else if include UNARY, tag
tag = 'UNARY'
else if include(RELATION, tag) and @value() in ['not', '!']
@tokens.pop()
tag = 'NOT_RELATED'
if include JS_FORBIDDEN, id
if forcedIdentifier
tag = 'STRING'
@ -588,6 +591,9 @@ COMPARE = ['<=', '<', '>', '>=']
# Mathmatical tokens.
MATH = ['*', '/', '%']
# Relational tokens that are negatable with `not` prefix.
RELATION = ['IN', 'OF', 'INSTANCEOF']
# Tokens which a regular expression will never immediately follow, but which
# a division operator might.
#

View file

@ -1130,6 +1130,7 @@ exports.OpNode = class OpNode extends BaseNode
CONVERSIONS:
'==': '==='
'!=': '!=='
of: 'in'
# The map of invertible operators.
INVERSIONS:

View file

@ -139,6 +139,5 @@ ok c is 3
# Instanceof.
# FIXME: These parentheses are workaround of #720
ok (new String) instanceof String
ok (new Number) not instanceof String
ok new String instanceof String
ok new Number not instanceof String