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 parser = require('./lib/grammar').parser
js = parser.generate() js = parser.generate()
# TODO: Remove this when the Jison patch is released. # 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 fs.writeFile 'lib/parser.js', js

View File

@@ -600,19 +600,15 @@
}), o("Expression IN Expression", function() { }), o("Expression IN Expression", function() {
return new InNode($1, $3); return new InNode($1, $3);
}), o("Expression OF Expression", function() { }), o("Expression OF Expression", function() {
return new OpNode('in', $1, $3); return new OpNode($2, $1, $3);
}), o("Expression INSTANCEOF Expression", function() { }), o("Expression INSTANCEOF Expression", function() {
return new OpNode('instanceof', $1, $3); return new OpNode($2, $1, $3);
}), o("Expression UNARY IN Expression", function() { }), o("Expression NOT_RELATED Expression", function() {
return new OpNode($2, new InNode($1, $4)); return $2 === 'in' ? new OpNode('!', new InNode($1, $3)) : new OpNode('!', new ParentheticalNode(new OpNode($2, $1, $3)));
}), 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)));
}) })
] ]
}; };
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 = []; tokens = [];
for (name in grammar) { for (name in grammar) {
if (!__hasProp.call(grammar, name)) continue; if (!__hasProp.call(grammar, name)) continue;

View File

@@ -1,5 +1,5 @@
(function() { (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; Rewriter = require('./rewriter').Rewriter;
_ref = require('./helpers'), include = _ref.include, count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last; _ref = require('./helpers'), include = _ref.include, count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
exports.Lexer = (function() { exports.Lexer = (function() {
@@ -28,7 +28,7 @@
return (new Rewriter).rewrite(this.tokens); return (new Rewriter).rewrite(this.tokens);
}; };
Lexer.prototype.identifierToken = function() { Lexer.prototype.identifierToken = function() {
var closeIndex, forcedIdentifier, id, match, tag; var _ref2, closeIndex, forcedIdentifier, id, match, tag;
if (!(match = IDENTIFIER.exec(this.chunk))) { if (!(match = IDENTIFIER.exec(this.chunk))) {
return false; return false;
} }
@@ -46,6 +46,9 @@
tag = 'LEADING_WHEN'; tag = 'LEADING_WHEN';
} else if (include(UNARY, tag)) { } else if (include(UNARY, tag)) {
tag = 'UNARY'; tag = 'UNARY';
} else if (('not' === (_ref2 = include(RELATION, tag) && this.value()) || '!' === _ref2)) {
this.tokens.pop();
tag = 'NOT_RELATED';
} }
} }
if (include(JS_FORBIDDEN, id)) { if (include(JS_FORBIDDEN, id)) {
@@ -602,9 +605,9 @@
SHIFT = ['<<', '>>', '>>>']; SHIFT = ['<<', '>>', '>>>'];
COMPARE = ['<=', '<', '>', '>=']; COMPARE = ['<=', '<', '>', '>='];
MATH = ['*', '/', '%']; MATH = ['*', '/', '%'];
RELATION = ['IN', 'OF', 'INSTANCEOF'];
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']']; NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::']; CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
NEGATABLE = ['IN', 'OF', 'INSTANCEOF'];
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
CONVERSIONS = { CONVERSIONS = {
'and': '&&', 'and': '&&',

View File

@@ -1346,7 +1346,8 @@
__extends(OpNode, BaseNode); __extends(OpNode, BaseNode);
OpNode.prototype.CONVERSIONS = { OpNode.prototype.CONVERSIONS = {
'==': '===', '==': '===',
'!=': '!==' '!=': '!==',
of: 'in'
}; };
OpNode.prototype.INVERSIONS = { 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 "Value COMPOUND_ASSIGN INDENT Expression OUTDENT", -> new OpNode $2, $1, $4
o "Expression IN Expression", -> new InNode $1, $3 o "Expression IN Expression", -> new InNode $1, $3
o "Expression OF Expression", -> new OpNode 'in', $1, $3 o "Expression OF Expression", -> new OpNode $2, $1, $3
o "Expression INSTANCEOF Expression", -> new OpNode 'instanceof', $1, $3 o "Expression INSTANCEOF Expression", -> new OpNode $2, $1, $3
o "Expression UNARY IN Expression", -> new OpNode $2, new InNode $1, $4 o "Expression NOT_RELATED Expression", ->
o "Expression UNARY OF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'in', $1, $4 if $2 is 'in'
o "Expression UNARY INSTANCEOF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'instanceof', $1, $4 new OpNode '!', new InNode $1, $3
else
new OpNode '!', new ParentheticalNode new OpNode $2, $1, $3
] ]
@@ -581,7 +583,7 @@ operators = [
["left", '+', '-'] ["left", '+', '-']
["left", 'SHIFT'] ["left", 'SHIFT']
["left", 'COMPARE'] ["left", 'COMPARE']
["left", 'INSTANCEOF'] ["left", 'INSTANCEOF', 'NOT_RELATED']
["left", '==', '!='] ["left", '==', '!=']
["left", 'LOGIC'] ["left", 'LOGIC']
["right", 'COMPOUND_ASSIGN'] ["right", 'COMPOUND_ASSIGN']

View File

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

View File

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

View File

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