Socket
Socket
Sign inDemoInstall

coffeescript

Package Overview
Dependencies
Maintainers
3
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

coffeescript - npm Package Compare versions

Comparing version 2.0.0-beta3 to 2.0.0-beta4

24

lib/coffeescript/browser.js

@@ -1,3 +0,7 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
// This **Browser** compatibility layer extends core CoffeeScript functions
// to make things work smoothly when compiling code directly in the browser.
// We add support for loading remote Coffee scripts via **XHR**, and
// `text/coffeescript` script tags, source maps via data-URLs, and so on.
var CoffeeScript, compile, runScripts,

@@ -10,2 +14,3 @@ indexOf = [].indexOf;

// Use standard JavaScript `eval` to eval code.
CoffeeScript.eval = function(code, options = {}) {

@@ -18,2 +23,3 @@ if (options.bare == null) {

// Running code does not provide access to this scope.
CoffeeScript.run = function(code, options = {}) {

@@ -25,4 +31,7 @@ options.bare = true;

// Export this more limited `CoffeeScript` than what is exported by
// `index.coffee`, which is intended for a Node environment.
module.exports = CoffeeScript;
// If we’re not in a browser environment, we’re finished with the public API.
if (typeof window === "undefined" || window === null) {

@@ -32,2 +41,5 @@ return;

// Include source maps where possible. If we’ve got a base64 encoder, a
// JSON serializer, and tools for escaping unicode characters, we’re good to go.
// Ported from https://developer.mozilla.org/en-US/docs/DOM/window.btoa
if ((typeof btoa !== "undefined" && btoa !== null) && (typeof JSON !== "undefined" && JSON !== null)) {

@@ -40,2 +52,3 @@ compile = function(code, options = {}) {

// Load a remote script from the current domain via XHR.
CoffeeScript.load = function(url, callback, options = {}, hold = false) {

@@ -68,2 +81,5 @@ var xhr;

// Activate CoffeeScript in the browser by having it compile and evaluate
// all script tags with a content-type of `text/coffeescript`.
// This happens on page load.
runScripts = function() {

@@ -107,2 +123,7 @@ var coffees, coffeetypes, execute, fn, i, index, j, len, s, script, scripts;

} else {
// `options.filename` defines the filename the source map appears as
// in Developer Tools. If a script tag has an `id`, use that as the
// filename; otherwise use `coffeescript`, or `coffeescript1` etc.,
// leaving the first one unnumbered for the common case that there’s
// only one CoffeeScript script block to parse.
options.filename = script.id && script.id !== '' ? script.id : `coffeescript${(i !== 0 ? i : '')}`;

@@ -120,2 +141,3 @@ options.sourceFiles = ['embedded'];

// Listen for window load, both in decent browsers and in IE.
if (window.addEventListener) {

@@ -122,0 +144,0 @@ window.addEventListener('DOMContentLoaded', runScripts, false);

@@ -1,3 +0,12 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
// `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
// ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))
// for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
// and can call them from the command line, or invoke them from other tasks.
// Running `cake` with no arguments will print out a list of all the tasks in the
// current directory's Cakefile.
// External dependencies.
var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;

@@ -15,4 +24,6 @@

// Register .coffee extension
CoffeeScript.register();
// Keep track of the list of defined tasks, the accepted options, and so on.
tasks = {};

@@ -26,3 +37,6 @@

// Mixin the top-level Cake functions for Cakefiles to use directly.
helpers.extend(global, {
// Define a Cake task with a short name, an optional sentence description,
// and the function to run as the action itself.
task: function(name, description, action) {

@@ -34,5 +48,9 @@ if (!action) {

},
// Define an option that the Cakefile accepts. The parsed options hash,
// containing all of the command-line options passed, will be made available
// as the first argument to the action.
option: function(letter, flag, description) {
return switches.push([letter, flag, description]);
},
// Invoke another task in the current Cakefile.
invoke: function(name) {

@@ -46,2 +64,6 @@ if (!tasks[name]) {

// Run `cake`. Executes all of the tasks you pass, in order. Note that Node's
// asynchrony may cause tasks to execute in a different order than you'd expect.
// If no tasks are passed, print the help screen. Keep a reference to the
// original directory name, when running Cake tasks from subdirectories.
exports.run = function() {

@@ -74,2 +96,3 @@ var arg, args, e, i, len, ref, results;

// Display the list of Cake tasks in a format similar to `rake -T`
printTasks = function() {

@@ -92,2 +115,3 @@ var cakefilePath, desc, name, relative, spaces, task;

// Print an error and exit when attempting to use an invalid task/option.
fatalError = function(message) {

@@ -103,2 +127,4 @@ console.error(message + '\n');

// When `cake` is invoked, search in the current and all parent directories
// to find the relevant Cakefile.
cakefileDirectory = function(dir) {

@@ -105,0 +131,0 @@ var parent;

@@ -1,4 +0,8 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
var Lexer, SourceMap, base64encode, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors;
// CoffeeScript can be used both on the server, as a command-line compiler based
// on Node.js/V8, or to run CoffeeScript directly in the browser. This module
// contains the main entry functions for tokenizing, parsing, and compiling
// source CoffeeScript into JavaScript.
var Lexer, SourceMap, base64encode, checkShebangLine, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors;

@@ -13,4 +17,7 @@ ({Lexer} = require('./lexer'));

// Require `package.json`, which is two levels above this file, as this file is
// evaluated from `lib/coffeescript`.
packageJson = require('../../package.json');
// The current CoffeeScript version number.
exports.VERSION = packageJson.version;

@@ -20,4 +27,6 @@

// Expose helpers for testing.
exports.helpers = helpers;
// Function that allows for btoa in both nodejs and the browser.
base64encode = function(src) {

@@ -28,2 +37,6 @@ switch (false) {

case typeof btoa !== 'function':
// The contents of a `<script>` block are encoded via UTF-16, so if any extended
// characters are used in the block, btoa will fail as it maxes out at UTF-8.
// See https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem
// for the gory details, and for the solution implemented here.
return btoa(encodeURIComponent(src).replace(/%([0-9A-F]{2})/g, function(match, p1) {

@@ -37,2 +50,4 @@ return String.fromCharCode('0x' + p1);

// Function wrapper to add source file information to SyntaxErrors thrown by the
// lexer/parser/compiler.
withPrettyErrors = function(fn) {

@@ -45,3 +60,3 @@ return function(code, options = {}) {

err = error;
if (typeof code !== 'string') {
if (typeof code !== 'string') { // Support `CoffeeScript.nodes(tokens)`.
throw err;

@@ -54,6 +69,24 @@ }

// For each compiled file, save its source in memory in case we need to
// recompile it later. We might need to recompile if the first compilation
// didn’t create a source map (faster) but something went wrong and we need
// a stack trace. Assuming that most of the time, code isn’t throwing
// exceptions, it’s probably more efficient to compile twice only when we
// need a stack trace, rather than always generating a source map even when
// it’s not likely to be used. Save in form of `filename`: `(source)`
sources = {};
// Also save source maps if generated, in form of `filename`: `(source map)`.
sourceMaps = {};
// Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
// If `options.sourceMap` is specified, then `options.filename` must also be
// specified. All options that can be passed to `SourceMap#generate` may also
// be passed here.
// This returns a javascript string, unless `options.sourceMap` is passed,
// in which case this returns a `{js, v3SourceMap, sourceMap}`
// object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for
// doing programmatic lookups.
exports.compile = compile = withPrettyErrors(function(code, options) {

@@ -63,4 +96,8 @@ var currentColumn, currentLine, encoded, extend, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, merge, newLines, ref, ref1, sourceMapDataURI, sourceURL, token, tokens, v3SourceMap;

options = extend({}, options);
// Always generate a source map if no filename is passed in, since without a
// a filename we have no way to retrieve this source later in the event that
// we need to recompile it to get a source map for `prepareStackTrace`.
generateSourceMap = options.sourceMap || options.inlineMap || (options.filename == null);
filename = options.filename || '<anonymous>';
checkShebangLine(filename, code);
sources[filename] = code;

@@ -71,2 +108,4 @@ if (generateSourceMap) {

tokens = lexer.tokenize(code, options);
// Pass a list of referenced variables, so that generated variables won’t get
// the same name.
options.referencedVars = (function() {

@@ -83,2 +122,3 @@ var i, len, results;

})();
// Check for import or export; if found, force bare mode.
if (!((options.bare != null) && options.bare === true)) {

@@ -105,3 +145,5 @@ for (i = 0, len = tokens.length; i < len; i++) {

fragment = fragments[j];
// Update the sourcemap with data from each fragment.
if (generateSourceMap) {
// Do not include empty, whitespace, or semicolon-only fragments.
if (fragment.locationData && !/^[;\s]*$/.test(fragment.code)) {

@@ -120,2 +162,3 @@ map.add([fragment.locationData.first_line, fragment.locationData.first_column], [currentLine, currentColumn], {

}
// Copy the code from each fragment into the final JavaScript.
js += fragment.code;

@@ -148,2 +191,3 @@ }

// Tokenize a string of CoffeeScript code, and return the array of tokens.
exports.tokens = withPrettyErrors(function(code, options) {

@@ -153,2 +197,5 @@ return lexer.tokenize(code, options);

// Parse a string of CoffeeScript code or an array of lexed tokens, and
// return the AST. You can then compile it by calling `.compile()` on the root,
// or traverse it by using `.traverseChildren()` with a callback.
exports.nodes = withPrettyErrors(function(source, options) {

@@ -162,2 +209,7 @@ if (typeof source === 'string') {

// This file used to export these methods; leave stubs that throw warnings
// instead. These methods have been moved into `index.coffee` to provide
// separate entrypoints for Node and non-Node environments, so that static
// analysis tools don’t choke on Node packages when compiling for a non-Node
// environment.
exports.run = exports.eval = exports.register = function() {

@@ -167,4 +219,8 @@ throw new Error('require index.coffee, not this file');

// Instantiate a Lexer for our use here.
lexer = new Lexer;
// 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".
parser.lexer = {

@@ -188,10 +244,15 @@ lex: function() {

upcomingInput: function() {
return "";
return '';
}
};
// Make all the AST nodes visible to the parser.
parser.yy = require('./nodes');
// Override Jison's default error handling function.
parser.yy.parseError = function(message, {token}) {
var errorLoc, errorTag, errorText, errorToken, tokens;
// Disregard Jison's message, it contains redundant line number information.
// Disregard the token, we take its value directly from the lexer in case
// the error is caused by a generated token which might refer to its origin.
({errorToken, tokens} = parser);

@@ -211,5 +272,11 @@ [errorTag, errorText, errorLoc] = errorToken;

})();
// The second argument has a `loc` property, which should have the location
// data for this token. Unfortunately, Jison seems to send an outdated `loc`
// (from the previous token), so we take the location information directly
// from the lexer.
return helpers.throwSyntaxError(`unexpected ${errorText}`, errorLoc);
};
// Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
// Modified to handle sourceMap
formatSourcePosition = function(frame, getSourceMapping) {

@@ -233,2 +300,3 @@ var as, column, fileLocation, filename, functionName, isConstructor, isMethodCall, line, methodName, source, tp, typeName;

column = frame.getColumnNumber();
// Check for a sourceMap position
source = getSourceMapping(filename, line, column);

@@ -268,2 +336,5 @@ fileLocation = source ? `${filename}:${source[0]}:${source[1]}` : `${filename}:${line}:${column}`;

return sourceMaps[filename];
// CoffeeScript compiled in a browser may get compiled with `options.filename`
// of `<anonymous>`, but the browser may request the stack trace with the
// filename of the script file.
} else if (sourceMaps['<anonymous>'] != null) {

@@ -283,2 +354,6 @@ return sourceMaps['<anonymous>'];

// Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
// NodeJS / V8 have no support for transforming positions in stack traces using
// sourceMap, so we must monkey-patch Error to display CoffeeScript source
// positions.
Error.prepareStackTrace = function(err, stack) {

@@ -313,2 +388,16 @@ var frame, frames, getSourceMapping;

checkShebangLine = function(file, input) {
var args, firstLine, ref, rest;
firstLine = input.split(/$/m)[0];
rest = firstLine != null ? firstLine.match(/^#!\s*([^\s]+\s*)(.*)/) : void 0;
args = rest != null ? (ref = rest[2]) != null ? ref.split(/\s/).filter(function(s) {
return s !== '';
}) : void 0 : void 0;
if ((args != null ? args.length : void 0) > 1) {
console.error('The script to be run begins with a shebang line with more than one\nargument. This script will fail on platforms such as Linux which only\nallow a single argument.');
console.error(`The shebang line was: '${firstLine}' in file '${file}'`);
return console.error(`The arguments were: ${JSON.stringify(args)}`);
}
};
}).call(this);

@@ -1,3 +0,10 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
// The `coffee` utility. Handles command-line compilation of CoffeeScript
// into various forms: saved into `.js` files or printed to stdout
// or recompiled every time the source is saved,
// printed as a token stream or as the syntax tree, or launch an
// interactive REPL.
// External dependencies.
var BANNER, CoffeeScript, EventEmitter, SWITCHES, buildCSOptionParser, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,

@@ -22,2 +29,3 @@ indexOf = [].indexOf;

// Allow CoffeeScript to emit Node.js events.
helpers.extend(CoffeeScript, new EventEmitter);

@@ -37,6 +45,9 @@

BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
// The help banner that is printed in conjunction with `-h`/`--help`.
BANNER = 'Usage: coffee [options] path/to/script.coffee [args]\n\nIf called without options, `coffee` will run your script.';
// The list of all the valid option flags that `coffee` knows how to handle.
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffeescript'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
// Top-level objects shared by all the functions.
opts = {};

@@ -58,6 +69,23 @@

// Run `coffee` by parsing passed options and determining what action to take.
// Many flags cause us to divert before compiling anything. Flags passed after
// `--` will be passed verbatim to your script as arguments in `process.argv`
exports.run = function() {
var i, len, literals, ref, replCliOpts, results, source;
var err, i, len, literals, ref, replCliOpts, results, source;
optionParser = buildCSOptionParser();
parseOptions();
try {
parseOptions();
} catch (error) {
err = error;
console.error(`option parsing error: ${err.message}`);
process.exit(1);
}
if ((!opts.doubleDashed) && (opts.arguments[1] === '--')) {
printWarn('coffee was invoked with \'--\' as the second positional argument, which is\nnow deprecated. To pass \'--\' as an argument to a script to run, put an\nadditional \'--\' before the path to your script.\n\n\'--\' will be removed from the argument list.');
printWarn(`The positional arguments were: ${JSON.stringify(opts.arguments)}`);
opts.arguments = [opts.arguments[0]].concat(opts.arguments.slice(2));
}
// Make the REPL *CLI* use the global context so as to (a) be consistent with the
// `node` REPL CLI and, therefore, (b) make packages that modify native prototypes
// (such as 'colors' and 'sugar') work as expected.
replCliOpts = {

@@ -122,2 +150,5 @@ useGlobal: true

// Compile a path, which could be a script or a directory. If a directory
// is passed, recursively compile all '.coffee', '.litcoffee', and '.coffee.md'
// extension source files in it and all subdirectories.
compilePath = function(source, topLevel, base) {

@@ -210,2 +241,5 @@ var code, err, file, files, i, len, results, stats;

// Compile a single source script, containing the given code, according to the
// requested options. If evaluating the script directly sets `__filename`,
// `__dirname` and `module.filename` to be correct relative to the script's path.
compileScript = function(file, input, base = null) {

@@ -264,2 +298,4 @@ var compiled, err, message, o, options, t, task;

// Attach the appropriate listeners to compile scripts incoming over **stdin**,
// and write them back to **stdout**.
compileStdio = function() {

@@ -279,2 +315,4 @@ var buffers, stdin;

// If all of the source files are done being read, concatenate and compile
// them together.
joinTimeout = null;

@@ -296,2 +334,5 @@

// Watch a source CoffeeScript file using `fs.watch`, recompiling it every
// time the file is updated. May be used in combination with other options,
// such as `--print`.
watch = function(source, base) {

@@ -360,2 +401,3 @@ var compile, compileTimeout, err, prevStats, rewatch, startWatcher, watchErr, watcher;

// Watch a directory of files for new additions.
watchDir = function(source, base) {

@@ -425,2 +467,4 @@ var err, readdirTimeout, startWatcher, stopWatcher, watcher;

// Remove a file from our source list, and source code cache. Optionally remove
// the compiled JS version as well.
removeSource = function(source, base) {

@@ -450,2 +494,3 @@ var index;

// Get the corresponding output JavaScript path for a source file.
outputPath = function(source, base, extension = ".js") {

@@ -465,2 +510,3 @@ var basename, dir, srcDir;

// Recursively mkdir, like `mkdir -p`.
mkdirp = function(dir, fn) {

@@ -487,2 +533,8 @@ var mkdirs, mode;

// Write out a JavaScript source file with the compiled code. By default, files
// are written out in `cwd` as `.js` files with the same name, but the output
// directory can be customized with `--output`.
// If `generatedSourceMap` is provided, this will write a `.js.map` file into the
// same directory as the `.js` file.
writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap = null) {

@@ -527,2 +579,3 @@ var compile, jsDir, sourceMapPath;

// Convenience for cleaner setTimeouts.
wait = function(milliseconds, func) {

@@ -532,2 +585,3 @@ return setTimeout(func, milliseconds);

// When watching scripts, it's useful to log changes with the timestamp.
timeLog = function(message) {

@@ -537,2 +591,3 @@ return console.log(`${(new Date).toLocaleTimeString()} - ${message}`);

// Pretty-print a stream of tokens, sans location data.
printTokens = function(tokens) {

@@ -554,2 +609,4 @@ var strings, tag, token, value;

// Use the [OptionParser module](optparse.html) to extract all options from
// `process.argv` that are specified in `SWITCHES`.
parseOptions = function() {

@@ -563,2 +620,3 @@ var o;

// The compile-time options to pass to the CoffeeScript compiler.
compileOptions = function(filename, base) {

@@ -596,4 +654,6 @@ var answer, cwd, jsDir, jsPath;

// Start up a new Node.js instance with the arguments in `--nodejs` passed to
// the `node` binary, preserving the other options.
forkNode = function() {
var args, nodeArgs, p;
var args, i, len, nodeArgs, p, ref, signal;
nodeArgs = opts.nodejs.split(/\s+/);

@@ -607,2 +667,11 @@ args = process.argv.slice(1);

});
ref = ['SIGINT', 'SIGTERM'];
for (i = 0, len = ref.length; i < len; i++) {
signal = ref[i];
process.on(signal, (function(signal) {
return function() {
return p.kill(signal);
};
})(signal));
}
return p.on('exit', function(code) {

@@ -613,2 +682,4 @@ return process.exit(code);

// Print the `--help` usage message and exit. Deprecated switches are not
// shown.
usage = function() {

@@ -618,2 +689,3 @@ return printLine(optionParser.help());

// Print the `--version` message and exit.
version = function() {

@@ -620,0 +692,0 @@ return printLine(`CoffeeScript version ${CoffeeScript.VERSION}`);

1570

lib/coffeescript/grammar.js

@@ -1,3 +0,20 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
// The CoffeeScript parser is generated by [Jison](https://github.com/zaach/jison)
// from this grammar file. Jison is a bottom-up parser generator, similar in
// style to [Bison](http://www.gnu.org/software/bison), implemented in JavaScript.
// It can recognize [LALR(1), LR(0), SLR(1), and LR(1)](https://en.wikipedia.org/wiki/LR_grammar)
// type grammars. To create the Jison parser, we list the pattern to match
// on the left-hand side, and the action to take (usually the creation of syntax
// tree nodes) on the right. As the parser runs, it
// shifts tokens from our token stream, from left to right, and
// [attempts to match](https://en.wikipedia.org/wiki/Bottom-up_parsing)
// the token sequence against the rules below. When a match can be made, it
// reduces into the [nonterminal](https://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols)
// (the enclosing name at the top), and we proceed from there.
// If you run the `cake build:parser` command, Jison constructs a parse table
// from our rules and saves it into `lib/parser.js`.
// The only dependency is on the **Jison.Parser**.
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;

@@ -7,60 +24,122 @@

// Jison DSL
// ---------
// Since we're going to be wrapped in a function by Jison in any case, if our
// action immediately returns a value, we can optimize by removing the function
// wrapper and just returning the value directly.
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
// Our handy DSL for Jison grammar generation, thanks to
// [Tim Caswell](https://github.com/creationix). For every rule in the grammar,
// we pass the pattern-defining string, the action to run, and extra options,
// optionally. If no action is specified, we simply pass the value of the
// previous nonterminal.
o = function(patternString, action, options) {
var addLocationDataFn, match, patternCount;
var getAddDataToNodeFunctionString, match, patternCount, performActionFunctionString;
patternString = patternString.replace(/\s{2,}/g, ' ');
patternCount = patternString.split(' ').length;
if (!action) {
return [patternString, '$$ = $1;', options];
if (action) {
action = (match = unwrap.exec(action)) ? match[1] : `(${action}())`;
// All runtime functions we need are defined on `yy`
action = action.replace(/\bnew /g, '$&yy.');
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
// Returns strings of functions to add to `parser.js` which add extra data
// that nodes may have, such as comments or location data. Location data
// is added to the first parameter passed in, and the parameter is returned.
// If the parameter is not a node, it will just be passed through unaffected.
getAddDataToNodeFunctionString = function(first, last) {
return `yy.addDataToNode(yy, @${first}${(last ? `, @${last}` : '')})`;
};
action = action.replace(/LOC\(([0-9]*)\)/g, getAddDataToNodeFunctionString('$1'));
action = action.replace(/LOC\(([0-9]*),\s*([0-9]*)\)/g, getAddDataToNodeFunctionString('$1', '$2'));
performActionFunctionString = `$$ = ${getAddDataToNodeFunctionString(1, patternCount)}(${action});`;
} else {
performActionFunctionString = '$$ = $1;';
}
action = (match = unwrap.exec(action)) ? match[1] : `(${action}())`;
action = action.replace(/\bnew /g, '$&yy.');
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
addLocationDataFn = function(first, last) {
if (!last) {
return `yy.addLocationDataFn(@${first})`;
} else {
return `yy.addLocationDataFn(@${first}, @${last})`;
}
};
action = action.replace(/LOC\(([0-9]*)\)/g, addLocationDataFn('$1'));
action = action.replace(/LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2'));
return [patternString, `$$ = ${addLocationDataFn(1, patternCount)}(${action});`, options];
return [patternString, performActionFunctionString, options];
};
// Grammatical Rules
// -----------------
// In all of the rules that follow, you'll see the name of the nonterminal as
// the key to a list of alternative matches. With each match's action, the
// dollar-sign variables are provided by Jison as references to the value of
// their numeric position, so in this rule:
// 'Expression UNLESS Expression'
// `$1` would be the value of the first `Expression`, `$2` would be the token
// for the `UNLESS` terminal, and `$3` would be the value of the second
// `Expression`.
grammar = {
// The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
// all parsing must end here.
Root: [
o('', function() {
o('',
function() {
return new Block;
}), o('Body')
}),
o('Body')
],
// Any list of statements and expressions, separated by line breaks or semicolons.
Body: [
o('Line', function() {
o('Line',
function() {
return Block.wrap([$1]);
}), o('Body TERMINATOR Line', function() {
}),
o('Body TERMINATOR Line',
function() {
return $1.push($3);
}), o('Body TERMINATOR')
}),
o('Body TERMINATOR')
],
// Block and statements, which make up a line in a body. YieldReturn is a
// statement, but not included in Statement because that results in an ambiguous
// grammar.
Line: [o('Expression'), o('Statement'), o('FuncDirective')],
FuncDirective: [o('YieldReturn'), o('AwaitReturn')],
// Pure statements which cannot be expressions.
Statement: [
o('Return'), o('Comment'), o('STATEMENT', function() {
o('Return'),
o('STATEMENT',
function() {
return new StatementLiteral($1);
}), o('Import'), o('Export')
}),
o('Import'),
o('Export')
],
Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw'), o('Yield')],
// All the different types of expressions in our language. The basic unit of
// CoffeeScript is the **Expression** -- everything that can be an expression
// is one. Blocks serve as the building blocks of many other rules, making
// them somewhat circular.
Expression: [o('Value'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw'), o('Yield')],
Yield: [
o('YIELD', function() {
return new Op($1, new Value(new Literal('')));
}), o('YIELD Expression', function() {
return new Op($1, $2);
}), o('YIELD FROM Expression', function() {
return new Op($1.concat($2), $3);
o('YIELD',
function() {
return new Op($1,
new Value(new Literal('')));
}),
o('YIELD Expression',
function() {
return new Op($1,
$2);
}),
o('YIELD FROM Expression',
function() {
return new Op($1.concat($2),
$3);
})
],
// 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.
Block: [
o('INDENT OUTDENT', function() {
o('INDENT OUTDENT',
function() {
return new Block;
}), o('INDENT Body OUTDENT', function() {
}),
o('INDENT Body OUTDENT',
function() {
return $2;

@@ -70,5 +149,8 @@ })

Identifier: [
o('IDENTIFIER', function() {
o('IDENTIFIER',
function() {
return new IdentifierLiteral($1);
}), o('CSX_TAG', function() {
}),
o('CSX_TAG',
function() {
return new CSXTag($1);

@@ -78,15 +160,23 @@ })

Property: [
o('PROPERTY', function() {
o('PROPERTY',
function() {
return new PropertyName($1);
})
],
// Alphanumerics are separated from the other **Literal** matchers because
// they can also serve as keys in object literals.
AlphaNumeric: [
o('NUMBER', function() {
o('NUMBER',
function() {
return new NumberLiteral($1);
}), o('String')
}),
o('String')
],
String: [
o('STRING', function() {
o('STRING',
function() {
return new StringLiteral($1);
}), o('STRING_START Body STRING_END', function() {
}),
o('STRING_START Body STRING_END',
function() {
return new StringWithInterpolations($2);

@@ -96,82 +186,181 @@ })

Regex: [
o('REGEX', function() {
o('REGEX',
function() {
return new RegexLiteral($1);
}), o('REGEX_START Invocation REGEX_END', function() {
}),
o('REGEX_START Invocation REGEX_END',
function() {
return new RegexWithInterpolations($2.args);
})
],
// All of our immediate values. Generally these can be passed straight
// through and printed to JavaScript.
Literal: [
o('AlphaNumeric'), o('JS', function() {
o('AlphaNumeric'),
o('JS',
function() {
return new PassthroughLiteral($1);
}), o('Regex'), o('UNDEFINED', function() {
return new UndefinedLiteral;
}), o('NULL', function() {
return new NullLiteral;
}), o('BOOL', function() {
}),
o('Regex'),
o('UNDEFINED',
function() {
return new UndefinedLiteral($1);
}),
o('NULL',
function() {
return new NullLiteral($1);
}),
o('BOOL',
function() {
return new BooleanLiteral($1);
}), o('INFINITY', function() {
}),
o('INFINITY',
function() {
return new InfinityLiteral($1);
}), o('NAN', function() {
return new NaNLiteral;
}),
o('NAN',
function() {
return new NaNLiteral($1);
})
],
// Assignment of a variable, property, or index to a value.
Assign: [
o('Assignable = Expression', function() {
return new Assign($1, $3);
}), o('Assignable = TERMINATOR Expression', function() {
return new Assign($1, $4);
}), o('Assignable = INDENT Expression OUTDENT', function() {
return new Assign($1, $4);
o('Assignable = Expression',
function() {
return new Assign($1,
$3);
}),
o('Assignable = TERMINATOR Expression',
function() {
return new Assign($1,
$4);
}),
o('Assignable = INDENT Expression OUTDENT',
function() {
return new Assign($1,
$4);
})
],
// Assignment when it happens within an object literal. The difference from
// the ordinary **Assign** is that these allow numbers and strings as keys.
AssignObj: [
o('ObjAssignable', function() {
o('ObjAssignable',
function() {
return new Value($1);
}), o('ObjRestValue'), o('ObjAssignable : Expression', function() {
return new Assign(LOC(1)(new Value($1)), $3, 'object', {
}),
o('ObjRestValue'),
o('ObjAssignable : Expression',
function() {
return new Assign(LOC(1)(new Value($1)),
$3,
'object',
{
operatorToken: LOC(2)(new Literal($2))
});
}), o('ObjAssignable : INDENT Expression OUTDENT', function() {
return new Assign(LOC(1)(new Value($1)), $4, 'object', {
}),
o('ObjAssignable : INDENT Expression OUTDENT',
function() {
return new Assign(LOC(1)(new Value($1)),
$4,
'object',
{
operatorToken: LOC(2)(new Literal($2))
});
}), o('SimpleObjAssignable = Expression', function() {
return new Assign(LOC(1)(new Value($1)), $3, null, {
}),
o('SimpleObjAssignable = Expression',
function() {
return new Assign(LOC(1)(new Value($1)),
$3,
null,
{
operatorToken: LOC(2)(new Literal($2))
});
}), o('SimpleObjAssignable = INDENT Expression OUTDENT', function() {
return new Assign(LOC(1)(new Value($1)), $4, null, {
}),
o('SimpleObjAssignable = INDENT Expression OUTDENT',
function() {
return new Assign(LOC(1)(new Value($1)),
$4,
null,
{
operatorToken: LOC(2)(new Literal($2))
});
}), o('Comment')
})
],
SimpleObjAssignable: [o('Identifier'), o('Property'), o('ThisProperty')],
ObjAssignable: [o('SimpleObjAssignable'), o('AlphaNumeric')],
// Object literal spread properties.
ObjRestValue: [
o('SimpleObjAssignable ...', function() {
o('SimpleObjAssignable ...',
function() {
return new Splat(new Value($1));
}), o('ObjSpreadExpr ...', function() {
}),
o('... SimpleObjAssignable',
function() {
return new Splat(new Value($2));
}),
o('ObjSpreadExpr ...',
function() {
return new Splat($1);
}),
o('... ObjSpreadExpr',
function() {
return new Splat($2);
})
],
ObjSpreadExpr: [
o('ObjSpreadIdentifier'), o('Object'), o('Parenthetical'), o('Super'), o('This'), o('SUPER Arguments', function() {
return new SuperCall(LOC(1)(new Super), $2);
}), o('SimpleObjAssignable Arguments', function() {
return new Call(new Value($1), $2);
}), o('ObjSpreadExpr Arguments', function() {
return new Call($1, $2);
o('ObjSpreadIdentifier'),
o('Object'),
o('Parenthetical'),
o('Super'),
o('This'),
o('SUPER Arguments',
function() {
return new SuperCall(LOC(1)(new Super),
$2,
false,
$1);
}),
o('SimpleObjAssignable Arguments',
function() {
return new Call(new Value($1),
$2);
}),
o('ObjSpreadExpr Arguments',
function() {
return new Call($1,
$2);
})
],
ObjSpreadIdentifier: [
o('SimpleObjAssignable . Property', function() {
return (new Value($1)).add(new Access($3));
}), o('SimpleObjAssignable INDEX_START IndexValue INDEX_END', function() {
return (new Value($1)).add($3);
o('SimpleObjAssignable ObjSpreadAccessor',
function() {
return (new Value($1)).add($2);
}),
o('ObjSpreadExpr ObjSpreadAccessor',
function() {
return (new Value($1)).add($2);
})
],
ObjSpreadAccessor: [
o('. Property',
function() {
return new Access($2);
}),
o('INDEX_START IndexValue INDEX_END',
function() {
return $2;
})
],
// A return statement from a function body.
Return: [
o('RETURN Expression', function() {
o('RETURN Expression',
function() {
return new Return($2);
}), o('RETURN', function() {
}),
o('RETURN INDENT Object OUTDENT',
function() {
return new Return(new Value($3));
}),
o('RETURN',
function() {
return new Return;

@@ -181,5 +370,8 @@ })

YieldReturn: [
o('YIELD RETURN Expression', function() {
o('YIELD RETURN Expression',
function() {
return new YieldReturn($3);
}), o('YIELD RETURN', function() {
}),
o('YIELD RETURN',
function() {
return new YieldReturn;

@@ -189,108 +381,212 @@ })

AwaitReturn: [
o('AWAIT RETURN Expression', function() {
o('AWAIT RETURN Expression',
function() {
return new AwaitReturn($3);
}), o('AWAIT RETURN', function() {
}),
o('AWAIT RETURN',
function() {
return new AwaitReturn;
})
],
Comment: [
o('HERECOMMENT', function() {
return new Comment($1);
})
],
// The **Code** node is the function literal. It's defined by an indented block
// of **Block** preceded by a function arrow, with an optional parameter list.
Code: [
o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() {
return new Code($2, $5, $4);
}), o('FuncGlyph Block', function() {
return new Code([], $2, $1);
o('PARAM_START ParamList PARAM_END FuncGlyph Block',
function() {
return new Code($2,
$5,
$4);
}),
o('FuncGlyph Block',
function() {
return new Code([],
$2,
$1);
})
],
// CoffeeScript has two different symbols for functions. `->` is for ordinary
// functions, and `=>` is for functions bound to the current value of *this*.
FuncGlyph: [
o('->', function() {
return 'func';
}), o('=>', function() {
return 'boundfunc';
o('->',
function() {
return new FuncGlyph($1);
}),
o('=>',
function() {
return new FuncGlyph($1);
})
],
// An optional, trailing comma.
OptComma: [o(''), o(',')],
// The list of parameters that a function accepts can be of any length.
ParamList: [
o('', function() {
o('',
function() {
return [];
}), o('Param', function() {
}),
o('Param',
function() {
return [$1];
}), o('ParamList , Param', function() {
}),
o('ParamList , Param',
function() {
return $1.concat($3);
}), o('ParamList OptComma TERMINATOR Param', function() {
}),
o('ParamList OptComma TERMINATOR Param',
function() {
return $1.concat($4);
}), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() {
}),
o('ParamList OptComma INDENT ParamList OptComma OUTDENT',
function() {
return $1.concat($4);
})
],
// A single parameter in a function definition can be ordinary, or a splat
// that hoovers up the remaining arguments.
Param: [
o('ParamVar', function() {
o('ParamVar',
function() {
return new Param($1);
}), o('ParamVar ...', function() {
return new Param($1, null, true);
}), o('ParamVar = Expression', function() {
return new Param($1, $3);
}), o('...', function() {
}),
o('ParamVar ...',
function() {
return new Param($1,
null,
true);
}),
o('... ParamVar',
function() {
return new Param($2,
null,
true);
}),
o('ParamVar = Expression',
function() {
return new Param($1,
$3);
}),
o('...',
function() {
return new Expansion;
})
],
// Function Parameters
ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')],
// A splat that occurs outside of a parameter list.
Splat: [
o('Expression ...', function() {
o('Expression ...',
function() {
return new Splat($1);
}),
o('... Expression',
function() {
return new Splat($2);
})
],
// Variables and properties that can be assigned to.
SimpleAssignable: [
o('Identifier', function() {
o('Identifier',
function() {
return new Value($1);
}), o('Value Accessor', function() {
}),
o('Value Accessor',
function() {
return $1.add($2);
}), o('Invocation Accessor', function() {
return new Value($1, [].concat($2));
}), o('ThisProperty')
}),
o('ThisProperty')
],
// Everything that can be assigned to.
Assignable: [
o('SimpleAssignable'), o('Array', function() {
o('SimpleAssignable'),
o('Array',
function() {
return new Value($1);
}), o('Object', function() {
}),
o('Object',
function() {
return new Value($1);
})
],
// The types of things that can be treated as values -- assigned to, invoked
// as functions, indexed into, named as a class, etc.
Value: [
o('Assignable'), o('Literal', function() {
o('Assignable'),
o('Literal',
function() {
return new Value($1);
}), o('Parenthetical', function() {
}),
o('Parenthetical',
function() {
return new Value($1);
}), o('Range', function() {
}),
o('Range',
function() {
return new Value($1);
}), o('This'), o('Super')
}),
o('Invocation',
function() {
return new Value($1);
}),
o('This'),
o('Super',
function() {
return new Value($1);
})
],
// A `super`-based expression that can be used as a value.
Super: [
o('SUPER . Property', function() {
return new Super(LOC(3)(new Access($3)));
}), o('SUPER INDEX_START Expression INDEX_END', function() {
return new Super(LOC(3)(new Index($3)));
o('SUPER . Property',
function() {
return new Super(LOC(3)(new Access($3)),
[],
false,
$1);
}),
o('SUPER INDEX_START Expression INDEX_END',
function() {
return new Super(LOC(3)(new Index($3)),
[],
false,
$1);
})
],
// The general group of accessors into an object, by property, by prototype
// or by array index or slice.
Accessor: [
o('. Property', function() {
o('. Property',
function() {
return new Access($2);
}), o('?. Property', function() {
return new Access($2, 'soak');
}), o(':: Property', function() {
return [LOC(1)(new Access(new PropertyName('prototype'))), LOC(2)(new Access($2))];
}), o('?:: Property', function() {
return [LOC(1)(new Access(new PropertyName('prototype'), 'soak')), LOC(2)(new Access($2))];
}), o('::', function() {
}),
o('?. Property',
function() {
return new Access($2,
'soak');
}),
o(':: Property',
function() {
return [LOC(1)(new Access(new PropertyName('prototype'))),
LOC(2)(new Access($2))];
}),
o('?:: Property',
function() {
return [LOC(1)(new Access(new PropertyName('prototype'),
'soak')),
LOC(2)(new Access($2))];
}),
o('::',
function() {
return new Access(new PropertyName('prototype'));
}), o('Index')
}),
o('Index')
],
// Indexing into an object or array using bracket notation.
Index: [
o('INDEX_START IndexValue INDEX_END', function() {
o('INDEX_START IndexValue INDEX_END',
function() {
return $2;
}), o('INDEX_SOAK Index', function() {
return extend($2, {
}),
o('INDEX_SOAK Index',
function() {
return extend($2,
{
soak: true

@@ -301,72 +597,151 @@ });

IndexValue: [
o('Expression', function() {
o('Expression',
function() {
return new Index($1);
}), o('Slice', function() {
}),
o('Slice',
function() {
return new Slice($1);
})
],
// In CoffeeScript, an object literal is simply a list of assignments.
Object: [
o('{ AssignList OptComma }', function() {
return new Obj($2, $1.generated);
o('{ AssignList OptComma }',
function() {
return new Obj($2,
$1.generated);
})
],
// Assignment of properties within an object literal can be separated by
// comma, as in JavaScript, or simply by newline.
AssignList: [
o('', function() {
o('',
function() {
return [];
}), o('AssignObj', function() {
}),
o('AssignObj',
function() {
return [$1];
}), o('AssignList , AssignObj', function() {
}),
o('AssignList , AssignObj',
function() {
return $1.concat($3);
}), o('AssignList OptComma TERMINATOR AssignObj', function() {
}),
o('AssignList OptComma TERMINATOR AssignObj',
function() {
return $1.concat($4);
}), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() {
}),
o('AssignList OptComma INDENT AssignList OptComma OUTDENT',
function() {
return $1.concat($4);
})
],
// Class definitions have optional bodies of prototype property assignments,
// and optional references to the superclass.
Class: [
o('CLASS', function() {
o('CLASS',
function() {
return new Class;
}), o('CLASS Block', function() {
return new Class(null, null, $2);
}), o('CLASS EXTENDS Expression', function() {
return new Class(null, $3);
}), o('CLASS EXTENDS Expression Block', function() {
return new Class(null, $3, $4);
}), o('CLASS SimpleAssignable', function() {
}),
o('CLASS Block',
function() {
return new Class(null,
null,
$2);
}),
o('CLASS EXTENDS Expression',
function() {
return new Class(null,
$3);
}),
o('CLASS EXTENDS Expression Block',
function() {
return new Class(null,
$3,
$4);
}),
o('CLASS SimpleAssignable',
function() {
return new Class($2);
}), o('CLASS SimpleAssignable Block', function() {
return new Class($2, null, $3);
}), o('CLASS SimpleAssignable EXTENDS Expression', function() {
return new Class($2, $4);
}), o('CLASS SimpleAssignable EXTENDS Expression Block', function() {
return new Class($2, $4, $5);
}),
o('CLASS SimpleAssignable Block',
function() {
return new Class($2,
null,
$3);
}),
o('CLASS SimpleAssignable EXTENDS Expression',
function() {
return new Class($2,
$4);
}),
o('CLASS SimpleAssignable EXTENDS Expression Block',
function() {
return new Class($2,
$4,
$5);
})
],
Import: [
o('IMPORT String', function() {
return new ImportDeclaration(null, $2);
}), o('IMPORT ImportDefaultSpecifier FROM String', function() {
return new ImportDeclaration(new ImportClause($2, null), $4);
}), o('IMPORT ImportNamespaceSpecifier FROM String', function() {
return new ImportDeclaration(new ImportClause(null, $2), $4);
}), o('IMPORT { } FROM String', function() {
return new ImportDeclaration(new ImportClause(null, new ImportSpecifierList([])), $5);
}), o('IMPORT { ImportSpecifierList OptComma } FROM String', function() {
return new ImportDeclaration(new ImportClause(null, new ImportSpecifierList($3)), $7);
}), o('IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String', function() {
return new ImportDeclaration(new ImportClause($2, $4), $6);
}), o('IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String', function() {
return new ImportDeclaration(new ImportClause($2, new ImportSpecifierList($5)), $9);
o('IMPORT String',
function() {
return new ImportDeclaration(null,
$2);
}),
o('IMPORT ImportDefaultSpecifier FROM String',
function() {
return new ImportDeclaration(new ImportClause($2,
null),
$4);
}),
o('IMPORT ImportNamespaceSpecifier FROM String',
function() {
return new ImportDeclaration(new ImportClause(null,
$2),
$4);
}),
o('IMPORT { } FROM String',
function() {
return new ImportDeclaration(new ImportClause(null,
new ImportSpecifierList([])),
$5);
}),
o('IMPORT { ImportSpecifierList OptComma } FROM String',
function() {
return new ImportDeclaration(new ImportClause(null,
new ImportSpecifierList($3)),
$7);
}),
o('IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String',
function() {
return new ImportDeclaration(new ImportClause($2,
$4),
$6);
}),
o('IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String',
function() {
return new ImportDeclaration(new ImportClause($2,
new ImportSpecifierList($5)),
$9);
})
],
ImportSpecifierList: [
o('ImportSpecifier', function() {
o('ImportSpecifier',
function() {
return [$1];
}), o('ImportSpecifierList , ImportSpecifier', function() {
}),
o('ImportSpecifierList , ImportSpecifier',
function() {
return $1.concat($3);
}), o('ImportSpecifierList OptComma TERMINATOR ImportSpecifier', function() {
}),
o('ImportSpecifierList OptComma TERMINATOR ImportSpecifier',
function() {
return $1.concat($4);
}), o('INDENT ImportSpecifierList OptComma OUTDENT', function() {
}),
o('INDENT ImportSpecifierList OptComma OUTDENT',
function() {
return $2;
}), o('ImportSpecifierList OptComma INDENT ImportSpecifierList OptComma OUTDENT', function() {
}),
o('ImportSpecifierList OptComma INDENT ImportSpecifierList OptComma OUTDENT',
function() {
return $1.concat($4);

@@ -376,14 +751,24 @@ })

ImportSpecifier: [
o('Identifier', function() {
o('Identifier',
function() {
return new ImportSpecifier($1);
}), o('Identifier AS Identifier', function() {
return new ImportSpecifier($1, $3);
}), o('DEFAULT', function() {
}),
o('Identifier AS Identifier',
function() {
return new ImportSpecifier($1,
$3);
}),
o('DEFAULT',
function() {
return new ImportSpecifier(new Literal($1));
}), o('DEFAULT AS Identifier', function() {
return new ImportSpecifier(new Literal($1), $3);
}),
o('DEFAULT AS Identifier',
function() {
return new ImportSpecifier(new Literal($1),
$3);
})
],
ImportDefaultSpecifier: [
o('Identifier', function() {
o('Identifier',
function() {
return new ImportDefaultSpecifier($1);

@@ -393,43 +778,82 @@ })

ImportNamespaceSpecifier: [
o('IMPORT_ALL AS Identifier', function() {
return new ImportNamespaceSpecifier(new Literal($1), $3);
o('IMPORT_ALL AS Identifier',
function() {
return new ImportNamespaceSpecifier(new Literal($1),
$3);
})
],
Export: [
o('EXPORT { }', function() {
o('EXPORT { }',
function() {
return new ExportNamedDeclaration(new ExportSpecifierList([]));
}), o('EXPORT { ExportSpecifierList OptComma }', function() {
}),
o('EXPORT { ExportSpecifierList OptComma }',
function() {
return new ExportNamedDeclaration(new ExportSpecifierList($3));
}), o('EXPORT Class', function() {
}),
o('EXPORT Class',
function() {
return new ExportNamedDeclaration($2);
}), o('EXPORT Identifier = Expression', function() {
return new ExportNamedDeclaration(new Assign($2, $4, null, {
}),
o('EXPORT Identifier = Expression',
function() {
return new ExportNamedDeclaration(new Assign($2,
$4,
null,
{
moduleDeclaration: 'export'
}));
}), o('EXPORT Identifier = TERMINATOR Expression', function() {
return new ExportNamedDeclaration(new Assign($2, $5, null, {
}),
o('EXPORT Identifier = TERMINATOR Expression',
function() {
return new ExportNamedDeclaration(new Assign($2,
$5,
null,
{
moduleDeclaration: 'export'
}));
}), o('EXPORT Identifier = INDENT Expression OUTDENT', function() {
return new ExportNamedDeclaration(new Assign($2, $5, null, {
}),
o('EXPORT Identifier = INDENT Expression OUTDENT',
function() {
return new ExportNamedDeclaration(new Assign($2,
$5,
null,
{
moduleDeclaration: 'export'
}));
}), o('EXPORT DEFAULT Expression', function() {
}),
o('EXPORT DEFAULT Expression',
function() {
return new ExportDefaultDeclaration($3);
}), o('EXPORT EXPORT_ALL FROM String', function() {
return new ExportAllDeclaration(new Literal($2), $4);
}), o('EXPORT { ExportSpecifierList OptComma } FROM String', function() {
return new ExportNamedDeclaration(new ExportSpecifierList($3), $7);
}),
o('EXPORT EXPORT_ALL FROM String',
function() {
return new ExportAllDeclaration(new Literal($2),
$4);
}),
o('EXPORT { ExportSpecifierList OptComma } FROM String',
function() {
return new ExportNamedDeclaration(new ExportSpecifierList($3),
$7);
})
],
ExportSpecifierList: [
o('ExportSpecifier', function() {
o('ExportSpecifier',
function() {
return [$1];
}), o('ExportSpecifierList , ExportSpecifier', function() {
}),
o('ExportSpecifierList , ExportSpecifier',
function() {
return $1.concat($3);
}), o('ExportSpecifierList OptComma TERMINATOR ExportSpecifier', function() {
}),
o('ExportSpecifierList OptComma TERMINATOR ExportSpecifier',
function() {
return $1.concat($4);
}), o('INDENT ExportSpecifierList OptComma OUTDENT', function() {
}),
o('INDENT ExportSpecifierList OptComma OUTDENT',
function() {
return $2;
}), o('ExportSpecifierList OptComma INDENT ExportSpecifierList OptComma OUTDENT', function() {
}),
o('ExportSpecifierList OptComma INDENT ExportSpecifierList OptComma OUTDENT',
function() {
return $1.concat($4);

@@ -439,149 +863,287 @@ })

ExportSpecifier: [
o('Identifier', function() {
o('Identifier',
function() {
return new ExportSpecifier($1);
}), o('Identifier AS Identifier', function() {
return new ExportSpecifier($1, $3);
}), o('Identifier AS DEFAULT', function() {
return new ExportSpecifier($1, new Literal($3));
}), o('DEFAULT', function() {
}),
o('Identifier AS Identifier',
function() {
return new ExportSpecifier($1,
$3);
}),
o('Identifier AS DEFAULT',
function() {
return new ExportSpecifier($1,
new Literal($3));
}),
o('DEFAULT',
function() {
return new ExportSpecifier(new Literal($1));
}), o('DEFAULT AS Identifier', function() {
return new ExportSpecifier(new Literal($1), $3);
}),
o('DEFAULT AS Identifier',
function() {
return new ExportSpecifier(new Literal($1),
$3);
})
],
// Ordinary function invocation, or a chained series of calls.
Invocation: [
o('Value OptFuncExist String', function() {
return new TaggedTemplateCall($1, $3, $2);
}), o('Value OptFuncExist Arguments', function() {
return new Call($1, $3, $2);
}), o('Invocation OptFuncExist Arguments', function() {
return new Call($1, $3, $2);
}), o('SUPER OptFuncExist Arguments', function() {
return new SuperCall(LOC(1)(new Super), $3, $2);
o('Value OptFuncExist String',
function() {
return new TaggedTemplateCall($1,
$3,
$2);
}),
o('Value OptFuncExist Arguments',
function() {
return new Call($1,
$3,
$2);
}),
o('SUPER OptFuncExist Arguments',
function() {
return new SuperCall(LOC(1)(new Super),
$3,
$2,
$1);
})
],
// An optional existence check on a function.
OptFuncExist: [
o('', function() {
o('',
function() {
return false;
}), o('FUNC_EXIST', function() {
}),
o('FUNC_EXIST',
function() {
return true;
})
],
// The list of arguments to a function call.
Arguments: [
o('CALL_START CALL_END', function() {
o('CALL_START CALL_END',
function() {
return [];
}), o('CALL_START ArgList OptComma CALL_END', function() {
}),
o('CALL_START ArgList OptComma CALL_END',
function() {
return $2;
})
],
// A reference to the *this* current object.
This: [
o('THIS', function() {
return new Value(new ThisLiteral);
}), o('@', function() {
return new Value(new ThisLiteral);
o('THIS',
function() {
return new Value(new ThisLiteral($1));
}),
o('@',
function() {
return new Value(new ThisLiteral($1));
})
],
// A reference to a property on *this*.
ThisProperty: [
o('@ Property', function() {
return new Value(LOC(1)(new ThisLiteral), [LOC(2)(new Access($2))], 'this');
o('@ Property',
function() {
return new Value(LOC(1)(new ThisLiteral($1)),
[LOC(2)(new Access($2))],
'this');
})
],
// The array literal.
Array: [
o('[ ]', function() {
o('[ ]',
function() {
return new Arr([]);
}), o('[ ArgList OptComma ]', function() {
}),
o('[ ArgList OptComma ]',
function() {
return new Arr($2);
})
],
// Inclusive and exclusive range dots.
RangeDots: [
o('..', function() {
o('..',
function() {
return 'inclusive';
}), o('...', function() {
}),
o('...',
function() {
return 'exclusive';
})
],
// The CoffeeScript range literal.
Range: [
o('[ Expression RangeDots Expression ]', function() {
return new Range($2, $4, $3);
o('[ Expression RangeDots Expression ]',
function() {
return new Range($2,
$4,
$3);
})
],
// Array slice literals.
Slice: [
o('Expression RangeDots Expression', function() {
return new Range($1, $3, $2);
}), o('Expression RangeDots', function() {
return new Range($1, null, $2);
}), o('RangeDots Expression', function() {
return new Range(null, $2, $1);
}), o('RangeDots', function() {
return new Range(null, null, $1);
o('Expression RangeDots Expression',
function() {
return new Range($1,
$3,
$2);
}),
o('Expression RangeDots',
function() {
return new Range($1,
null,
$2);
}),
o('RangeDots Expression',
function() {
return new Range(null,
$2,
$1);
}),
o('RangeDots',
function() {
return new Range(null,
null,
$1);
})
],
// The **ArgList** is both the list of objects passed into a function call,
// as well as the contents of an array literal
// (i.e. comma-separated expressions). Newlines work as well.
ArgList: [
o('Arg', function() {
o('Arg',
function() {
return [$1];
}), o('ArgList , Arg', function() {
}),
o('ArgList , Arg',
function() {
return $1.concat($3);
}), o('ArgList OptComma TERMINATOR Arg', function() {
}),
o('ArgList OptComma TERMINATOR Arg',
function() {
return $1.concat($4);
}), o('INDENT ArgList OptComma OUTDENT', function() {
}),
o('INDENT ArgList OptComma OUTDENT',
function() {
return $2;
}), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() {
}),
o('ArgList OptComma INDENT ArgList OptComma OUTDENT',
function() {
return $1.concat($4);
})
],
// Valid arguments are Blocks or Splats.
Arg: [
o('Expression'), o('Splat'), o('...', function() {
o('Expression'),
o('Splat'),
o('...',
function() {
return new Expansion;
})
],
// Just simple, comma-separated, required arguments (no fancy syntax). We need
// this to be separate from the **ArgList** for use in **Switch** blocks, where
// having the newlines wouldn't make sense.
SimpleArgs: [
o('Expression'), o('SimpleArgs , Expression', function() {
return [].concat($1, $3);
o('Expression'),
o('SimpleArgs , Expression',
function() {
return [].concat($1,
$3);
})
],
// The variants of *try/catch/finally* exception handling blocks.
Try: [
o('TRY Block', function() {
o('TRY Block',
function() {
return new Try($2);
}), o('TRY Block Catch', function() {
return new Try($2, $3[0], $3[1]);
}), o('TRY Block FINALLY Block', function() {
return new Try($2, null, null, $4);
}), o('TRY Block Catch FINALLY Block', function() {
return new Try($2, $3[0], $3[1], $5);
}),
o('TRY Block Catch',
function() {
return new Try($2,
$3[0],
$3[1]);
}),
o('TRY Block FINALLY Block',
function() {
return new Try($2,
null,
null,
$4);
}),
o('TRY Block Catch FINALLY Block',
function() {
return new Try($2,
$3[0],
$3[1],
$5);
})
],
// A catch clause names its error and runs a block of code.
Catch: [
o('CATCH Identifier Block', function() {
return [$2, $3];
}), o('CATCH Object Block', function() {
return [LOC(2)(new Value($2)), $3];
}), o('CATCH Block', function() {
return [null, $2];
o('CATCH Identifier Block',
function() {
return [$2,
$3];
}),
o('CATCH Object Block',
function() {
return [LOC(2)(new Value($2)),
$3];
}),
o('CATCH Block',
function() {
return [null,
$2];
})
],
// Throw an exception object.
Throw: [
o('THROW Expression', function() {
o('THROW Expression',
function() {
return new Throw($2);
}),
o('THROW INDENT Object OUTDENT',
function() {
return new Throw(new Value($3));
})
],
// Parenthetical expressions. Note that the **Parenthetical** is a **Value**,
// not an **Expression**, so if you need to use an expression in a place
// where only values are accepted, wrapping it in parentheses will always do
// the trick.
Parenthetical: [
o('( Body )', function() {
o('( Body )',
function() {
return new Parens($2);
}), o('( INDENT Body OUTDENT )', function() {
}),
o('( INDENT Body OUTDENT )',
function() {
return new Parens($3);
})
],
// The condition portion of a while loop.
WhileSource: [
o('WHILE Expression', function() {
o('WHILE Expression',
function() {
return new While($2);
}), o('WHILE Expression WHEN Expression', function() {
return new While($2, {
}),
o('WHILE Expression WHEN Expression',
function() {
return new While($2,
{
guard: $4
});
}), o('UNTIL Expression', function() {
return new While($2, {
}),
o('UNTIL Expression',
function() {
return new While($2,
{
invert: true
});
}), o('UNTIL Expression WHEN Expression', function() {
return new While($2, {
}),
o('UNTIL Expression WHEN Expression',
function() {
return new While($2,
{
invert: true,

@@ -592,10 +1154,19 @@ guard: $4

],
// The while loop can either be normal, with a block of expressions to execute,
// or postfix, with a single expression. There is no do..while.
While: [
o('WhileSource Block', function() {
o('WhileSource Block',
function() {
return $1.addBody($2);
}), o('Statement WhileSource', function() {
}),
o('Statement WhileSource',
function() {
return $2.addBody(LOC(1)(Block.wrap([$1])));
}), o('Expression WhileSource', function() {
}),
o('Expression WhileSource',
function() {
return $2.addBody(LOC(1)(Block.wrap([$1])));
}), o('Loop', function() {
}),
o('Loop',
function() {
return $1;

@@ -605,23 +1176,40 @@ })

Loop: [
o('LOOP Block', function() {
o('LOOP Block',
function() {
return new While(LOC(1)(new BooleanLiteral('true'))).addBody($2);
}), o('LOOP Expression', function() {
}),
o('LOOP Expression',
function() {
return new While(LOC(1)(new BooleanLiteral('true'))).addBody(LOC(2)(Block.wrap([$2])));
})
],
// Array, object, and range comprehensions, at the most generic level.
// Comprehensions can either be normal, with a block of expressions to execute,
// or postfix, with a single expression.
For: [
o('Statement ForBody', function() {
return new For($1, $2);
}), o('Expression ForBody', function() {
return new For($1, $2);
}), o('ForBody Block', function() {
return new For($2, $1);
o('Statement ForBody',
function() {
return new For($1,
$2);
}),
o('Expression ForBody',
function() {
return new For($1,
$2);
}),
o('ForBody Block',
function() {
return new For($2,
$1);
})
],
ForBody: [
o('FOR Range', function() {
o('FOR Range',
function() {
return {
source: LOC(2)(new Value($2))
};
}), o('FOR Range BY Expression', function() {
}),
o('FOR Range BY Expression',
function() {
return {

@@ -631,3 +1219,5 @@ source: LOC(2)(new Value($2)),

};
}), o('ForStart ForSource', function() {
}),
o('ForStart ForSource',
function() {
$2.own = $1.own;

@@ -641,5 +1231,8 @@ $2.ownTag = $1.ownTag;

ForStart: [
o('FOR ForVariables', function() {
o('FOR ForVariables',
function() {
return $2;
}), o('FOR OWN ForVariables', function() {
}),
o('FOR OWN ForVariables',
function() {
$3.own = true;

@@ -650,22 +1243,42 @@ $3.ownTag = LOC(2)(new Literal($2));

],
// An array of all accepted values for a variable inside the loop.
// This enables support for pattern matching.
ForValue: [
o('Identifier'), o('ThisProperty'), o('Array', function() {
o('Identifier'),
o('ThisProperty'),
o('Array',
function() {
return new Value($1);
}), o('Object', function() {
}),
o('Object',
function() {
return new Value($1);
})
],
// An array or range comprehension has variables for the current element
// and (optional) reference to the current index. Or, *key, value*, in the case
// of object comprehensions.
ForVariables: [
o('ForValue', function() {
o('ForValue',
function() {
return [$1];
}), o('ForValue , ForValue', function() {
return [$1, $3];
}),
o('ForValue , ForValue',
function() {
return [$1,
$3];
})
],
// The source of a comprehension is an array or object with an optional guard
// clause. If it's an array comprehension, you can also choose to step through
// in fixed-size increments.
ForSource: [
o('FORIN Expression', function() {
o('FORIN Expression',
function() {
return {
source: $2
};
}), o('FOROF Expression', function() {
}),
o('FOROF Expression',
function() {
return {

@@ -675,3 +1288,5 @@ source: $2,

};
}), o('FORIN Expression WHEN Expression', function() {
}),
o('FORIN Expression WHEN Expression',
function() {
return {

@@ -681,3 +1296,5 @@ source: $2,

};
}), o('FOROF Expression WHEN Expression', function() {
}),
o('FOROF Expression WHEN Expression',
function() {
return {

@@ -688,3 +1305,5 @@ source: $2,

};
}), o('FORIN Expression BY Expression', function() {
}),
o('FORIN Expression BY Expression',
function() {
return {

@@ -694,3 +1313,5 @@ source: $2,

};
}), o('FORIN Expression WHEN Expression BY Expression', function() {
}),
o('FORIN Expression WHEN Expression BY Expression',
function() {
return {

@@ -701,3 +1322,5 @@ source: $2,

};
}), o('FORIN Expression BY Expression WHEN Expression', function() {
}),
o('FORIN Expression BY Expression WHEN Expression',
function() {
return {

@@ -708,3 +1331,5 @@ source: $2,

};
}), o('FORFROM Expression', function() {
}),
o('FORFROM Expression',
function() {
return {

@@ -714,3 +1339,5 @@ source: $2,

};
}), o('FORFROM Expression WHEN Expression', function() {
}),
o('FORFROM Expression WHEN Expression',
function() {
return {

@@ -724,31 +1351,63 @@ source: $2,

Switch: [
o('SWITCH Expression INDENT Whens OUTDENT', function() {
return new Switch($2, $4);
}), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() {
return new Switch($2, $4, $6);
}), o('SWITCH INDENT Whens OUTDENT', function() {
return new Switch(null, $3);
}), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() {
return new Switch(null, $3, $5);
o('SWITCH Expression INDENT Whens OUTDENT',
function() {
return new Switch($2,
$4);
}),
o('SWITCH Expression INDENT Whens ELSE Block OUTDENT',
function() {
return new Switch($2,
$4,
$6);
}),
o('SWITCH INDENT Whens OUTDENT',
function() {
return new Switch(null,
$3);
}),
o('SWITCH INDENT Whens ELSE Block OUTDENT',
function() {
return new Switch(null,
$3,
$5);
})
],
Whens: [
o('When'), o('Whens When', function() {
o('When'),
o('Whens When',
function() {
return $1.concat($2);
})
],
// An individual **When** clause, with action.
When: [
o('LEADING_WHEN SimpleArgs Block', function() {
return [[$2, $3]];
}), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() {
return [[$2, $3]];
o('LEADING_WHEN SimpleArgs Block',
function() {
return [[$2,
$3]];
}),
o('LEADING_WHEN SimpleArgs Block TERMINATOR',
function() {
return [[$2,
$3]];
})
],
// The most basic form of *if* is a condition and an action. The following
// if-related rules are broken up along these lines in order to avoid
// ambiguity.
IfBlock: [
o('IF Expression Block', function() {
return new If($2, $3, {
o('IF Expression Block',
function() {
return new If($2,
$3,
{
type: $1
});
}), o('IfBlock ELSE IF Expression Block', function() {
return $1.addElse(LOC(3, 5)(new If($4, $5, {
}),
o('IfBlock ELSE IF Expression Block',
function() {
return $1.addElse(LOC(3,
5)(new If($4,
$5,
{
type: $3

@@ -758,12 +1417,24 @@ })));

],
// The full complement of *if* expressions, including postfix one-liner
// *if* and *unless*.
If: [
o('IfBlock'), o('IfBlock ELSE Block', function() {
o('IfBlock'),
o('IfBlock ELSE Block',
function() {
return $1.addElse($3);
}), o('Statement POST_IF Expression', function() {
return new If($3, LOC(1)(Block.wrap([$1])), {
}),
o('Statement POST_IF Expression',
function() {
return new If($3,
LOC(1)(Block.wrap([$1])),
{
type: $2,
statement: true
});
}), o('Expression POST_IF Expression', function() {
return new If($3, LOC(1)(Block.wrap([$1])), {
}),
o('Expression POST_IF Expression',
function() {
return new If($3,
LOC(1)(Block.wrap([$1])),
{
type: $2,

@@ -774,63 +1445,170 @@ statement: true

],
// Arithmetic and logical operators, working on one or more operands.
// Here they are grouped by order of precedence. The actual precedence rules
// are defined at the bottom of the page. It would be shorter if we could
// combine most of these rules into a single generic *Operand OpSymbol Operand*
// -type rule, but in order to make the precedence binding possible, separate
// rules are necessary.
Operation: [
o('UNARY Expression', function() {
return new Op($1, $2);
}), o('UNARY_MATH Expression', function() {
return new Op($1, $2);
}), o('- Expression', (function() {
return new Op('-', $2);
}), {
o('UNARY Expression',
function() {
return new Op($1,
$2);
}),
o('UNARY_MATH Expression',
function() {
return new Op($1,
$2);
}),
o('- Expression',
(function() {
return new Op('-',
$2);
}),
{
prec: 'UNARY_MATH'
}), o('+ Expression', (function() {
return new Op('+', $2);
}), {
}),
o('+ Expression',
(function() {
return new Op('+',
$2);
}),
{
prec: 'UNARY_MATH'
}), o('AWAIT Expression', function() {
return new Op($1, $2);
}), o('-- SimpleAssignable', function() {
return new Op('--', $2);
}), o('++ SimpleAssignable', function() {
return new Op('++', $2);
}), o('SimpleAssignable --', function() {
return new Op('--', $1, null, true);
}), o('SimpleAssignable ++', function() {
return new Op('++', $1, null, true);
}), o('Expression ?', function() {
}),
o('AWAIT Expression',
function() {
return new Op($1,
$2);
}),
o('-- SimpleAssignable',
function() {
return new Op('--',
$2);
}),
o('++ SimpleAssignable',
function() {
return new Op('++',
$2);
}),
o('SimpleAssignable --',
function() {
return new Op('--',
$1,
null,
true);
}),
o('SimpleAssignable ++',
function() {
return new Op('++',
$1,
null,
true);
}),
// [The existential operator](http://coffeescript.org/#existential-operator).
o('Expression ?',
function() {
return new Existence($1);
}), o('Expression + Expression', function() {
return new Op('+', $1, $3);
}), o('Expression - Expression', function() {
return new Op('-', $1, $3);
}), o('Expression MATH Expression', function() {
return new Op($2, $1, $3);
}), o('Expression ** Expression', function() {
return new Op($2, $1, $3);
}), o('Expression SHIFT Expression', function() {
return new Op($2, $1, $3);
}), o('Expression COMPARE Expression', function() {
return new Op($2, $1, $3);
}), o('Expression & Expression', function() {
return new Op($2, $1, $3);
}), o('Expression ^ Expression', function() {
return new Op($2, $1, $3);
}), o('Expression | Expression', function() {
return new Op($2, $1, $3);
}), o('Expression && Expression', function() {
return new Op($2, $1, $3);
}), o('Expression || Expression', function() {
return new Op($2, $1, $3);
}), o('Expression BIN? Expression', function() {
return new Op($2, $1, $3);
}), o('Expression RELATION Expression', function() {
}),
o('Expression + Expression',
function() {
return new Op('+',
$1,
$3);
}),
o('Expression - Expression',
function() {
return new Op('-',
$1,
$3);
}),
o('Expression MATH Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression ** Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression SHIFT Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression COMPARE Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression & Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression ^ Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression | Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression && Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression || Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression BIN? Expression',
function() {
return new Op($2,
$1,
$3);
}),
o('Expression RELATION Expression',
function() {
if ($2.charAt(0) === '!') {
return new Op($2.slice(1), $1, $3).invert();
return new Op($2.slice(1),
$1,
$3).invert();
} else {
return new Op($2, $1, $3);
return new Op($2,
$1,
$3);
}
}), o('SimpleAssignable COMPOUND_ASSIGN Expression', function() {
return new Assign($1, $3, $2);
}), o('SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT', function() {
return new Assign($1, $4, $2);
}), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression', function() {
return new Assign($1, $4, $2);
}),
o('SimpleAssignable COMPOUND_ASSIGN Expression',
function() {
return new Assign($1,
$3,
$2);
}),
o('SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT',
function() {
return new Assign($1,
$4,
$2);
}),
o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression',
function() {
return new Assign($1,
$4,
$2);
})

@@ -840,4 +1618,22 @@ ]

// Precedence
// ----------
// Operators at the top of this list have higher precedence than the ones lower
// down. Following these rules is what makes `2 + 3 * 4` parse as:
// 2 + (3 * 4)
// And not:
// (2 + 3) * 4
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', 'AWAIT'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', '&'], ['left', '^'], ['left', '|'], ['left', '&&'], ['left', '||'], ['left', 'BIN?'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT'], ['left', 'POST_IF']];
// Wrapping Up
// -----------
// Finally, now that we have our **grammar** and our **operators**, we can create
// our **Jison.Parser**. We do this by processing all of our rules, recording all
// terminals (every symbol which does not appear as the name of a rule above)
// as "tokens".
tokens = [];

@@ -868,2 +1664,6 @@

// Initialize the **Parser** with our list of terminal **tokens**, our **grammar**
// rules, and the name of the root. Reverse the operators because Jison orders
// precedence from low to high, and we have it high to low
// (as in [Yacc](http://dinosaur.compilertools.net/yacc/index.html)).
exports.parser = new Parser({

@@ -870,0 +1670,0 @@ tokens: tokens.join(' '),

@@ -1,5 +0,10 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
var buildLocationData, extend, flatten, ref, repeat, syntaxErrorToString;
// This file contains the common helper functions that we'd like to share among
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
// arrays, count characters, that sort of thing.
// Peek at the beginning of a given string to see if it matches a sequence.
var attachCommentsToNode, buildLocationData, buildLocationHash, extend, flatten, ref, repeat, syntaxErrorToString;
exports.starts = function(string, literal, start) {

@@ -9,2 +14,3 @@ return literal === string.substr(start, literal.length);

// Peek at the end of a given string to see if it matches a sequence.
exports.ends = function(string, literal, back) {

@@ -16,4 +22,6 @@ var len;

// Repeat a string `n` times.
exports.repeat = repeat = function(str, n) {
var res;
// Use clever algorithm to have O(log(n)) string concatenation operations.
res = '';

@@ -30,2 +38,3 @@ while (n > 0) {

// Trim out all falsy values from an array.
exports.compact = function(array) {

@@ -43,2 +52,3 @@ var i, item, len1, results;

// Count the number of occurrences of a string in a string.
exports.count = function(string, substr) {

@@ -56,2 +66,5 @@ var num, pos;

// Merge objects, returning a fresh copy with attributes from both sides.
// Used every time `Base#compile` is called, to allow properties in the
// options hash to propagate down the tree without polluting other branches.
exports.merge = function(options, overrides) {

@@ -61,2 +74,3 @@ return extend(extend({}, options), overrides);

// Extend a source object with the properties of another object (shallow copy).
extend = exports.extend = function(object, properties) {

@@ -71,2 +85,4 @@ var key, val;

// Return a flattened version of an array.
// Handy for getting a list of `children` from the nodes.
exports.flatten = flatten = function(array) {

@@ -86,2 +102,4 @@ var element, flattened, i, len1;

// Delete a key from an object, returning the value. Useful when a node is
// looking for a particular method in an options hash.
exports.del = function(obj, key) {

@@ -94,2 +112,3 @@ var val;

// Typical Array::some
exports.some = (ref = Array.prototype.some) != null ? ref : function(fn) {

@@ -107,2 +126,5 @@ var e, i, len1, ref1;

// Helper function for extracting code from Literate CoffeeScript by stripping
// out all non-code blocks, producing a string of CoffeeScript code that can
// be compiled “normally.”
exports.invertLiterate = function(code) {

@@ -113,3 +135,6 @@ var blankLine, i, indented, insideComment, len1, line, listItemStart, out, ref1;

indented = /^[\t ]/;
listItemStart = /^(?:\t?| {0,3})(?:[\*\-\+]|[0-9]{1,9}\.)[ \t]/;
listItemStart = /^(?:\t?| {0,3})(?:[\*\-\+]|[0-9]{1,9}\.)[ \t]/; // Up to one tab, or up to three spaces, or neither;
// followed by `*`, `-` or `+`;
// or by an integer up to 9 digits long, followed by a period;
// followed by a space or a tab.
insideComment = false;

@@ -135,2 +160,4 @@ ref1 = code.split('\n');

// Merge two jison-style location data objects together.
// If `last` is not provided, this will simply return `first`.
buildLocationData = function(first, last) {

@@ -149,7 +176,39 @@ if (!last) {

exports.addLocationDataFn = function(first, last) {
buildLocationHash = function(loc) {
return `${loc.first_line}x${loc.first_column}-${loc.last_line}x${loc.last_column}`;
};
// This returns a function which takes an object as a parameter, and if that
// object is an AST node, updates that object's locationData.
// The object is returned either way.
exports.addDataToNode = function(parserState, first, last) {
return function(obj) {
if (((typeof obj) === 'object') && (!!obj['updateLocationDataIfMissing'])) {
var i, len1, objHash, ref1, token, tokenHash;
// Add location data
if (((obj != null ? obj.updateLocationDataIfMissing : void 0) != null) && (first != null)) {
obj.updateLocationDataIfMissing(buildLocationData(first, last));
}
// Add comments data
if (!parserState.tokenComments) {
parserState.tokenComments = {};
ref1 = parserState.parser.tokens;
for (i = 0, len1 = ref1.length; i < len1; i++) {
token = ref1[i];
if (!token.comments) {
continue;
}
tokenHash = buildLocationHash(token[2]);
if (parserState.tokenComments[tokenHash] == null) {
parserState.tokenComments[tokenHash] = token.comments;
} else {
parserState.tokenComments[tokenHash].push(...token.comments);
}
}
}
if (obj.locationData != null) {
objHash = buildLocationHash(obj.locationData);
if (parserState.tokenComments[objHash] != null) {
attachCommentsToNode(parserState.tokenComments[objHash], obj);
}
}
return obj;

@@ -159,2 +218,14 @@ };

exports.attachCommentsToNode = attachCommentsToNode = function(comments, node) {
if ((comments == null) || comments.length === 0) {
return;
}
if (node.comments == null) {
node.comments = [];
}
return node.comments.push(...comments);
};
// Convert jison location data to a string.
// `obj` can be a token, or a locationData.
exports.locationDataToString = function(obj) {

@@ -174,2 +245,3 @@ var locationData;

// A `.coffee.md` compatible version of `basename`, that returns the file sans-extension.
exports.baseFileName = function(file, stripExt = false, useWinPathSep = false) {

@@ -191,2 +263,3 @@ var parts, pathSep;

// Determine if a filename represents a CoffeeScript file.
exports.isCoffee = function(file) {

@@ -196,2 +269,3 @@ return /\.((lit)?coffee|coffee\.md)$/.test(file);

// Determine if a filename represents a Literate CoffeeScript file.
exports.isLiterate = function(file) {

@@ -201,2 +275,6 @@ return /\.(litcoffee|coffee\.md)$/.test(file);

// Throws a SyntaxError from a given location.
// The error's `toString` will return an error message following the "standard"
// format `<filename>:<line>:<col>: <message>` plus the line with the error and a
// marker showing where the error is.
exports.throwSyntaxError = function(message, location) {

@@ -207,2 +285,5 @@ var error;

error.toString = syntaxErrorToString;
// Instead of showing the compiler's stacktrace, show our custom error message
// (this is useful when the error bubbles up in Node.js applications that
// compile CoffeeScript for example).
error.stack = error.toString();

@@ -212,3 +293,6 @@ throw error;

// Update a compiler SyntaxError with source code information if it didn't have
// it already.
exports.updateSyntaxError = function(error, code, filename) {
// Avoid screwing up the `stack` property of other errors (i.e. possible bugs).
if (error.toString === syntaxErrorToString) {

@@ -237,4 +321,6 @@ error.code || (error.code = code);

start = first_column;
// Show only the first line on multi-line errors.
end = first_line === last_line ? last_column + 1 : codeLine.length;
marker = codeLine.slice(0, start).replace(/[^\s]/g, ' ') + repeat('^', end - start);
// Check to see if we're running on a color-enabled TTY.
if (typeof process !== "undefined" && process !== null) {

@@ -241,0 +327,0 @@ colorsEnabled = ((ref1 = process.stdout) != null ? ref1.isTTY : void 0) && !((ref2 = process.env) != null ? ref2.NODE_DISABLE_COLORS : void 0);

@@ -1,3 +0,4 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
// Node.js Implementation
var CoffeeScript, compile, ext, fn, fs, helpers, i, len, path, ref, vm,

@@ -18,9 +19,15 @@ hasProp = {}.hasOwnProperty;

// Compile and execute a string of CoffeeScript (on the server), correctly
// setting `__filename`, `__dirname`, and relative `require()`.
CoffeeScript.run = function(code, options = {}) {
var answer, dir, mainModule, ref;
mainModule = require.main;
// Set the filename.
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '<anonymous>';
// Clear the module cache.
mainModule.moduleCache && (mainModule.moduleCache = {});
// Assign paths for node_modules loading
dir = options.filename != null ? path.dirname(fs.realpathSync(options.filename)) : fs.realpathSync('.');
mainModule.paths = require('module')._nodeModulePaths(dir);
// Compile.
if (!helpers.isCoffee(mainModule.filename) || require.extensions) {

@@ -33,2 +40,4 @@ answer = compile(code, options);

// Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
// The CoffeeScript REPL uses this to run the input.
CoffeeScript.eval = function(code, options = {}) {

@@ -62,2 +71,3 @@ var Module, _module, _require, createContext, i, isContext, js, k, len, o, r, ref, ref1, ref2, ref3, sandbox, v;

sandbox.__dirname = path.dirname(sandbox.__filename);
// define module/require only if they chose not to specify their own
if (!(sandbox !== global || sandbox.module || sandbox.require)) {

@@ -77,2 +87,3 @@ Module = require('module');

}
// use the same hack node currently uses for their own REPL
_require.paths = _module.paths = Module._nodeModulePaths(process.cwd());

@@ -90,3 +101,3 @@ _require.resolve = function(request) {

}
o.bare = true;
o.bare = true; // ensure return value
js = compile(code, o);

@@ -104,2 +115,3 @@ if (sandbox === global) {

// Throw error with deprecation warning when depending upon implicit `require.extensions` registration
if (require.extensions) {

@@ -122,2 +134,3 @@ ref = CoffeeScript.FILE_EXTENSIONS;

raw = fs.readFileSync(filename, 'utf8');
// Strip the Unicode byte order mark, if this file begins with one.
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;

@@ -134,2 +147,5 @@ try {

err = error;
// As the filename and code of a dynamically loaded file will be different
// from the original file compiled with CoffeeScript.run, add that
// information to error so it can be pretty-printed later.
throw helpers.updateSyntaxError(err, stripped, filename);

@@ -136,0 +152,0 @@ }

@@ -1,4 +0,14 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARABLE_LEFT_SIDE, COMPARE, COMPOUND_ASSIGN, CSX_ATTRIBUTE, CSX_IDENTIFIER, CSX_INTERPOLATION, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_CSX, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, starts, throwSyntaxError,
// 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
// form:
// [tag, value, locationData]
// where locationData is {first_line, first_column, last_line, last_column}, which is a
// format that can be fed directly into [Jison](https://github.com/zaach/jison). These
// are read by jison in the `parser.lexer` function defined in coffeescript.coffee.
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARABLE_LEFT_SIDE, COMPARE, COMPOUND_ASSIGN, CSX_ATTRIBUTE, CSX_IDENTIFIER, CSX_INTERPOLATION, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, HERE_JSTOKEN, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INSIDE_CSX, INVERSES, JSTOKEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, REGEX_INVALID_ESCAPE, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_INVALID_ESCAPE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, UNFINISHED, UNICODE_CODE_POINT_ESCAPE, VALID_FLAGS, WHITESPACE, attachCommentsToNode, compact, count, invertLiterate, isForFrom, isUnassignable, key, locationDataToString, merge, repeat, starts, throwSyntaxError,
indexOf = [].indexOf;

@@ -8,28 +18,51 @@

({count, starts, compact, repeat, invertLiterate, merge, locationDataToString, throwSyntaxError} = require('./helpers'));
// Import the helpers we need.
({count, starts, compact, repeat, invertLiterate, merge, attachCommentsToNode, locationDataToString, throwSyntaxError} = require('./helpers'));
// The Lexer Class
// ---------------
// The Lexer class reads a stream of CoffeeScript and divvies it up into tagged
// tokens. Some potential ambiguity in the grammar has been avoided by
// pushing some extra smarts into the Lexer.
exports.Lexer = Lexer = class Lexer {
// **tokenize** is the Lexer's main method. Scan by attempting to match tokens
// one at a time, using a regular expression anchored at the start of the
// remaining code, or a custom recursive token-matching method
// (for interpolations). When the next token has been recorded, we move forward
// within the code past the token, and begin again.
// Each tokenizing method is responsible for returning the number of characters
// it has consumed.
// Before returning the token stream, run it through the [Rewriter](rewriter.html).
tokenize(code, opts = {}) {
var consumed, end, i, ref;
this.literate = opts.literate;
this.indent = 0;
this.baseIndent = 0;
this.indebt = 0;
this.outdebt = 0;
this.indents = [];
this.indentLiteral = '';
this.ends = [];
this.tokens = [];
this.seenFor = false;
this.seenImport = false;
this.seenExport = false;
this.importSpecifierList = false;
this.exportSpecifierList = false;
this.csxDepth = 0;
this.chunkLine = opts.line || 0;
this.chunkColumn = opts.column || 0;
code = this.clean(code);
this.literate = opts.literate; // Are we lexing literate CoffeeScript?
this.indent = 0; // The current indentation level.
this.baseIndent = 0; // The overall minimum indentation level.
this.indebt = 0; // The over-indentation at the current level.
this.outdebt = 0; // The under-outdentation at the current level.
this.indents = []; // The stack of all current indentation levels.
this.indentLiteral = ''; // The indentation.
this.ends = []; // The stack for pairing up tokens.
this.tokens = []; // Stream of parsed tokens in the form `['TYPE', value, location data]`.
this.seenFor = false; // Used to recognize `FORIN`, `FOROF` and `FORFROM` tokens.
this.seenImport = false; // Used to recognize `IMPORT FROM? AS?` tokens.
this.seenExport = false; // Used to recognize `EXPORT FROM? AS?` tokens.
this.importSpecifierList = false; // Used to identify when in an `IMPORT {...} FROM? ...`.
this.exportSpecifierList = false; // Used to identify when in an `EXPORT {...} FROM? ...`.
this.csxDepth = 0; // Used to optimize CSX checks, how deep in CSX we are.
this.csxObjAttribute = {}; // Used to detect if CSX attributes is wrapped in {} (<div {props...} />).
this.chunkLine = opts.line || 0; // The start line for the current @chunk.
this.chunkColumn = opts.column || 0; // The start column of the current @chunk.
code = this.clean(code); // The stripped, cleaned original source code.
// At every position, run through this list of attempted matches,
// short-circuiting if any of them succeed. Their order determines precedence:
// `@literalToken` is the fallback catch-all.
i = 0;
while (this.chunk = code.slice(i)) {
consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.stringToken() || this.numberToken() || this.csxToken() || this.regexToken() || this.jsToken() || this.literalToken();
// Update position.
[this.chunkLine, this.chunkColumn] = this.getLineAndColumnFromChunk(consumed);

@@ -54,2 +87,5 @@ i += consumed;

// Preprocess the code to remove leading and trailing whitespace, carriage
// returns, etc. If we’re lexing literate CoffeeScript, strip external Markdown
// by removing all lines that aren’t indented by at least four spaces or a tab.
clean(code) {

@@ -70,4 +106,13 @@ if (code.charCodeAt(0) === BOM) {

// Tokenizers
// ----------
// 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
// allowed in JavaScript, we’re careful not to tag them as keywords when
// referenced as property names here, so you can still do `jQuery.is()` even
// though `is` means `===` otherwise.
identifierToken() {
var alias, colon, colonOffset, colonToken, id, idLength, inCSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, regex, tag, tagToken;
var alias, colon, colonOffset, colonToken, id, idLength, inCSXTag, input, match, poppedToken, prev, prevprev, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, regExSuper, regex, sup, tag, tagToken;
inCSXTag = this.atCSXTag();

@@ -79,2 +124,3 @@ regex = inCSXTag ? CSX_ATTRIBUTE : IDENTIFIER;

[input, id, colon] = match;
// Preserve length of id for location data
idLength = id.length;

@@ -109,2 +155,9 @@ poppedToken = void 0;

}
if (id === 'do' && (regExSuper = /^(\s*super)(?!\(\))/.exec(this.chunk.slice(3)))) {
this.token('SUPER', 'super');
this.token('CALL_START', '(');
this.token('CALL_END', ')');
[input, sup] = regExSuper;
return sup.length + 3;
}
prev = this.prev();

@@ -141,2 +194,5 @@ tag = colon || (prev != null) && (((ref4 = prev[0]) === '.' || ref4 === '?.' || ref4 === '::' || ref4 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';

this.seenFor = false;
// Throw an error on attempts to use `get` or `set` as keywords, or
// what CoffeeScript would normally interpret as calls to functions named
// `get` or `set`, i.e. `get({foo: function () {}})`.
} else if (tag === 'PROPERTY' && prev) {

@@ -194,3 +250,3 @@ if (prev.spaced && (ref6 = prev[0], indexOf.call(CALLABLE, ref6) >= 0) && /^[gs]et$/.test(prev[1])) {

colonToken = this.token(':', ':', colonOffset, colon.length);
if (inCSXTag) {
if (inCSXTag) { // used by rewriter
colonToken.csxColon = true;

@@ -205,2 +261,4 @@ }

// Matches numbers, including decimals, hex, and exponential notation.
// Be careful not to interfere with ranges in progress.
numberToken() {

@@ -252,2 +310,4 @@ var base, lexedLength, match, number, numberValue, tag;

// Matches strings, including multiline strings, as well as heredocs, with or without
// interpolation.
stringToken() {

@@ -259,2 +319,4 @@ var $, attempt, delimiter, doc, end, heredoc, i, indent, indentRegex, match, prev, quote, ref, regex, token, tokens;

}
// If the preceding token is `from` and this is an import or export statement,
// properly tag the `from`.
prev = this.prev();

@@ -284,2 +346,3 @@ if (prev && this.value() === 'from' && (this.seenImport || this.seenExport)) {

if (heredoc) {
// Find the smallest indentation. It will be removed from all lines later.
indent = null;

@@ -342,23 +405,73 @@ doc = ((function() {

commentToken() {
var comment, here, match;
if (!(match = this.chunk.match(COMMENT))) {
// Matches and consumes comments. The comments are taken out of the token
// stream and saved for later, to be reinserted into the output after
// everything has been parsed and the JavaScript code generated.
commentToken(chunk = this.chunk) {
var comment, commentAttachments, content, contents, here, i, match, matchIllegal, newLine, placeholderToken, prev;
if (!(match = chunk.match(COMMENT))) {
return 0;
}
[comment, here] = match;
contents = null;
// Does this comment follow code on the same line?
newLine = /^\s*\n+\s*#/.test(comment);
if (here) {
if (match = HERECOMMENT_ILLEGAL.exec(comment)) {
this.error(`block comments cannot contain ${match[0]}`, {
offset: match.index,
length: match[0].length
matchIllegal = HERECOMMENT_ILLEGAL.exec(comment);
if (matchIllegal) {
this.error(`block comments cannot contain ${matchIllegal[0]}`, {
offset: matchIllegal.index,
length: matchIllegal[0].length
});
}
if (here.indexOf('\n') >= 0) {
here = here.replace(RegExp(`\\n${repeat(' ', this.indent)}`, "g"), '\n');
// Parse indentation or outdentation as if this block comment didn’t exist.
chunk = chunk.replace(`###${here}###`, '');
// Remove leading newlines, like `Rewriter::removeLeadingNewlines`, to
// avoid the creation of unwanted `TERMINATOR` tokens.
chunk = chunk.replace(/^\n+/, '');
this.lineToken(chunk);
// Pull out the ###-style comment’s content, and format it.
content = here;
if (indexOf.call(content, '\n') >= 0) {
content = content.replace(RegExp(`\\n${repeat(' ', this.indent)}`, "g"), '\n');
}
this.token('HERECOMMENT', here, 0, comment.length);
contents = [content];
} else {
// The `COMMENT` regex captures successive line comments as one token.
// Remove any leading newlines before the first comment, but preserve
// blank lines between line comments.
content = comment.replace(/^(\n*)/, '');
content = content.replace(/^([ |\t]*)#/gm, '');
contents = content.split('\n');
}
commentAttachments = (function() {
var j, len, results;
results = [];
for (i = j = 0, len = contents.length; j < len; i = ++j) {
content = contents[i];
results.push({
content: content,
here: here != null,
newLine: newLine || i !== 0 // Line comments after the first one start new lines, by definition.
});
}
return results;
})();
prev = this.prev();
if (!prev) {
// If there’s no previous token, create a placeholder token to attach
// this comment to; and follow with a newline.
commentAttachments[0].newLine = true;
this.lineToken(this.chunk.slice(comment.length));
placeholderToken = this.makeToken('JS', '');
placeholderToken.generated = true;
placeholderToken.comments = commentAttachments;
this.tokens.push(placeholderToken);
this.newlineToken(0);
} else {
attachCommentsToNode(commentAttachments, prev);
}
return comment.length;
}
// Matches JavaScript interpolated directly into the source via backticks.
jsToken() {

@@ -369,3 +482,7 @@ var match, script;

}
// Convert escaped backticks to backticks, and escaped backslashes
// just before escaped backticks to backslashes
script = match[1].replace(/\\+(`|$)/g, function(string) {
// `string` is always a value like '\`', '\\\`', '\\\\\`', etc.
// By reducing it to its latter half, we turn '\`' to '`', '\\\`' to '\`', etc.
return string.slice(-Math.ceil(string.length / 2));

@@ -377,4 +494,7 @@ });

// Matches regular expression literals, as well as multiline extended ones.
// Lexing regular expressions is difficult to distinguish from division, so we
// borrow some basic heuristics from JavaScript and Ruby.
regexToken() {
var body, closed, end, flags, index, match, origin, prev, ref, ref1, regex, tokens;
var body, closed, comment, comments, end, flags, index, j, len, match, origin, prev, ref, ref1, regex, tokens;
switch (false) {

@@ -388,2 +508,9 @@ case !(match = REGEX_ILLEGAL.exec(this.chunk)):

({tokens, index} = match);
comments = this.chunk.slice(0, index).match(/\s+(#(?!{).*)/g);
if (comments) {
for (j = 0, len = comments.length; j < len; j++) {
comment = comments[j];
this.commentToken(comment);
}
}
break;

@@ -457,5 +584,15 @@ case !(match = REGEX.exec(this.chunk)):

lineToken() {
// Matches newlines, indents, and outdents, and determines which is which.
// If we can detect that the current line is continued onto the next line,
// then the newline is suppressed:
// elements
// .each( ... )
// .map( ... )
// Keeps track of the level of indentation, because a single outdent token
// can close multiple indents, so we need to know how far in we happen to be.
lineToken(chunk = this.chunk) {
var diff, indent, match, minLiteralLength, newIndentLiteral, noNewlines, size;
if (!(match = MULTI_DENT.exec(this.chunk))) {
if (!(match = MULTI_DENT.exec(chunk))) {
return 0;

@@ -496,3 +633,3 @@ }

if (size > this.indent) {
if (noNewlines || this.tag() === 'RETURN') {
if (noNewlines) {
this.indebt = size - this.indent;

@@ -527,2 +664,4 @@ this.suppressNewlines();

// Record an outdent token or multiple tokens, if we happen to be moving back
// inwards past several recorded indents. Sets new @indent value.
outdentToken(moveOut, noNewlines, outdentLength) {

@@ -545,2 +684,3 @@ var decreasedIndent, dent, lastIndent, ref;

this.outdebt = 0;
// pair might call outdentToken, so preserve decreasedIndent
this.pair('OUTDENT');

@@ -565,2 +705,4 @@ this.token('OUTDENT', moveOut, 0, outdentLength);

// Matches and consumes non-meaningful whitespace. Tag the previous token
// as being “spaced”, because there are some cases where it makes a difference.
whitespaceToken() {

@@ -582,2 +724,3 @@ var match, nline, prev;

// Generate a newline token. Consecutive newlines get merged together.
newlineToken(offset) {

@@ -593,4 +736,14 @@ while (this.value() === ';') {

// Use a `\` at a line-ending to suppress the newline.
// The slash is removed here once its job is done.
suppressNewlines() {
if (this.value() === '\\') {
var prev;
prev = this.prev();
if (prev[1] === '\\') {
if (prev.comments && this.tokens.length > 1) {
// `@tokens.length` should be at least 2 (some code, then `\`).
// If something puts a `\` after nothing, they deserve to lose any
// comments that trail it.
attachCommentsToNode(prev.comments, this.tokens[this.tokens.length - 2]);
}
this.tokens.pop();

@@ -601,7 +754,11 @@ }

// CSX is like JSX but for CoffeeScript.
csxToken() {
var afterTag, colon, csxTag, end, firstChar, id, input, match, origin, prev, ref, token, tokens;
var afterTag, colon, csxTag, end, firstChar, id, input, match, origin, prev, prevChar, ref, token, tokens;
firstChar = this.chunk[0];
// Check the previous token to detect if attribute is spread.
prevChar = this.tokens.length > 0 ? this.tokens[this.tokens.length - 1][0] : '';
if (firstChar === '<') {
match = CSX_IDENTIFIER.exec(this.chunk.slice(1));
// Not the right hand side of an unspaced comparison (i.e. `a<b`).
if (!(match && (this.csxDepth > 0 || !(prev = this.prev()) || prev.spaced || (ref = prev[0], indexOf.call(COMPARABLE_LEFT_SIDE, ref) < 0)))) {

@@ -613,3 +770,3 @@ return 0;

this.token('CALL_START', '(');
this.token('{', '{');
this.token('[', '[');
this.ends.push({

@@ -625,3 +782,3 @@ tag: '/>',

this.pair('/>');
this.token('}', '}', 0, 2);
this.token(']', ']', 0, 2);
this.token('CALL_END', ')', 0, 2);

@@ -631,3 +788,9 @@ this.csxDepth--;

} else if (firstChar === '{') {
token = this.token('(', '(');
if (prevChar === ':') {
token = this.token('(', '(');
this.csxObjAttribute[this.csxDepth] = false;
} else {
token = this.token('{', '{');
this.csxObjAttribute[this.csxDepth] = true;
}
this.ends.push({

@@ -639,4 +802,5 @@ tag: '}',

} else if (firstChar === '>') {
this.pair('/>');
origin = this.token('}', '}');
// Ignore terminators inside a tag.
this.pair('/>'); // As if the current tag was self-closing.
origin = this.token(']', ']');
this.token(',', ',');

@@ -665,2 +829,3 @@ ({

}
// +1 for the closing `>`.
this.token('CALL_END', ')', end, csxTag.name.length + 1);

@@ -675,3 +840,8 @@ this.csxDepth--;

this.pair(firstChar);
this.token(')', ')');
if (this.csxObjAttribute[this.csxDepth]) {
this.token('}', '}');
this.csxObjAttribute[this.csxDepth] = false;
} else {
this.token(')', ')');
}
this.token(',', ',');

@@ -693,3 +863,3 @@ return 1;

i = this.ends.length - 1;
while (((ref = this.ends[i]) != null ? ref.tag : void 0) === 'OUTDENT' || depth-- > 0) {
while (((ref = this.ends[i]) != null ? ref.tag : void 0) === 'OUTDENT' || depth-- > 0) { // Ignore indents.
i--;

@@ -701,2 +871,7 @@ }

// We treat all other single characters as a token. E.g.: `( ) , . !`
// Multi-character operators are also literal tokens, so that Jison can assign
// the proper order of operations. There are some symbols that we tag specially
// here. `;` and newlines are both treated as a `TERMINATOR`, we distinguish
// parentheses that indicate a method call from regular parentheses, and so on.
literalToken() {

@@ -794,2 +969,8 @@ var match, message, origin, prev, ref, ref1, ref2, ref3, skipToken, tag, token, value;

// Token Manipulators
// ------------------
// A source of ambiguity in our grammar used to be parameter lists in function
// definitions versus argument lists in function calls. Walk backwards, tagging
// parameters specially in order to make things easier for the parser.
tagParameters() {

@@ -826,2 +1007,3 @@ var i, paramEndToken, stack, tok, tokens;

// Close up all remaining open blocks at the end of the file.
closeIndentation() {

@@ -831,2 +1013,21 @@ return this.outdentToken(this.indent);

// Match the contents of a delimited token and expand variables and expressions
// inside it using Ruby-like notation for substitution of arbitrary
// expressions.
// "Hello #{name.capitalize()}."
// If it encounters an interpolation, this method will recursively create a new
// Lexer and tokenize until the `{` of `#{` is balanced with a `}`.
// - `regex` matches the contents of a token (but not `delimiter`, and not
// `#{` if interpolations are desired).
// - `delimiter` is the delimiter of the token. Examples are `'`, `"`, `'''`,
// `"""` and `///`.
// - `closingDelimiter` is different from `delimiter` only in CSX
// - `interpolators` matches the start of an interpolation, for CSX it's both
// `{` and `<` (i.e. nested CSX tag)
// This method allows us to have strings within interpolations within strings,
// ad infinitum.
matchWithInterpolations(regex, delimiter, closingDelimiter, interpolators) {

@@ -852,2 +1053,3 @@ var braceInterpolator, close, column, firstToken, index, interpolationOffset, interpolator, lastToken, line, match, nested, offsetInChunk, open, ref, rest, str, strPart, tokens;

});
// Push a fake `'NEOSTRING'` token, which will get turned into a real string later.
tokens.push(this.makeToken('NEOSTRING', strPart, offsetInChunk));

@@ -860,2 +1062,3 @@ str = str.slice(strPart.length);

[interpolator] = match;
// To remove the `#` in `#{`.
interpolationOffset = interpolator.length - 1;

@@ -872,5 +1075,8 @@ [line, column] = this.getLineAndColumnFromChunk(offsetInChunk + interpolationOffset);

}));
// Account for the `#` in `#{`
index += interpolationOffset;
braceInterpolator = str[index - 1] === '}';
if (braceInterpolator) {
// Turn the leading and trailing `{` and `}` into parentheses. Unnecessary
// parentheses will be removed later.
open = nested[0], close = nested[nested.length - 1];

@@ -882,5 +1088,7 @@ open[0] = open[1] = '(';

if (((ref = nested[1]) != null ? ref[0] : void 0) === 'TERMINATOR') {
// Remove leading `'TERMINATOR'` (if any).
nested.splice(1, 1);
}
if (!braceInterpolator) {
// We are not using `{` and `}`, so wrap the interpolated tokens instead.
open = this.makeToken('(', '(', offsetInChunk, 0);

@@ -890,2 +1098,3 @@ close = this.makeToken(')', ')', offsetInChunk + index, 0);

}
// Push a fake `'TOKENS'` token, which will get turned into real tokens later.
tokens.push(['TOKENS', nested]);

@@ -917,2 +1126,6 @@ str = str.slice(index);

// Merge the array `tokens` of the fake token types `'TOKENS'` and `'NEOSTRING'`
// (as returned by `matchWithInterpolations`) into the token stream. The value
// of `'NEOSTRING'`s are converted using `fn` and turned into strings using
// `options` first.
mergeInterpolationTokens(tokens, options, fn) {

@@ -930,4 +1143,7 @@ var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, rparen, tag, token, tokensToPush, value;

if (value.length === 2) {
// Optimize out empty interpolations (an empty pair of parentheses).
continue;
}
// Push all the tokens in the fake `'TOKENS'` token. These already have
// sane location data.
locationToken = value[0];

@@ -937,3 +1153,7 @@ tokensToPush = value;

case 'NEOSTRING':
// Convert `'NEOSTRING'` into `'STRING'`.
converted = fn.call(this, token[1], i);
// Optimize out empty strings. We ensure that the tokens stream always
// starts with a string token, though, to make sure that the result
// really is a string.
if (converted.length === 0) {

@@ -946,4 +1166,6 @@ if (i === 0) {

}
// However, there is one case where we can optimize away a starting
// empty string.
if (i === 2 && (firstEmptyStringIndex != null)) {
this.tokens.splice(firstEmptyStringIndex, 2);
this.tokens.splice(firstEmptyStringIndex, 2); // Remove empty string and the plus.
}

@@ -956,2 +1178,3 @@ token[0] = 'STRING';

if (this.tokens.length > firstIndex) {
// Create a 0-length "+" token.
plusToken = this.token('+', '+');

@@ -970,3 +1193,5 @@ plusToken[2] = {

lparen.origin = [
'STRING', null, {
'STRING',
null,
{
first_line: lparen[2].first_line,

@@ -978,2 +1203,3 @@ first_column: lparen[2].first_column,

];
lparen[2] = lparen.origin[2];
rparen = this.token('STRING_END', ')');

@@ -989,2 +1215,4 @@ return rparen[2] = {

// Pairs up a closing token, ensuring that all listed pairs of tokens are
// correctly balanced throughout the course of the token stream.
pair(tag) {

@@ -997,2 +1225,7 @@ var lastIndent, prev, ref, ref1, wanted;

}
// Auto-close `INDENT` to support syntax like this:
// el.click((event) ->
// el.hide())
ref1 = this.indents, lastIndent = ref1[ref1.length - 1];

@@ -1005,2 +1238,8 @@ this.outdentToken(lastIndent, true);

// Helpers
// -------
// Returns the line and column number from an offset into the current chunk.
// `offset` is a number of characters into `@chunk`.
getLineAndColumnFromChunk(offset) {

@@ -1027,2 +1266,4 @@ var column, lastLine, lineCount, ref, string;

// Same as `token`, except this just returns the token without adding it
// to the results.
makeToken(tag, value, offsetInChunk = 0, length = value.length) {

@@ -1032,2 +1273,4 @@ var lastCharacter, locationData, token;

[locationData.first_line, locationData.first_column] = this.getLineAndColumnFromChunk(offsetInChunk);
// Use length - 1 for the final offset - we're supplying the last_line and the last_column,
// so if last_column == first_column, then we're looking at a character of length 1.
lastCharacter = length > 0 ? length - 1 : 0;

@@ -1039,2 +1282,8 @@ [locationData.last_line, locationData.last_column] = this.getLineAndColumnFromChunk(offsetInChunk + lastCharacter);

// Add a token to the results.
// `offset` is the offset into the current `@chunk` where the token starts.
// `length` is the length of the token in the `@chunk`, after the offset. If
// not specified, the length of `value` will be used.
// Returns the new token.
token(tag, value, offsetInChunk, length, origin) {

@@ -1050,2 +1299,3 @@ var token;

// Peek at the last tag in the token stream.
tag() {

@@ -1057,2 +1307,3 @@ var ref, token;

// Peek at the last value in the token stream.
value() {

@@ -1064,2 +1315,3 @@ var ref, token;

// Get the previous token in the token stream.
prev() {

@@ -1069,5 +1321,6 @@ return this.tokens[this.tokens.length - 1];

// Are we in the midst of an unfinished expression?
unfinished() {
var ref;
return LINE_CONTINUER.test(this.chunk) || ((ref = this.tag()) === '\\' || ref === '.' || ref === '?.' || ref === '?::' || ref === 'UNARY' || ref === 'MATH' || ref === 'UNARY_MATH' || ref === '+' || ref === '-' || ref === '**' || ref === 'SHIFT' || ref === 'RELATION' || ref === 'COMPARE' || ref === '&' || ref === '^' || ref === '|' || ref === '&&' || ref === '||' || ref === 'BIN?' || ref === 'THROW' || ref === 'EXTENDS' || ref === 'DEFAULT');
return LINE_CONTINUER.test(this.chunk) || (ref = this.tag(), indexOf.call(UNFINISHED, ref) >= 0);
}

@@ -1099,2 +1352,3 @@

}
// surrogate pair
high = Math.floor((codePoint - 0x10000) / 0x400) + 0xD800;

@@ -1105,2 +1359,3 @@ low = (codePoint - 0x10000) % 0x400 + 0xDC00;

// Replace `\u{...}` with `\uxxxx[\uxxxx]` in regexes without `u` flag
replaceUnicodeCodePointEscapes(str, options) {

@@ -1128,2 +1383,3 @@ var shouldReplace;

// Validates escapes in strings and regexes.
validateEscapes(str, options = {}) {

@@ -1145,2 +1401,3 @@ var before, hex, invalidEscape, invalidEscapeRegex, match, message, octal, ref, unicode, unicodeCodePoint;

// Constructs a string or regex by escaping certain characters.
makeDelimitedLiteral(body, options = {}) {

@@ -1151,5 +1408,11 @@ var regex;

}
regex = RegExp(`(\\\\\\\\)|(\\\\0(?=[1-7]))|\\\\?(${options.delimiter})|\\\\?(?:(\\n)|(\\r)|(\\u2028)|(\\u2029))|(\\\\.)`, "g");
regex = RegExp(`(\\\\\\\\)|(\\\\0(?=[1-7]))|\\\\?(${options.delimiter // Escaped backslash.
// Null character mistaken as octal escape.
// (Possibly escaped) delimiter.
// (Possibly escaped) newlines.
// Other escapes.
})|\\\\?(?:(\\n)|(\\r)|(\\u2028)|(\\u2029))|(\\\\.)`, "g");
body = body.replace(regex, function(match, backslash, nul, delimiter, lf, cr, ls, ps, other) {
switch (false) {
// Ignore escaped backslashes.
case !backslash:

@@ -1184,2 +1447,4 @@ if (options.double) {

// Throws an error at either a given offset from the current chunk or at the
// location of a token (`token[2]`).
error(message, options = {}) {

@@ -1197,2 +1462,4 @@ var first_column, first_line, location, ref, ref1;

// Helper functions
// ----------------
isUnassignable = function(name, displayName = name) {

@@ -1213,5 +1480,10 @@ switch (false) {

// `from` isn’t a CoffeeScript keyword, but it behaves like one in `import` and
// `export` statements (handled above) and in the declaration line of a `for`
// loop. Try to detect when `from` is a variable identifier and when it is this
// “sometimes” keyword.
isForFrom = function(prev) {
var ref;
if (prev[0] === 'IDENTIFIER') {
// `for i from from`, `for from from iterable`
if (prev[1] === 'from') {

@@ -1221,5 +1493,8 @@ prev[1][0] = 'IDENTIFIER';

}
// `for i from iterable`
return true;
// `for from…`
} else if (prev[0] === 'FOR') {
return false;
// `for {from}…`, `for [from]…`, `for {a, from}…`, `for {a: from}…`
} else if ((ref = prev[1]) === '{' || ref === '[' || ref === ',' || ref === ':') {

@@ -1232,4 +1507,9 @@ return false;

// Constants
// ---------
// Keywords that CoffeeScript shares in common with JavaScript.
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'yield', 'await', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super', 'import', 'export', 'default'];
// CoffeeScript-only keywords.
COFFEE_KEYWORDS = ['undefined', 'Infinity', 'NaN', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];

@@ -1260,2 +1540,5 @@

// The list of keywords that are reserved by JavaScript, but not used, or are
// used by CoffeeScript internally. We throw an error when these are encountered,
// to avoid having a JavaScript error at runtime.
RESERVED = ['case', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'native', 'implements', 'interface', 'package', 'private', 'protected', 'public', 'static'];

@@ -1265,19 +1548,34 @@

// The superset of both JavaScript keywords and reserved words, none of which may
// be used as identifiers or properties.
exports.JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);
// The character code of the nasty Microsoft madness otherwise known as the BOM.
BOM = 65279;
IDENTIFIER = /^(?!\d)((?:(?!\s)[$\w\x7f-\uffff])+)([^\n\S]*:(?!:))?/;
// Token matching regexes.
IDENTIFIER = /^(?!\d)((?:(?!\s)[$\w\x7f-\uffff])+)([^\n\S]*:(?!:))?/; // Is this a property name?
CSX_IDENTIFIER = /^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/;
CSX_IDENTIFIER = /^(?![\d<])((?:(?!\s)[\.\-$\w\x7f-\uffff])+)/; // Must not start with `<`.
// Like `IDENTIFIER`, but includes `-`s and `.`s.
CSX_ATTRIBUTE = /^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/;
CSX_ATTRIBUTE = /^(?!\d)((?:(?!\s)[\-$\w\x7f-\uffff])+)([^\S]*=(?!=))?/; // Like `IDENTIFIER`, but includes `-`s.
// Is this an attribute with a value?
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; // binary
// octal
// hex
// decimal
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>*\/%])\2=?|\?(\.|::)|\.{2,3})/;
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>*\/%])\2=?|\?(\.|::)|\.{2,3})/; // function
// compound assign / compare
// zero-fill right shift
// doubles
// logic / shift / power / floor division / modulo
// soak access
// range or splat
WHITESPACE = /^[^\n\S]+/;
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/;
COMMENT = /^\s*###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/;

@@ -1292,2 +1590,3 @@ CODE = /^[-=]>/;

// String-matching-regexes.
STRING_START = /^(?:'''|"""|'|")/;

@@ -1303,7 +1602,10 @@

INSIDE_CSX = /^(?:[^\{<])*/;
INSIDE_CSX = /^(?:[^\{<])*/; // Start of CoffeeScript interpolation. // Similar to `HEREDOC_DOUBLE` but there is no escaping.
// Maybe CSX tag (`<` not allowed even if bare).
CSX_INTERPOLATION = /^(?:\{|<(?!\/))/;
CSX_INTERPOLATION = /^(?:\{|<(?!\/))/; // CoffeeScript interpolation.
// CSX opening tag.
STRING_OMIT = /((?:\\\\)+)|\\[^\S\n]*\n\s*/g;
STRING_OMIT = /((?:\\\\)+)|\\[^\S\n]*\n\s*/g; // Consume (and preserve) an even number of backslashes.
// Remove escaped newlines.

@@ -1314,3 +1616,6 @@ SIMPLE_STRING_OMIT = /\s*\n\s*/g;

REGEX = /^\/(?!\/)((?:[^[\/\n\\]|\\[^\n]|\[(?:\\[^\n]|[^\]\n\\])*\])*)(\/)?/;
// Regex-matching-regexes.
REGEX = /^\/(?!\/)((?:[^[\/\n\\]|\\[^\n]|\[(?:\\[^\n]|[^\]\n\\])*\])*)(\/)?/; // Every other thing.
// Anything but newlines escaped.
// Character class.

@@ -1323,3 +1628,5 @@ REGEX_FLAGS = /^\w*/;

HEREGEX_OMIT = /((?:\\\\)+)|\\(\s)|\s+(?:#.*)?/g;
HEREGEX_OMIT = /((?:\\\\)+)|\\(\s)|\s+(?:#.*)?/g; // Consume (and preserve) an even number of backslashes.
// Preserve escaped whitespace.
// Remove whitespace and comments.

@@ -1330,2 +1637,3 @@ REGEX_ILLEGAL = /^(\/|\/{3}\s*)(\*)/;

// Other regexes.
HERECOMMENT_ILLEGAL = /\*\//;

@@ -1335,7 +1643,15 @@

STRING_INVALID_ESCAPE = /((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7]|[1-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/;
STRING_INVALID_ESCAPE = /((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7]|[1-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/; // Make sure the escape isn’t escaped.
// octal escape
// hex escape
// unicode code point escape
// unicode escape
REGEX_INVALID_ESCAPE = /((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/;
REGEX_INVALID_ESCAPE = /((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7])|(x(?![\da-fA-F]{2}).{0,2})|(u\{(?![\da-fA-F]{1,}\})[^}]*\}?)|(u(?!\{|[\da-fA-F]{4}).{0,4}))/; // Make sure the escape isn’t escaped.
// octal escape
// hex escape
// unicode code point escape
// unicode escape
UNICODE_CODE_POINT_ESCAPE = /(\\\\)|\\u\{([\da-fA-F]+)\}/g;
UNICODE_CODE_POINT_ESCAPE = /(\\\\)|\\u\{([\da-fA-F]+)\}/g; // Make sure the escape isn’t escaped.

@@ -1348,4 +1664,6 @@ LEADING_BLANK_LINE = /^[^\n\S]*\n/;

// Compound assignment tokens.
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=', '**=', '//=', '%%='];
// Unary tokens.
UNARY = ['NEW', 'TYPEOF', 'DELETE', 'DO'];

@@ -1355,12 +1673,20 @@

// Bit-shifting tokens.
SHIFT = ['<<', '>>', '>>>'];
// Comparison tokens.
COMPARE = ['==', '!=', '<', '>', '<=', '>='];
// Mathematical tokens.
MATH = ['*', '/', '%', '//', '%%'];
// Relational tokens that are negatable with `not` prefix.
RELATION = ['IN', 'OF', 'INSTANCEOF'];
// Boolean tokens.
BOOL = ['TRUE', 'FALSE'];
// Tokens which could legitimately be invoked or indexed. An opening
// parentheses or bracket following these tokens will be recorded as the start
// of a function invocation or indexing operation.
CALLABLE = ['IDENTIFIER', 'PROPERTY', ')', ']', '?', '@', 'THIS', 'SUPER'];

@@ -1370,10 +1696,22 @@

// Tokens which can be the left-hand side of a less-than comparison, i.e. `a<b`.
COMPARABLE_LEFT_SIDE = ['IDENTIFIER', ')', ']', 'NUMBER'];
// Tokens which a regular expression will never immediately follow (except spaced
// CALLABLEs in some cases), but which a division operator can.
// See: http://www-archive.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
NOT_REGEX = INDEXABLE.concat(['++', '--']);
// Tokens that, when immediately preceding a `WHEN`, indicate that the `WHEN`
// 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'];
// Additional indent in front of these is ignored.
INDENTABLE_CLOSERS = [')', '}', ']'];
// Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', '**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||', 'BIN?', 'EXTENDS', 'DEFAULT'];
}).call(this);

@@ -1,63 +0,76 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat;
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
slice = [].slice;
({repeat} = require('./helpers'));
// A simple **OptionParser** class to parse option flags from the command-line.
// Use it like so:
// parser = new OptionParser switches, helpBanner
// options = parser.parse process.argv
// The first non-option is considered to be the start of the file (and file
// option) list, and all subsequent arguments are left unparsed.
// The `coffee` command uses an instance of **OptionParser** to parse its
// command-line arguments in `src/command.coffee`.
exports.OptionParser = OptionParser = class OptionParser {
constructor(rules, banner) {
// Initialize with a list of valid options, in the form:
// [short-flag, long-flag, description]
// Along with an optional banner for the usage help.
constructor(ruleDeclarations, banner) {
this.banner = banner;
this.rules = buildRules(rules);
this.rules = buildRules(ruleDeclarations);
}
// Parse the list of arguments, populating an `options` object with all of the
// specified options, and return it. Options after the first non-option
// argument are treated as arguments. `options.arguments` will be an array
// containing the remaining arguments. This is a simpler API than many option
// parsers that allow you to attach callback actions for every flag. Instead,
// you're responsible for interpreting the options object.
parse(args) {
var arg, i, isOption, j, k, len, len1, matchedRule, options, originalArgs, pos, ref, rule, seenNonOptionArg, skippingArgument, value;
options = {
arguments: []
};
skippingArgument = false;
originalArgs = args;
args = normalizeArguments(args);
for (i = j = 0, len = args.length; j < len; i = ++j) {
arg = args[i];
if (skippingArgument) {
skippingArgument = false;
continue;
}
if (arg === '--') {
pos = originalArgs.indexOf('--');
options.arguments = options.arguments.concat(originalArgs.slice(pos + 1));
break;
}
isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
seenNonOptionArg = options.arguments.length > 0;
if (!seenNonOptionArg) {
matchedRule = false;
ref = this.rules;
for (k = 0, len1 = ref.length; k < len1; k++) {
rule = ref[k];
if (rule.shortFlag === arg || rule.longFlag === arg) {
value = true;
if (rule.hasArgument) {
skippingArgument = true;
value = args[i + 1];
}
options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
matchedRule = true;
break;
var argument, hasArgument, i, isList, len, name, options, positional, rules;
// The CoffeeScript option parser is a little odd; options after the first
// non-option argument are treated as non-option arguments themselves.
// Optional arguments are normalized by expanding merged flags into multiple
// flags. This allows you to have `-wl` be the same as `--watch --lint`.
// Note that executable scripts with a shebang (`#!`) line should use the
// line `#!/usr/bin/env coffee`, or `#!/absolute/path/to/coffee`, without a
// `--` argument after, because that will fail on Linux (see #3946).
({rules, positional} = normalizeArguments(args, this.rules.flagDict));
options = {};
// The `argument` field is added to the rule instance non-destructively by
// `normalizeArguments`.
for (i = 0, len = rules.length; i < len; i++) {
({hasArgument, argument, isList, name} = rules[i]);
if (hasArgument) {
if (isList) {
if (options[name] == null) {
options[name] = [];
}
options[name].push(argument);
} else {
options[name] = argument;
}
if (isOption && !matchedRule) {
throw new Error(`unrecognized option: ${arg}`);
}
} else {
options[name] = true;
}
if (seenNonOptionArg || !isOption) {
options.arguments.push(arg);
}
}
if (positional[0] === '--') {
options.doubleDashed = true;
positional = positional.slice(1);
}
options.arguments = positional;
return options;
}
// Return the help text for this **OptionParser**, listing and describing all
// of the valid options, for `--help` and such.
help() {
var j, len, letPart, lines, ref, rule, spaces;
var i, len, letPart, lines, ref, rule, spaces;
lines = [];

@@ -67,5 +80,5 @@ if (this.banner) {

}
ref = this.rules;
for (j = 0, len = ref.length; j < len; j++) {
rule = ref[j];
ref = this.rules.ruleList;
for (i = 0, len = ref.length; i < len; i++) {
rule = ref[i];
spaces = 15 - rule.longFlag.length;

@@ -81,2 +94,6 @@ spaces = spaces > 0 ? repeat(' ', spaces) : '';

// Helpers
// -------
// Regex matchers for option flags on the command line and their rules.
LONG_FLAG = /^(--\w[\w\-]*)/;

@@ -88,23 +105,50 @@

// Matches the long flag part of a rule for an option with an argument. Not
// applied to anything in process.argv.
OPTIONAL = /\[(\w+(\*?))\]/;
buildRules = function(rules) {
var j, len, results, tuple;
results = [];
for (j = 0, len = rules.length; j < len; j++) {
tuple = rules[j];
if (tuple.length < 3) {
tuple.unshift(null);
// Build and return the list of option rules. If the optional *short-flag* is
// unspecified, leave it out by padding with `null`.
buildRules = function(ruleDeclarations) {
var flag, flagDict, i, j, len, len1, ref, rule, ruleList, tuple;
ruleList = (function() {
var i, len, results;
results = [];
for (i = 0, len = ruleDeclarations.length; i < len; i++) {
tuple = ruleDeclarations[i];
if (tuple.length < 3) {
tuple.unshift(null);
}
results.push(buildRule(...tuple));
}
results.push(buildRule(...tuple));
return results;
})();
flagDict = {};
for (i = 0, len = ruleList.length; i < len; i++) {
rule = ruleList[i];
ref = [rule.shortFlag, rule.longFlag];
// `shortFlag` is null if not provided in the rule.
for (j = 0, len1 = ref.length; j < len1; j++) {
flag = ref[j];
if (!(flag != null)) {
continue;
}
if (flagDict[flag] != null) {
throw new Error(`flag ${flag} for switch ${rule.name} was already declared for switch ${flagDict[flag].name}`);
}
flagDict[flag] = rule;
}
}
return results;
return {ruleList, flagDict};
};
buildRule = function(shortFlag, longFlag, description, options = {}) {
// Build a rule from a `-o` short flag, a `--output [DIR]` long flag, and the
// description of what the option does.
buildRule = function(shortFlag, longFlag, description) {
var match;
match = longFlag.match(OPTIONAL);
shortFlag = shortFlag != null ? shortFlag.match(SHORT_FLAG)[1] : void 0;
longFlag = longFlag.match(LONG_FLAG)[1];
return {
name: longFlag.substr(2),
name: longFlag.replace(/^--/, ''),
shortFlag: shortFlag,

@@ -118,21 +162,73 @@ longFlag: longFlag,

normalizeArguments = function(args) {
var arg, j, k, l, len, len1, match, ref, result;
args = args.slice(0);
result = [];
for (j = 0, len = args.length; j < len; j++) {
arg = args[j];
if (match = arg.match(MULTI_FLAG)) {
ref = match[1].split('');
for (k = 0, len1 = ref.length; k < len1; k++) {
l = ref[k];
result.push('-' + l);
normalizeArguments = function(args, flagDict) {
var arg, argIndex, flag, i, innerOpts, j, k, lastOpt, len, len1, multiFlags, multiOpts, needsArgOpt, positional, ref, rule, rules, singleRule, withArg;
rules = [];
positional = [];
needsArgOpt = null;
for (argIndex = i = 0, len = args.length; i < len; argIndex = ++i) {
arg = args[argIndex];
// If the previous argument given to the script was an option that uses the
// next command-line argument as its argument, create copy of the option’s
// rule with an `argument` field.
if (needsArgOpt != null) {
withArg = Object.assign({}, needsArgOpt.rule, {
argument: arg
});
rules.push(withArg);
needsArgOpt = null;
continue;
}
multiFlags = (ref = arg.match(MULTI_FLAG)) != null ? ref[1].split('').map(function(flagName) {
return `-${flagName}`;
}) : void 0;
if (multiFlags != null) {
multiOpts = multiFlags.map(function(flag) {
var rule;
rule = flagDict[flag];
if (rule == null) {
throw new Error(`unrecognized option ${flag} in multi-flag ${arg}`);
}
return {rule, flag};
});
// Only the last flag in a multi-flag may have an argument.
innerOpts = 2 <= multiOpts.length ? slice.call(multiOpts, 0, j = multiOpts.length - 1) : (j = 0, []), lastOpt = multiOpts[j++];
for (k = 0, len1 = innerOpts.length; k < len1; k++) {
({rule, flag} = innerOpts[k]);
if (rule.hasArgument) {
throw new Error(`cannot use option ${flag} in multi-flag ${arg} except as the last option, because it needs an argument`);
}
rules.push(rule);
}
if (lastOpt.rule.hasArgument) {
needsArgOpt = lastOpt;
} else {
rules.push(lastOpt.rule);
}
} else if ([LONG_FLAG, SHORT_FLAG].some(function(pat) {
return arg.match(pat) != null;
})) {
singleRule = flagDict[arg];
if (singleRule == null) {
throw new Error(`unrecognized option ${arg}`);
}
if (singleRule.hasArgument) {
needsArgOpt = {
rule: singleRule,
flag: arg
};
} else {
rules.push(singleRule);
}
} else {
result.push(arg);
// This is a positional argument.
positional = args.slice(argIndex);
break;
}
}
return result;
if (needsArgOpt != null) {
throw new Error(`value required for ${needsArgOpt.flag}, but it was the last argument provided`);
}
return {rules, positional};
};
}).call(this);

@@ -1,2 +0,2 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {

@@ -13,2 +13,3 @@ var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, i, len, loadFile, path, ref;

// Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = function(module, filename) {

@@ -20,2 +21,4 @@ var answer;

// If the installed version of Node supports `require.extensions`, register
// CoffeeScript as an extension.
if (require.extensions) {

@@ -27,2 +30,4 @@ ref = CoffeeScript.FILE_EXTENSIONS;

}
// Patch Node's module loader to be able to handle multi-dot extensions.
// This is a horrible thing that should not be required.
Module = require('module');

@@ -33,4 +38,6 @@ findExtension = function(filename) {

if (extensions[0] === '') {
// Remove the initial dot from dotfiles.
extensions.shift();
}
// Start with the longest possible extension and work our way shortwards.
while (extensions.shift()) {

@@ -54,2 +61,4 @@ curExtension = '.' + extensions.join('.');

// If we're on Node, patch `child_process.fork` so that Coffee scripts are able
// to fork both CoffeeScript files, and JavaScript files, directly.
if (child_process) {

@@ -56,0 +65,0 @@ ({fork} = child_process);

@@ -1,4 +0,4 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, updateSyntaxError, vm;
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, updateSyntaxError, vm;

@@ -17,2 +17,4 @@ fs = require('fs');

sawSIGINT = false;
replDefaults = {

@@ -28,10 +30,18 @@ prompt: 'coffee> ',

historyMaxInputSize: 10240,
eval: function(input, context, filename, cb) {
var Assign, Block, Literal, Value, ast, err, js, referencedVars, token, tokens;
eval: async function(input, context, filename, cb) {
var Assign, Block, Call, Code, Literal, Value, ast, err, isAsync, js, referencedVars, result, token, tokens;
// XXX: multiline hack.
input = input.replace(/\uFF00/g, '\n');
// Node's REPL sends the input ending with a newline and then wrapped in
// parens. Unwrap all that.
input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1');
// Node's REPL v6.9.1+ sends the input wrapped in a try/catch statement.
// Unwrap that too.
input = input.replace(/^\s*try\s*{([\s\S]*)}\s*catch.*$/m, '$1');
({Block, Assign, Value, Literal} = require('./nodes'));
// Require AST nodes to do some AST manipulation.
({Block, Assign, Value, Literal, Call, Code} = require('./nodes'));
try {
// Tokenize the clean input.
tokens = CoffeeScript.tokens(input);
// Collect referenced variable names just like in `CoffeeScript.compile`.
referencedVars = (function() {

@@ -48,12 +58,31 @@ var i, len, results;

})();
// Generate the AST of the tokens.
ast = CoffeeScript.nodes(tokens);
// Add assignment to `__` variable to force the input to be an expression.
ast = new Block([new Assign(new Value(new Literal('__')), ast, '=')]);
// Wrap the expression in a closure to support top-level `await`
ast = new Code([], ast);
isAsync = ast.isAsync;
// Invoke the wrapping closure
ast = new Block([new Call(ast)]);
js = ast.compile({
bare: true,
locals: Object.keys(context),
referencedVars
referencedVars,
sharedScope: true
});
return cb(null, runInContext(js, context, filename));
result = runInContext(js, context, filename);
// Await an async result, if necessary
if (isAsync) {
result = (await result);
if (!sawSIGINT) {
cb(null, result);
}
return sawSIGINT = false;
} else {
return cb(null, result);
}
} catch (error) {
err = error;
// AST's `compile` does not add source code information to syntax errors.
updateSyntaxError(err, input);

@@ -76,2 +105,3 @@ return cb(err);

({rli, inputStream, outputStream} = repl);
// Node 0.11.12 changed API, prompt is now _prompt.
origPrompt = (ref = repl._prompt) != null ? ref : repl.prompt;

@@ -88,2 +118,3 @@ multiline = {

};
// Proxy node's line listener
nodeLineListener = rli.listeners('line')[0];

@@ -101,2 +132,3 @@ rli.removeListener('line', nodeLineListener);

});
// Handle Ctrl-v
return inputStream.on('keypress', function(char, key) {

@@ -107,2 +139,3 @@ if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) {

if (multiline.enabled) {
// allow arbitrarily switching between modes any time before multiple lines are entered
if (!multiline.buffer.match(/\n/)) {

@@ -114,5 +147,7 @@ multiline.enabled = !multiline.enabled;

}
// no-op unless the current line is empty
if ((rli.line != null) && !rli.line.match(/^\s*$/)) {
return;
}
// eval, print, loop
multiline.enabled = !multiline.enabled;

@@ -123,2 +158,3 @@ rli.line = '';

rli.output.clearLine(1);
// XXX: multiline hack
multiline.buffer = multiline.buffer.replace(/\n/g, '\uFF00');

@@ -135,2 +171,3 @@ rli.emit('line', multiline.buffer);

// Store and load command history from a file
addHistory = function(repl, filename, maxSize) {

@@ -140,4 +177,6 @@ var buffer, fd, lastLine, readFd, size, stat;

try {
// Get file info and at most maxSize of command history
stat = fs.statSync(filename);
size = Math.min(maxSize, stat.size);
// Read last `size` bytes from the file
readFd = fs.openSync(filename, 'r');

@@ -147,7 +186,10 @@ buffer = Buffer.alloc(size);

fs.closeSync(readFd);
// Set the history on the interpreter
repl.rli.history = buffer.toString().split('\n').reverse();
if (stat.size > maxSize) {
// If the history file was truncated we should pop off a potential partial line
repl.rli.history.pop();
}
if (repl.rli.history[0] === '') {
// Shift off the final blank newline
repl.rli.history.shift();

@@ -161,2 +203,3 @@ }

if (code && code.length && code !== '.history' && code !== '.exit' && lastLine !== code) {
// Save the latest command in the file
fs.writeSync(fd, `${code}\n`);

@@ -166,5 +209,10 @@ return lastLine = code;

});
// XXX: The SIGINT event from REPLServer is undocumented, so this is a bit fragile
repl.on('SIGINT', function() {
return sawSIGINT = true;
});
repl.on('exit', function() {
return fs.closeSync(fd);
});
// Add a command to show the history stack
return repl.commands[getCommandId(repl, 'history')] = {

@@ -181,2 +229,3 @@ help: 'Show command history',

var commandsHaveLeadingDot;
// Node 0.11 changed API, a command such as '.help' is now stored as 'help'
commandsHaveLeadingDot = repl.commands['.help'] != null;

@@ -216,2 +265,3 @@ if (commandsHaveLeadingDot) {

}
// Adapt help inherited from the node REPL
repl.commands[getCommandId(repl, 'load')].help = 'Load code from a file into this REPL session';

@@ -218,0 +268,0 @@ return repl;

@@ -1,4 +0,10 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
var BALANCED_PAIRS, CALL_CLOSERS, CONTROL_IN_IMPLICIT, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, rite, throwSyntaxError,
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
// and shorthand syntax. This can greatly complicate a grammar and bloat
// the resulting parse table. Instead of making the parser handle it all, we take
// a series of passes over the token stream, using this **Rewriter** to convert
// shorthand into the unambiguous long form, add implicit indentation and
// parentheses, and generally clean things up.
var BALANCED_PAIRS, CALL_CLOSERS, CONTROL_IN_IMPLICIT, DISCARDED, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, moveComments, right, throwSyntaxError,
indexOf = [].indexOf;

@@ -8,16 +14,71 @@

generate = function(tag, value, origin) {
var tok;
tok = [tag, value];
tok.generated = true;
// Move attached comments from one token to another.
moveComments = function(fromToken, toToken) {
var comment, k, len, ref, unshiftedComments;
if (!fromToken.comments) {
return;
}
if (toToken.comments && toToken.comments.length !== 0) {
unshiftedComments = [];
ref = fromToken.comments;
for (k = 0, len = ref.length; k < len; k++) {
comment = ref[k];
if (comment.unshift) {
unshiftedComments.push(comment);
} else {
toToken.comments.push(comment);
}
}
toToken.comments = unshiftedComments.concat(toToken.comments);
} else {
toToken.comments = fromToken.comments;
}
return delete fromToken.comments;
};
// Create a generated token: one that exists due to a use of implicit syntax.
// Optionally have this new token take the attached comments from another token.
generate = function(tag, value, origin, commentsToken) {
var token;
token = [tag, value];
token.generated = true;
if (origin) {
tok.origin = origin;
token.origin = origin;
}
return tok;
if (commentsToken) {
moveComments(commentsToken, token);
}
return token;
};
// The **Rewriter** class is used by the [Lexer](lexer.html), directly against
// its internal array of tokens.
exports.Rewriter = Rewriter = (function() {
class Rewriter {
// Rewrite the token stream in multiple passes, one logical filter at
// a time. This could certainly be changed into a single pass through the
// stream, with a big ol’ efficient switch, but it’s much nicer to work with
// like this. The order of these passes matters—indentation must be
// corrected before implicit parentheses can be wrapped around blocks of code.
rewrite(tokens1) {
var ref, ref1, t;
this.tokens = tokens1;
// Set environment variable `DEBUG_TOKEN_STREAM` to `true` to output token
// debugging info. Also set `DEBUG_REWRITTEN_TOKEN_STREAM` to `true` to
// output the token stream after it has been rewritten by this file.
if (typeof process !== "undefined" && process !== null ? (ref = process.env) != null ? ref.DEBUG_TOKEN_STREAM : void 0 : void 0) {
if (process.env.DEBUG_REWRITTEN_TOKEN_STREAM) {
console.log('Initial token stream:');
}
console.log(((function() {
var k, len, ref1, results;
ref1 = this.tokens;
results = [];
for (k = 0, len = ref1.length; k < len; k++) {
t = ref1[k];
results.push(t[0] + '/' + t[1] + (t.comments ? '*' : ''));
}
return results;
}).call(this)).join(' '));
}
this.removeLeadingNewlines();

@@ -29,8 +90,29 @@ this.closeOpenCalls();

this.addImplicitBracesAndParens();
this.rescueStowawayComments();
this.addLocationDataToGeneratedTokens();
this.enforceValidCSXAttributes();
this.fixOutdentLocationData();
if (typeof process !== "undefined" && process !== null ? (ref1 = process.env) != null ? ref1.DEBUG_REWRITTEN_TOKEN_STREAM : void 0 : void 0) {
if (process.env.DEBUG_TOKEN_STREAM) {
console.log('Rewritten token stream:');
}
console.log(((function() {
var k, len, ref2, results;
ref2 = this.tokens;
results = [];
for (k = 0, len = ref2.length; k < len; k++) {
t = ref2[k];
results.push(t[0] + '/' + t[1] + (t.comments ? '*' : ''));
}
return results;
}).call(this)).join(' '));
}
return this.tokens;
}
// Rewrite the token stream, looking one token ahead and behind.
// Allow the return value of the block to tell us how many tokens to move
// forwards (or backwards) in the stream, to make sure we don’t miss anything
// as tokens are inserted and removed, and the stream changes length under
// our feet.
scanTokens(block) {

@@ -70,4 +152,6 @@ var i, token, tokens;

// Leading newlines would introduce an ambiguity in the grammar, so we
// dispatch them here.
removeLeadingNewlines() {
var i, k, len, ref, tag;
var i, k, l, leadingNewlineToken, len, len1, ref, ref1, tag;
ref = this.tokens;

@@ -77,10 +161,22 @@ for (i = k = 0, len = ref.length; k < len; i = ++k) {

if (tag !== 'TERMINATOR') {
// Find the index of the first non-`TERMINATOR` token.
break;
}
}
if (i) {
return this.tokens.splice(0, i);
if (i === 0) {
return;
}
ref1 = this.tokens.slice(0, i);
// If there are any comments attached to the tokens we’re about to discard,
// shift them forward to what will become the new first token.
for (l = 0, len1 = ref1.length; l < len1; l++) {
leadingNewlineToken = ref1[l];
moveComments(leadingNewlineToken, this.tokens[i]);
}
// Discard all the leading newline tokens.
return this.tokens.splice(0, i);
}
// The lexer has tagged the opening parenthesis of a method call. Match it with
// its paired close.
closeOpenCalls() {

@@ -103,2 +199,4 @@ var action, condition;

// The lexer has tagged the opening bracket of an indexing operation call.
// Match it with its paired close.
closeOpenIndexes() {

@@ -121,2 +219,5 @@ var action, condition;

// Match tags in token stream starting at `i` with `pattern`.
// `pattern` may consist of strings (equality), an array of strings (one of)
// or null (wildcard). Returns the index of the match or -1 if no match.
indexOfTag(i, ...pattern) {

@@ -126,5 +227,2 @@ var fuzz, j, k, ref, ref1;

for (j = k = 0, ref = pattern.length; 0 <= ref ? k < ref : k > ref; j = 0 <= ref ? ++k : --k) {
while (this.tag(i + j + fuzz) === 'HERECOMMENT') {
fuzz += 2;
}
if (pattern[j] == null) {

@@ -143,9 +241,11 @@ continue;

// Returns `yes` if standing in front of something looking like
// `@<x>:`, `<x>:` or `<EXPRESSION_START><x>...<EXPRESSION_END>:`.
looksObjectish(j) {
var end, index;
if (this.indexOfTag(j, '@', null, ':') > -1 || this.indexOfTag(j, null, ':') > -1) {
if (this.indexOfTag(j, '@', null, ':') !== -1 || this.indexOfTag(j, null, ':') !== -1) {
return true;
}
index = this.indexOfTag(j, EXPRESSION_START);
if (index > -1) {
if (index !== -1) {
end = null;

@@ -165,2 +265,5 @@ this.detectEnd(index + 1, (function(token) {

// Returns `yes` if current line of tokens contain an element of tags on same
// expression level. Stop searching at `LINEBREAKS` or explicit start of
// containing balanced expression.
findTagsBackwards(i, tags) {

@@ -181,4 +284,7 @@ var backStack, ref, ref1, ref2, ref3, ref4, ref5;

// Look for signs of implicit calls and objects in the token stream and
// add them.
addImplicitBracesAndParens() {
var stack, start;
// Track current balancing depth (both implicit and explicit) on stack.
stack = [];

@@ -195,5 +301,8 @@ start = null;

startIdx = i;
// Helper function, used for keeping track of the number of tokens consumed
// and spliced, when returning for getting a new token.
forward = function(n) {
return i - startIdx + n;
};
// Helper functions
isImplicit = function(stackItem) {

@@ -218,2 +327,4 @@ var ref;

};
// Unclosed control statement inside implicit parens (like
// class declaration or if-conditionals).
inImplicitControl = function() {

@@ -225,11 +336,13 @@ var ref;

stack.push([
'(', idx, {
'(',
idx,
{
ours: true
}
]);
return tokens.splice(idx, 0, generate('CALL_START', '('));
return tokens.splice(idx, 0, generate('CALL_START', '(', ['', 'implicit function call', token[2]], prevToken));
};
endImplicitCall = function() {
stack.pop();
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]]));
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]], prevToken));
return i += 1;

@@ -240,3 +353,5 @@ };

stack.push([
'{', idx, {
'{',
idx,
{
sameLine: true,

@@ -249,3 +364,3 @@ startsLine: startsLine,

val.generated = true;
return tokens.splice(idx, 0, generate('{', val, token));
return tokens.splice(idx, 0, generate('{', val, token, prevToken));
};

@@ -255,3 +370,3 @@ endImplicitObject = function(j) {

stack.pop();
tokens.splice(j, 0, generate('}', '}', token));
tokens.splice(j, 0, generate('}', '}', token, prevToken));
return i += 1;

@@ -274,5 +389,8 @@ };

};
// Don’t end an implicit call/object on next indent if any of these are in an argument/value.
if ((inImplicitCall() || inImplicitObject()) && indexOf.call(CONTROL_IN_IMPLICIT, tag) >= 0 || inImplicitObject() && prevTag === ':' && tag === 'FOR') {
stack.push([
'CONTROL', i, {
'CONTROL',
i,
{
ours: true

@@ -284,2 +402,6 @@ }

if (tag === 'INDENT' && inImplicit()) {
// An `INDENT` closes an implicit call unless
// 1. We have seen a `CONTROL` argument on the line.
// 2. The last token before the indent is part of the list below.
if (prevTag !== '=>' && prevTag !== '->' && prevTag !== '[' && prevTag !== '(' && prevTag !== ',' && prevTag !== '{' && prevTag !== 'ELSE' && prevTag !== '=') {

@@ -300,2 +422,3 @@ while (inImplicitCall() || inImplicitObject() && prevTag !== ':') {

}
// Straightforward start of explicit expression.
if (indexOf.call(EXPRESSION_START, tag) >= 0) {

@@ -305,2 +428,3 @@ stack.push([tag, i]);

}
// Close all implicit expressions inside of explicitly closed expressions.
if (indexOf.call(EXPRESSION_END, tag) >= 0) {

@@ -318,3 +442,6 @@ while (inImplicit()) {

}
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !nextToken.spaced && !nextToken.newLine)) {
// Recognize standard implicit calls like
// f a, f() b, f? c, h[0] d etc.
// Added support for spread dots on the left side: f ...a
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || nextTag === '...' || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !nextToken.spaced && !nextToken.newLine)) {
if (tag === '?') {

@@ -326,2 +453,20 @@ tag = token[0] = 'FUNC_EXIST';

}
// Implicit call taking an implicit indented object as first argument.
// f
// a: b
// c: d
// Don’t accept implicit calls of this type, when on the same line
// as the control structures below as that may misinterpret constructs like:
// if f
// a: 1
// as
// if f(a: 1)
// which is probably always unintended.
// Furthermore don’t allow this in literal arrays, as
// that creates grammatical ambiguities.
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT') > -1 && this.looksObjectish(i + 2) && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {

@@ -332,3 +477,5 @@ startImplicitCall(i + 1);

}
// Implicit objects start here.
if (tag === ':') {
// Go back to the (implicit) start of the object.
s = (function() {

@@ -345,6 +492,4 @@ var ref;

}).call(this);
while (this.tag(s - 2) === 'HERECOMMENT') {
s -= 2;
}
startsLine = s === 0 || (ref = this.tag(s - 1), indexOf.call(LINEBREAKS, ref) >= 0) || tokens[s - 1].newLine;
// Are we just continuing an already declared object?
if (stackTop()) {

@@ -359,5 +504,24 @@ [stackTag, stackIdx] = stackTop();

}
// End implicit calls when chaining method calls
// like e.g.:
// f ->
// a
// .g b, ->
// c
// .h a
// and also
// f a
// .g b
// .h a
// Mark all enclosing objects as not sameLine
if (indexOf.call(LINEBREAKS, tag) >= 0) {
for (k = stack.length - 1; k >= 0; k += -1) {
stackItem = stack[k];
if (!isImplicit(stackItem)) {
break;
}
if (isImplicitObject(stackItem)) {

@@ -372,10 +536,13 @@ stackItem[2].sameLine = false;

[stackTag, stackIdx, {sameLine, startsLine}] = stackTop();
// Close implicit calls when reached end of argument list
if (inImplicitCall() && prevTag !== ',') {
endImplicitCall();
// Close implicit objects such as:
// return a: 1, b: 2 unless true
} else if (inImplicitObject() && sameLine && tag !== 'TERMINATOR' && prevTag !== ':' && !((tag === 'POST_IF' || tag === 'FOR' || tag === 'WHILE' || tag === 'UNTIL') && startsLine && implicitObjectContinues(i + 1))) {
endImplicitObject();
// Close implicit objects when at end of line, line didn't end with a comma
// and the implicit object didn't start the line or the next line doesn’t look like
// the continuation of an object.
} else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
if (nextTag === 'HERECOMMENT') {
return forward(1);
}
endImplicitObject();

@@ -387,3 +554,21 @@ } else {

}
// Close implicit object if comma is the last character
// and what comes after doesn’t look like it belongs.
// This is used for trailing commas and calls, like:
// x =
// a: b,
// c: d,
// e = 2
// and
// f a, b: c, d: e, f, g: h: i, j
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
// When nextTag is OUTDENT the comma is insignificant and
// should just be ignored so embed it in the implicit object.
// When it isn’t the comma go on to play a role in a call or
// array further up the stack, so give it a chance.
offset = nextTag === 'OUTDENT' ? 1 : 0;

@@ -398,2 +583,3 @@ while (inImplicitObject()) {

// Make sure only strings and wrapped expressions are used in CSX attributes.
enforceValidCSXAttributes() {

@@ -405,3 +591,3 @@ return this.scanTokens(function(token, i, tokens) {

if ((ref = next[0]) !== 'STRING_START' && ref !== 'STRING' && ref !== '(') {
throwSyntaxError('expected wrapped or quoted CSX attribute', next[2]);
throwSyntaxError('expected wrapped or quoted JSX attribute', next[2]);
}

@@ -413,2 +599,117 @@ }

// Not all tokens survive processing by the parser. To avoid comments getting
// lost into the ether, find comments attached to doomed tokens and move them
// to a token that will make it to the other side.
rescueStowawayComments() {
var insertPlaceholder, shiftCommentsBackward, shiftCommentsForward;
insertPlaceholder = function(token, j, tokens, method) {
if (tokens[j][0] !== 'TERMINATOR') {
tokens[method](generate('TERMINATOR', '\n', tokens[j]));
}
return tokens[method](generate('JS', '', tokens[j], token));
};
shiftCommentsForward = function(token, i, tokens) {
var comment, j, k, len, ref, ref1, ref2;
// Find the next surviving token and attach this token’s comments to it,
// with a flag that we know to output such comments *before* that
// token’s own compilation. (Otherwise comments are output following
// the token they’re attached to.)
j = i;
while (j !== tokens.length && (ref = tokens[j][0], indexOf.call(DISCARDED, ref) >= 0)) {
j++;
}
if (!(j === tokens.length || (ref1 = tokens[j][0], indexOf.call(DISCARDED, ref1) >= 0))) {
ref2 = token.comments;
for (k = 0, len = ref2.length; k < len; k++) {
comment = ref2[k];
comment.unshift = true;
}
moveComments(token, tokens[j]);
return 1; // All following tokens are doomed!
} else {
j = tokens.length - 1;
insertPlaceholder(token, j, tokens, 'push');
// The generated tokens were added to the end, not inline, so we don’t skip.
return 1;
}
};
shiftCommentsBackward = function(token, i, tokens) {
var j, ref, ref1;
// Find the last surviving token and attach this token’s comments to it.
j = i;
while (j !== -1 && (ref = tokens[j][0], indexOf.call(DISCARDED, ref) >= 0)) {
j--;
}
if (!(j === -1 || (ref1 = tokens[j][0], indexOf.call(DISCARDED, ref1) >= 0))) {
moveComments(token, tokens[j]);
return 1; // All previous tokens are doomed!
} else {
insertPlaceholder(token, 0, tokens, 'unshift');
// We added two tokens, so shift forward to account for the insertion.
return 3;
}
};
return this.scanTokens(function(token, i, tokens) {
var dummyToken, j, ref, ref1, ret;
if (!token.comments) {
return 1;
}
ret = 1;
if (ref = token[0], indexOf.call(DISCARDED, ref) >= 0) {
// This token won’t survive passage through the parser, so we need to
// rescue its attached tokens and redistribute them to nearby tokens.
// Comments that don’t start a new line can shift backwards to the last
// safe token, while other tokens should shift forward.
dummyToken = {
comments: []
};
j = token.comments.length - 1;
while (j !== -1) {
if (token.comments[j].newLine === false && token.comments[j].here === false) {
dummyToken.comments.unshift(token.comments[j]);
token.comments.splice(j, 1);
}
j--;
}
if (dummyToken.comments.length !== 0) {
ret = shiftCommentsBackward(dummyToken, i - 1, tokens);
}
if (token.comments.length !== 0) {
shiftCommentsForward(token, i, tokens);
}
} else {
// If any of this token’s comments start a line—there’s only
// whitespace between the preceding newline and the start of the
// comment—and this isn’t one of the special `JS` tokens, then
// shift this comment forward to precede the next valid token.
// `Block.compileComments` also has logic to make sure that
// “starting new line” comments follow or precede the nearest
// newline relative to the token that the comment is attached to,
// but that newline might be inside a `}` or `)` or other generated
// token that we really want this comment to output after. Therefore
// we need to shift the comments here, avoiding such generated and
// discarded tokens.
dummyToken = {
comments: []
};
j = token.comments.length - 1;
while (j !== -1) {
if (token.comments[j].newLine && !token.comments[j].unshift && !(token[0] === 'JS' && token.generated)) {
dummyToken.comments.unshift(token.comments[j]);
token.comments.splice(j, 1);
}
j--;
}
if (dummyToken.comments.length !== 0) {
ret = shiftCommentsForward(dummyToken, i + 1, tokens);
}
}
if (((ref1 = token.comments) != null ? ref1.length : void 0) === 0) {
delete token.comments;
}
return ret;
});
}
// Add location data to all tokens generated by the rewriter.
addLocationDataToGeneratedTokens() {

@@ -446,2 +747,5 @@ return this.scanTokens(function(token, i, tokens) {

// `OUTDENT` tokens should always be positioned at the last character of the
// previous token, so that AST nodes ending in an `OUTDENT` token end up with a
// location corresponding to the last “real” token under the node.
fixOutdentLocationData() {

@@ -464,2 +768,7 @@ return this.scanTokens(function(token, i, tokens) {

// Because our grammar is LALR(1), it can’t handle some single-line
// expressions that lack ending delimiters. The **Rewriter** adds the implicit
// blocks, so it doesn’t need to. To keep the grammar clean and tidy, trailing
// newlines within expressions are removed and the indentation tokens of empty
// blocks are added.
normalizeLines() {

@@ -519,2 +828,4 @@ var action, condition, indent, outdent, starter;

// Tag postfix conditionals as such, so that we can parse them with a
// different precedence.
tagPostfixConditionals() {

@@ -544,2 +855,3 @@ var action, condition, original;

// Generate the indentation tokens, based on another token on the same line.
indentation(origin) {

@@ -558,2 +870,3 @@ var indent, outdent;

// Look up a tag by token index.
tag(i) {

@@ -572,6 +885,13 @@ var ref;

// Constants
// ---------
// List of the token pairs that must be balanced.
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['REGEX_START', 'REGEX_END']];
// The inverse mappings of `BALANCED_PAIRS` we’re trying to fix up, so we can
// look things up from either end.
exports.INVERSES = INVERSES = {};
// The tokens that signal the start/end of a balanced pair.
EXPRESSION_START = [];

@@ -582,11 +902,14 @@

for (k = 0, len = BALANCED_PAIRS.length; k < len; k++) {
[left, rite] = BALANCED_PAIRS[k];
EXPRESSION_START.push(INVERSES[rite] = left);
EXPRESSION_END.push(INVERSES[left] = rite);
[left, right] = BALANCED_PAIRS[k];
EXPRESSION_START.push(INVERSES[right] = left);
EXPRESSION_END.push(INVERSES[left] = right);
}
// Tokens that indicate the close of a clause of an expression.
EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
// Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation.
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
// If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
IMPLICIT_CALL = ['IDENTIFIER', 'CSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];

@@ -596,4 +919,7 @@

// Tokens that always mark the end of an implicit call for single-liners.
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
// Single-line flavors of block expressions that have unclosed endings.
// The grammar can’t disambiguate them, so we insert the implicit indentation.
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];

@@ -603,8 +929,19 @@

// Tokens that end a line.
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
// Tokens that close open calls when they follow a newline.
CALL_CLOSERS = ['.', '?.', '::', '?::'];
// Tokens that prevent a subsequent indent from ending implicit calls/objects
CONTROL_IN_IMPLICIT = ['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH'];
// Tokens that are swallowed up by the parser, never leading to code generation.
// You can spot these in `grammar.coffee` because the `o` function second
// argument doesn’t contain a `new` call for these tokens.
// `STRING_START` isn’t on this list because its `locationData` matches that of
// the node that becomes `StringWithInterpolations`, and therefore
// `addDataToNode` attaches `STRING_START`’s tokens to that node.
DISCARDED = ['(', ')', '[', ']', '{', '}', '.', '..', '...', ',', '=', '++', '--', '?', 'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'ELSE', 'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'LEADING_WHEN', 'OUTDENT', 'PARAM_START', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
}).call(this);

@@ -1,3 +0,9 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
// The **Scope** class regulates lexical scoping within CoffeeScript. As you
// generate code, you create a tree of scopes in the same shape as the nested
// function bodies. Each scope knows about the variables declared within it,
// and has a reference to its parent enclosing scope. In this way, we know which
// variables are new and need to be declared with `var`, and which are shared
// with external scopes.
var Scope,

@@ -7,2 +13,7 @@ indexOf = [].indexOf;

exports.Scope = Scope = class Scope {
// Initialize a scope with its parent, for lookups up the chain,
// as well as a reference to the **Block** node it belongs to, which is
// where it should declare its variables, a reference to the function that
// it belongs to, and a list of variables referenced in the source code
// and therefore should be avoided when generating variables.
constructor(parent, expressions, method, referencedVars) {

@@ -24,5 +35,7 @@ var ref, ref1;

}
// The `@root` is the top-level **Scope** object for a given file.
this.root = (ref = (ref1 = this.parent) != null ? ref1.root : void 0) != null ? ref : this;
}
// Adds a new variable or overrides an existing one.
add(name, type, immediate) {

@@ -39,2 +52,7 @@ if (this.shared && !immediate) {

// When `super` is called, we need to find the name of the current method we're
// in, so that we know how to invoke the same method of the parent class. This
// can get complicated if super is being called from an inner function.
// `namedMethod` will walk up the scope tree until it either finds the first
// function object that has a name filled in, or bottoms out.
namedMethod() {

@@ -48,2 +66,4 @@ var ref;

// Look up a variable name in lexical scope, and declare it if it does not
// already exist.
find(name, type = 'var') {

@@ -57,2 +77,4 @@ if (this.check(name)) {

// Reserve a variable name as originating from a function parameter for this
// scope. No `var` required for internal references.
parameter(name) {

@@ -65,2 +87,4 @@ if (this.shared && this.parent.check(name, true)) {

// Just check to see if a variable has already been declared, without reserving,
// walks up to the root scope.
check(name) {

@@ -71,2 +95,3 @@ var ref;

// Generate a temporary variable name at the given index.
temporary(name, index, single = false) {

@@ -87,2 +112,3 @@ var diff, endCode, letter, newCode, num, startCode;

// Gets the type of a variable.
type(name) {

@@ -100,2 +126,4 @@ var i, len, ref, v;

// If we need to store an intermediate result, find an available name for a
// compiler-generated variable. `_var`, `_var2`, and so on...
freeVariable(name, options = {}) {

@@ -117,2 +145,4 @@ var index, ref, temp;

// Ensure that an assignment is made at the top of this scope
// (or at the top-level scope, if requested).
assign(name, value) {

@@ -126,2 +156,3 @@ this.add(name, {

// Does this scope have any declared variables?
hasDeclarations() {

@@ -131,2 +162,3 @@ return !!this.declaredVariables().length;

// Return the list of variables first declared in this scope.
declaredVariables() {

@@ -148,2 +180,4 @@ var v;

// Return the list of assignments that are supposed to be made at the top
// of this scope.
assignedVariables() {

@@ -150,0 +184,0 @@ var i, len, ref, results, v;

@@ -1,3 +0,20 @@

// Generated by CoffeeScript 2.0.0-beta3
// Generated by CoffeeScript 2.0.0-beta4
(function() {
// Source maps allow JavaScript runtimes to match running JavaScript back to
// the original source code that corresponds to it. This can be minified
// JavaScript, but in our case, we're concerned with mapping pretty-printed
// JavaScript back to CoffeeScript.
// In order to produce maps, we must keep track of positions (line number, column number)
// that originated every node in the syntax tree, and be able to generate a
// [map file](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit)
// — which is a compact, VLQ-encoded representation of the JSON serialization
// of this information — to write out alongside the generated JavaScript.
// LineMap
// -------
// A **LineMap** object keeps track of information about original line and column
// positions for a single line of output JavaScript code.
// **SourceMaps** are implemented in terms of **LineMaps**.
var LineMap, SourceMap;

@@ -33,2 +50,11 @@

// SourceMap
// ---------
// Maps locations in a single generated JavaScript file back to locations in
// the original CoffeeScript source file.
// This is intentionally agnostic towards how a source map might be represented on
// disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
// through the arrays of line and column buffer to produce it.
SourceMap = (function() {

@@ -42,2 +68,6 @@ var BASE64_CHARS, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK;

// Adds a mapping to this SourceMap. `sourceLocation` and `generatedLocation`
// are both `[line, column]` arrays. If `options.noReplace` is true, then if there
// is already a mapping for the specified `line` and `column`, this will have no
// effect.
add(sourceLocation, generatedLocation, options = {}) {

@@ -50,2 +80,4 @@ var base, column, line, lineMap;

// Look up the original position of a given `line` and `column` in the generated
// code.
sourceLocation([line, column]) {

@@ -59,2 +91,9 @@ var lineMap;

// V3 SourceMap Generation
// -----------------------
// Builds up a V3 source map, returning the generated JSON as a string.
// `options.sourceRoot` may be used to specify the sourceRoot written to the source
// map. Also, `options.sourceFiles` and `options.generatedFile` may be passed to
// set "sources" and "file", respectively.
generate(options = {}, code = null) {

@@ -84,2 +123,3 @@ var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline;

}
// Write a comma if we've already written a segment on this line.
if (needComma) {

@@ -89,7 +129,15 @@ buffer += ",";

}
// Write the next segment. Segments can be 1, 4, or 5 values. If just one, then it
// is a generated column which doesn't match anything in the source code.
// The starting column in the generated source, relative to any previous recorded
// column for the current line:
buffer += this.encodeVlq(mapping.column - lastColumn);
lastColumn = mapping.column;
// The index into the list of sources:
buffer += this.encodeVlq(0);
// The starting line in the original source, relative to the previous source line.
buffer += this.encodeVlq(mapping.sourceLine - lastSourceLine);
lastSourceLine = mapping.sourceLine;
// The starting column in the original source, relative to the previous column.
buffer += this.encodeVlq(mapping.sourceColumn - lastSourceColumn);

@@ -101,2 +149,3 @@ lastSourceColumn = mapping.sourceColumn;

}
// Produce the canonical JSON object format for a "v3" source map.
v3 = {

@@ -119,4 +168,7 @@ version: 3,

answer = '';
// Least significant bit represents the sign.
signBit = value < 0 ? 1 : 0;
// The next bits are the actual value.
valueToEncode = (Math.abs(value) << 1) + signBit;
// Make sure we encode at least one character, even if valueToEncode is 0.
while (valueToEncode || !answer) {

@@ -141,8 +193,18 @@ nextChunk = valueToEncode & VLQ_VALUE_MASK;

// Base64 VLQ Encoding
// -------------------
// Note that SourceMap VLQ encoding is "backwards". MIDI-style VLQ encoding puts
// the most-significant-bit (MSB) from the original value into the MSB of the VLQ
// encoded value (see [Wikipedia](https://en.wikipedia.org/wiki/File:Uintvar_coding.svg)).
// SourceMap VLQ does things the other way around, with the least significat four
// bits of the original value encoded into the first byte of the VLQ encoded value.
VLQ_SHIFT = 5;
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT;
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT; // 0010 0000
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1;
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1; // 0001 1111
// Regular Base64 Encoding
// -----------------------
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

@@ -154,4 +216,5 @@

// Our API for source maps is just the `SourceMap` class.
module.exports = SourceMap;
}).call(this);

@@ -11,3 +11,3 @@ {

"author": "Jeremy Ashkenas",
"version": "2.0.0-beta3",
"version": "2.0.0-beta4",
"license": "MIT",

@@ -43,13 +43,14 @@ "engines": {

"devDependencies": {
"babel-core": "^6.24.1",
"babel-preset-babili": "0.0.12",
"babel-preset-env": "^1.4.0",
"babel-core": "~6.25.0",
"babel-preset-babili": "~0.1.4",
"babel-preset-env": "~1.6.0",
"babili": "^0.1.4",
"docco": "~0.7.0",
"highlight.js": "~9.11.0",
"highlight.js": "~9.12.0",
"jison": ">=0.4.17",
"markdown-it": "^8.3.1",
"markdown-it": "~8.3.1",
"underscore": "~1.8.3",
"webpack": "^2.5.1"
"webpack": "~3.2.0"
},
"dependencies": {}
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc