removing extensions from CoffeeScript
This commit is contained in:
parent
b7faa4a7f2
commit
f7345ffaac
|
@ -57,13 +57,6 @@
|
|||
__dirname = path.dirname(__filename);
|
||||
return eval(exports.compile(code, options));
|
||||
});
|
||||
// Extend CoffeeScript with a custom language extension. It should hook in to
|
||||
// the **Lexer** (as a peer of any of the lexer's tokenizing methods), and
|
||||
// push a token on to the stack that contains a **Node** as the value (as a
|
||||
// peer of the nodes in [nodes.coffee](nodes.html)).
|
||||
exports.extend = function(func) {
|
||||
return Lexer.extensions.push(func);
|
||||
};
|
||||
// The real Lexer produces a generic stream of tokens. This object provides a
|
||||
// thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
// directly as a "Jison lexer".
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
// CoffeeScript is the **Expression** -- everything that can be an expression
|
||||
// is one. Expressions serve as the building blocks of many other rules, making
|
||||
// them somewhat circular.
|
||||
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment"), o("Extension")],
|
||||
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment")],
|
||||
// A an indented block of expressions. Note that the [Rewriter](rewriter.html)
|
||||
// will convert some postfix forms into blocks for us, by adjusting the
|
||||
// token stream.
|
||||
|
@ -453,9 +453,6 @@
|
|||
return new ParentheticalNode($2);
|
||||
})
|
||||
],
|
||||
// A language extension to CoffeeScript from the outside. We simply pass
|
||||
// it through unaltered.
|
||||
Extension: [o("EXTENSION")],
|
||||
// The condition portion of a while loop.
|
||||
WhileSource: [
|
||||
o("WHILE Expression", function() {
|
||||
|
|
22
lib/lexer.js
22
lib/lexer.js
|
@ -74,9 +74,6 @@
|
|||
// short-circuiting if any of them succeed. Their order determines precedence:
|
||||
// `@literalToken` is the fallback catch-all.
|
||||
Lexer.prototype.extractNextToken = function() {
|
||||
if (this.extensionToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.identifierToken()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -108,19 +105,6 @@
|
|||
};
|
||||
// Tokenizers
|
||||
// ----------
|
||||
// Language extensions get the highest priority, first chance to tag tokens
|
||||
// as something else.
|
||||
Lexer.prototype.extensionToken = function() {
|
||||
var _d, _e, _f, extension;
|
||||
_e = Lexer.extensions;
|
||||
for (_d = 0, _f = _e.length; _d < _f; _d++) {
|
||||
extension = _e[_d];
|
||||
if (extension.call(this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// Matches identifying literals: variables, keywords, method names, etc.
|
||||
// Check to ensure that JavaScript reserved words aren't being used as
|
||||
// identifiers. Because CoffeeScript reserves a handful of keywords that are
|
||||
|
@ -667,12 +651,8 @@
|
|||
prev = this.prev(2);
|
||||
return this.value() && this.value().match && this.value().match(NO_NEWLINE) && prev && (prev[0] !== '.') && !this.value().match(CODE);
|
||||
};
|
||||
// Lexer Properties
|
||||
// ----------------
|
||||
// There are no exensions to the core lexer by default.
|
||||
Lexer.extensions = [];
|
||||
return Lexer;
|
||||
}).call(this);
|
||||
})();
|
||||
// Constants
|
||||
// ---------
|
||||
// Keywords that CoffeeScript shares in common with JavaScript.
|
||||
|
|
386
lib/parser.js
386
lib/parser.js
File diff suppressed because one or more lines are too long
|
@ -419,7 +419,7 @@
|
|||
// Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation.
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@'];
|
||||
// If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'EXTENSION', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'THIS', 'NULL', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'THIS', 'NULL', '@', '->', '=>', '[', '(', '{'];
|
||||
// Tokens indicating that the implicit call must enclose a block of expressions.
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
// Tokens that always mark the end of an implicit call for single-liners.
|
||||
|
|
|
@ -55,13 +55,6 @@ exports.run: ((code, options) ->
|
|||
eval exports.compile code, options
|
||||
)
|
||||
|
||||
# Extend CoffeeScript with a custom language extension. It should hook in to
|
||||
# the **Lexer** (as a peer of any of the lexer's tokenizing methods), and
|
||||
# push a token on to the stack that contains a **Node** as the value (as a
|
||||
# peer of the nodes in [nodes.coffee](nodes.html)).
|
||||
exports.extend: (func) ->
|
||||
Lexer.extensions.push func
|
||||
|
||||
# The real Lexer produces a generic stream of tokens. This object provides a
|
||||
# thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
# directly as a "Jison lexer".
|
||||
|
|
|
@ -100,7 +100,6 @@ grammar: {
|
|||
o "Splat"
|
||||
o "Existence"
|
||||
o "Comment"
|
||||
o "Extension"
|
||||
]
|
||||
|
||||
# A an indented block of expressions. Note that the [Rewriter](rewriter.html)
|
||||
|
@ -396,12 +395,6 @@ grammar: {
|
|||
o "( Line )", -> new ParentheticalNode $2
|
||||
]
|
||||
|
||||
# A language extension to CoffeeScript from the outside. We simply pass
|
||||
# it through unaltered.
|
||||
Extension: [
|
||||
o "EXTENSION"
|
||||
]
|
||||
|
||||
# The condition portion of a while loop.
|
||||
WhileSource: [
|
||||
o "WHILE Expression", -> new WhileNode $2
|
||||
|
|
|
@ -60,7 +60,6 @@ exports.Lexer: class Lexer
|
|||
# short-circuiting if any of them succeed. Their order determines precedence:
|
||||
# `@literalToken` is the fallback catch-all.
|
||||
extractNextToken: ->
|
||||
return if @extensionToken()
|
||||
return if @identifierToken()
|
||||
return if @numberToken()
|
||||
return if @heredocToken()
|
||||
|
@ -75,13 +74,6 @@ exports.Lexer: class Lexer
|
|||
# Tokenizers
|
||||
# ----------
|
||||
|
||||
# Language extensions get the highest priority, first chance to tag tokens
|
||||
# as something else.
|
||||
extensionToken: ->
|
||||
for extension in Lexer.extensions
|
||||
return true if extension.call this
|
||||
false
|
||||
|
||||
# Matches identifying literals: variables, keywords, method names, etc.
|
||||
# Check to ensure that JavaScript reserved words aren't being used as
|
||||
# identifiers. Because CoffeeScript reserves a handful of keywords that are
|
||||
|
@ -451,12 +443,6 @@ exports.Lexer: class Lexer
|
|||
@value() and @value().match and @value().match(NO_NEWLINE) and
|
||||
prev and (prev[0] isnt '.') and not @value().match(CODE)
|
||||
|
||||
# Lexer Properties
|
||||
# ----------------
|
||||
|
||||
# There are no exensions to the core lexer by default.
|
||||
@extensions: []
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ IMPLICIT_FUNC: ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@']
|
|||
|
||||
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL: ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START',
|
||||
'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'EXTENSION',
|
||||
'TRY', 'DELETE', 'TYPEOF', 'SWITCH',
|
||||
'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!',
|
||||
'THIS', 'NULL',
|
||||
'@', '->', '=>', '[', '(', '{']
|
||||
|
|
|
@ -6,68 +6,3 @@ js: CoffeeScript.compile("one\r\ntwo", {noWrap: on})
|
|||
|
||||
ok js is "one;\ntwo;"
|
||||
|
||||
|
||||
# Try out language extensions to CoffeeScript.
|
||||
|
||||
# Create the Node were going to add -- a literal syntax for splitting
|
||||
# strings into letters.
|
||||
class SplitNode extends BaseNode
|
||||
type: 'Split'
|
||||
|
||||
constructor: (variable) ->
|
||||
@variable: variable
|
||||
|
||||
compileNode: (o) ->
|
||||
"'${@variable}'.split('')"
|
||||
|
||||
# Extend CoffeeScript with our lexing function that matches --wordgoeshere--
|
||||
# and creates a SplitNode.
|
||||
CoffeeScript.extend ->
|
||||
return false unless variable: @match(/^--(\w+)--/, 1)
|
||||
@i: + variable.length + 4
|
||||
@token 'EXTENSION', new SplitNode(variable)
|
||||
true
|
||||
|
||||
# Compile with the extension.
|
||||
js: CoffeeScript.compile 'return --tobesplit--', {noWrap: on}
|
||||
|
||||
ok js is "return 'tobesplit'.split('');"
|
||||
|
||||
|
||||
# Let's try a different extension, for Ruby-style array literals.
|
||||
|
||||
class WordArrayNode extends BaseNode
|
||||
type: 'WordArray'
|
||||
|
||||
constructor: (words) ->
|
||||
@words: words
|
||||
|
||||
compileNode: (o) ->
|
||||
strings = ("\"$word\"" for word in @words).join ', '
|
||||
"[$strings]"
|
||||
|
||||
CoffeeScript.extend ->
|
||||
return false unless words: @chunk.match(/^%w\{(.*?)\}/)
|
||||
@i: + words[0].length
|
||||
@token 'EXTENSION', new WordArrayNode(words[1].split(/\s+/))
|
||||
true
|
||||
|
||||
js: CoffeeScript.compile 'puts %w{one two three}', {noWrap: on}
|
||||
|
||||
ok js is 'puts(["one", "two", "three"]);'
|
||||
|
||||
|
||||
# Finally, let's try an extension that converts `a << b` into `a.push(b)`.
|
||||
|
||||
CoffeeScript.extend ->
|
||||
return false unless @chunk.match(/^<</)
|
||||
@i: + 2
|
||||
@token 'PROPERTY_ACCESS', '.'
|
||||
@token 'IDENTIFIER', 'push'
|
||||
|
||||
js: CoffeeScript.compile 'a << b', {noWrap: on}
|
||||
|
||||
ok js is 'a.push(b);'
|
||||
|
||||
Lexer.extensions: []
|
||||
|
||||
|
|
Loading…
Reference in New Issue