lexer now distinguishes between IN/OF and FORIN/FOROF to help grammar, fixing #737

This commit is contained in:
satyr
2010-10-06 04:46:17 +09:00
parent 380bee97dd
commit 2e6b50335f
8 changed files with 101 additions and 90 deletions

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, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, 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, 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, op, 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() {
@@ -16,6 +16,7 @@
this.indent = 0;
this.indebt = 0;
this.outdebt = 0;
this.seenFor = false;
this.indents = [];
this.tokens = [];
while ((this.chunk = code.slice(this.i))) {
@@ -28,7 +29,7 @@
return (new Rewriter).rewrite(this.tokens);
};
Lexer.prototype.identifierToken = function() {
var _ref2, closeIndex, forcedIdentifier, id, match, tag;
var closeIndex, forcedIdentifier, id, match, tag;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return false;
}
@@ -44,11 +45,21 @@
tag = id.toUpperCase();
if (tag === 'WHEN' && include(LINE_BREAK, this.tag())) {
tag = 'LEADING_WHEN';
} else if (tag === 'FOR') {
this.seenFor = true;
} else if (include(UNARY, tag)) {
tag = 'UNARY';
} else if (('not' === (_ref2 = include(RELATION, tag) && this.value()) || '!' === _ref2)) {
this.tokens.pop();
tag = 'NOT_RELATED';
} else if (include(RELATION, tag)) {
if (tag !== 'INSTANCEOF' && this.seenFor) {
this.seenFor = false;
tag = 'FOR' + tag;
} else {
tag = 'RELATION';
if (this.value() === '!') {
this.tokens.pop();
id = '!' + id;
}
}
}
}
if (include(JS_FORBIDDEN, id)) {
@@ -67,8 +78,8 @@
}
}
if (!(forcedIdentifier)) {
if (include(COFFEE_ALIASES, id)) {
tag = (id = CONVERSIONS[id]);
if (COFFEE_ALIASES.hasOwnProperty(id)) {
tag = (id = COFFEE_ALIASES[id]);
}
if (id === '!') {
tag = 'UNARY';
@@ -330,7 +341,7 @@
if (('or' === pval || 'and' === pval)) {
prev = last(this.tokens);
prev[0] = 'COMPOUND_ASSIGN';
prev[1] = CONVERSIONS[pval] + '=';
prev[1] = COFFEE_ALIASES[pval] + '=';
return true;
}
}
@@ -575,8 +586,18 @@
return Lexer;
})();
JS_KEYWORDS = ['if', 'else', 'true', 'false', 'new', 'return', 'try', 'catch', 'finally', 'throw', 'break', 'continue', 'for', 'in', 'while', 'delete', 'instanceof', 'typeof', 'switch', 'super', 'extends', 'class', 'this', 'null', 'debugger'];
COFFEE_ALIASES = ['and', 'or', 'is', 'isnt', 'not'];
COFFEE_KEYWORDS = COFFEE_ALIASES.concat(['then', 'unless', 'until', 'loop', 'yes', 'no', 'on', 'off', 'of', 'by', 'when']);
COFFEE_KEYWORDS = ['then', 'unless', 'until', 'loop', 'yes', 'no', 'on', 'off', 'of', 'by', 'when'];
COFFEE_ALIASES = {
and: '&&',
or: '||',
is: '==',
isnt: '!=',
not: '!'
};
for (op in COFFEE_ALIASES) {
COFFEE_KEYWORDS.push(op);
}
COFFEE_ALIASES['==='] = '==';
RESERVED = ['case', 'default', 'do', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice'];
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
IDENTIFIER = /^[a-zA-Z_$][\w$]*/;
@@ -609,12 +630,4 @@
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
CONVERSIONS = {
'and': '&&',
'or': '||',
'is': '==',
'isnt': '!=',
'not': '!',
'===': '=='
};
}).call(this);