mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
one step further
This commit is contained in:
parent
ddf18ae34c
commit
acd9be3863
2 changed files with 35 additions and 12 deletions
23
lib/lexer.js
23
lib/lexer.js
|
@ -1,5 +1,5 @@
|
|||
(function(){
|
||||
var ACCESSORS, ASSIGNMENT, CALLABLE, CODE, COFFEE_KEYWORDS, COMMENT, COMMENT_CLEANER, HEREDOC, HEREDOC_INDENT, IDENTIFIER, INTERPOLATION, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_ESCAPE, REGEX_FLAGS, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, balanced_string, compact, count, helpers, include, starts;
|
||||
var ACCESSORS, ASSIGNMENT, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMMENT_CLEANER, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, INTERPOLATION, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_ESCAPE, REGEX_FLAGS, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, balanced_string, compact, count, helpers, include, starts;
|
||||
// The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
|
||||
// matches against the beginning of the source code. When a match is found,
|
||||
// a token is produced, we consume the match, and start again. Tokens are in the
|
||||
|
@ -122,13 +122,14 @@
|
|||
// referenced as property names here, so you can still do `jQuery.is()` even
|
||||
// though `is` means `===` otherwise.
|
||||
Lexer.prototype.identifier_token = function identifier_token() {
|
||||
var id, tag;
|
||||
var id, space, tag;
|
||||
if (!((id = this.match(IDENTIFIER, 1)))) {
|
||||
return false;
|
||||
}
|
||||
this.name_access_type();
|
||||
space = this.prev() && this.prev().spaced;
|
||||
tag = 'IDENTIFIER';
|
||||
if (include(KEYWORDS, id) && !(include(ACCESSORS, this.tag(0)) && !this.prev().spaced)) {
|
||||
if (include(KEYWORDS, id) && !(include(ACCESSORS, this.tag(0)) && !space)) {
|
||||
tag = id.toUpperCase();
|
||||
}
|
||||
if (include(RESERVED, id)) {
|
||||
|
@ -137,8 +138,11 @@
|
|||
if (tag === 'WHEN' && include(LINE_BREAK, this.tag())) {
|
||||
tag = 'LEADING_WHEN';
|
||||
}
|
||||
this.token(tag, id);
|
||||
this.i += id.length;
|
||||
if (space && include(COFFEE_ALIASES, id)) {
|
||||
tag = (id = CONVERSIONS[id]);
|
||||
}
|
||||
this.token(tag, id);
|
||||
return true;
|
||||
};
|
||||
// Matches numbers, including decimals, hex, and exponential notation.
|
||||
|
@ -576,7 +580,8 @@
|
|||
JS_KEYWORDS = ["if", "else", "true", "false", "new", "return", "try", "catch", "finally", "throw", "break", "continue", "for", "in", "while", "delete", "instanceof", "typeof", "switch", "super", "extends", "class"];
|
||||
// CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
|
||||
// be used standalone, but you can reference them as an attached property.
|
||||
COFFEE_KEYWORDS = ["then", "unless", "yes", "no", "on", "off", "and", "or", "is", "isnt", "not", "of", "by", "where", "when"];
|
||||
COFFEE_ALIASES = ["and", "or", "is", "isnt", "not"];
|
||||
COFFEE_KEYWORDS = COFFEE_ALIASES.concat(["then", "unless", "yes", "no", "on", "off", "of", "by", "where", "when"]);
|
||||
// The combined list of keywords is the superset that gets passed verbatim to
|
||||
// the parser.
|
||||
KEYWORDS = JS_KEYWORDS.concat(COFFEE_KEYWORDS);
|
||||
|
@ -628,4 +633,12 @@
|
|||
// occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
// avoid an ambiguity in the grammar.
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
// Conversions from CoffeeScript operators into JavaScript ones.
|
||||
CONVERSIONS = {
|
||||
'and': '&&',
|
||||
'or': '||',
|
||||
'is': '==',
|
||||
'isnt': '!=',
|
||||
'not': '!'
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -94,13 +94,14 @@ exports.Lexer: class Lexer
|
|||
identifier_token: ->
|
||||
return false unless id: @match IDENTIFIER, 1
|
||||
@name_access_type()
|
||||
space: @prev() and @prev().spaced
|
||||
tag: 'IDENTIFIER'
|
||||
tag: id.toUpperCase() if include(KEYWORDS, id) and
|
||||
not (include(ACCESSORS, @tag(0)) and not @prev().spaced)
|
||||
@identifier_error id if include RESERVED, id
|
||||
tag: 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag()
|
||||
@token(tag, id)
|
||||
tag: id.toUpperCase() if include(KEYWORDS, id) and not (include(ACCESSORS, @tag(0)) and not space)
|
||||
@identifier_error id if include RESERVED, id
|
||||
tag: 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag()
|
||||
@i += id.length
|
||||
tag: id: CONVERSIONS[id] if space and include(COFFEE_ALIASES, id)
|
||||
@token(tag, id)
|
||||
true
|
||||
|
||||
# Matches numbers, including decimals, hex, and exponential notation.
|
||||
|
@ -432,10 +433,10 @@ JS_KEYWORDS: [
|
|||
|
||||
# CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
|
||||
# be used standalone, but you can reference them as an attached property.
|
||||
COFFEE_KEYWORDS: [
|
||||
COFFEE_ALIASES: ["and", "or", "is", "isnt", "not"]
|
||||
COFFEE_KEYWORDS: COFFEE_ALIASES.concat [
|
||||
"then", "unless",
|
||||
"yes", "no", "on", "off",
|
||||
"and", "or", "is", "isnt", "not",
|
||||
"of", "by", "where", "when"
|
||||
]
|
||||
|
||||
|
@ -507,3 +508,12 @@ ACCESSORS: ['PROPERTY_ACCESS', 'PROTOTYPE_ACCESS', 'SOAK_ACCESS', '@']
|
|||
# occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
# avoid an ambiguity in the grammar.
|
||||
LINE_BREAK: ['INDENT', 'OUTDENT', 'TERMINATOR']
|
||||
|
||||
# Conversions from CoffeeScript operators into JavaScript ones.
|
||||
CONVERSIONS: {
|
||||
'and': '&&'
|
||||
'or': '||'
|
||||
'is': '=='
|
||||
'isnt': '!='
|
||||
'not': '!'
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue