adding interpolation to heredocs, using the same rules as for strings
This commit is contained in:
parent
70cfc9500e
commit
d880b8b8f2
|
@ -11,7 +11,7 @@
|
|||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
// The help banner that is printed when `coffee` is called without arguments.
|
||||
BANNER = "coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee";
|
||||
BANNER = 'coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee';
|
||||
// The list of all the valid option flags that `coffee` knows how to handle.
|
||||
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['--no-wrap', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||
// Top-level objects shared by all the functions.
|
||||
|
|
11
lib/lexer.js
11
lib/lexer.js
|
@ -169,12 +169,13 @@
|
|||
// Matches heredocs, adjusting indentation to the correct level, as heredocs
|
||||
// preserve whitespace, but ignore indentation to the left.
|
||||
Lexer.prototype.heredoc_token = function heredoc_token() {
|
||||
var doc, match;
|
||||
var doc, match, quote;
|
||||
if (!((match = this.chunk.match(HEREDOC)))) {
|
||||
return false;
|
||||
}
|
||||
doc = this.sanitize_heredoc(match[2] || match[4]);
|
||||
this.token('STRING', "\"" + doc + "\"");
|
||||
quote = match[1].substr(0, 1);
|
||||
doc = this.sanitize_heredoc(match[2] || match[4], quote);
|
||||
this.interpolate_string('' + quote + doc + quote);
|
||||
this.line += count(match[1], "\n");
|
||||
this.i += match[1].length;
|
||||
return true;
|
||||
|
@ -383,10 +384,10 @@
|
|||
};
|
||||
// Sanitize a heredoc by escaping internal double quotes and erasing all
|
||||
// external indentation on the left-hand side.
|
||||
Lexer.prototype.sanitize_heredoc = function sanitize_heredoc(doc) {
|
||||
Lexer.prototype.sanitize_heredoc = function sanitize_heredoc(doc, quote) {
|
||||
var indent;
|
||||
indent = (doc.match(HEREDOC_INDENT) || ['']).sort()[0];
|
||||
return doc.replace(new RegExp("^" + indent, 'gm'), '').replace(MULTILINER, "\\n").replace(/"/g, '\\"');
|
||||
return doc.replace(new RegExp("^" + indent, 'gm'), '').replace(MULTILINER, "\\n").replace(new RegExp(quote, 'g'), '\\"');
|
||||
};
|
||||
// A source of ambiguity in our grammar used to be parameter lists in function
|
||||
// definitions versus argument lists in function calls. Walk backwards, tagging
|
||||
|
|
|
@ -494,7 +494,7 @@
|
|||
};
|
||||
__extends(ExtendsNode, BaseNode);
|
||||
ExtendsNode.prototype.type = 'Extends';
|
||||
ExtendsNode.prototype.code = "function(child, parent) {\n var ctor = function(){ };\n ctor.prototype = parent.prototype;\n child.__superClass__ = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n }";
|
||||
ExtendsNode.prototype.code = 'function(child, parent) {\n var ctor = function(){ };\n ctor.prototype = parent.prototype;\n child.__superClass__ = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n }';
|
||||
// Hooks one constructor into another's prototype chain.
|
||||
ExtendsNode.prototype.compile_node = function compile_node(o) {
|
||||
var call, ref;
|
||||
|
|
|
@ -126,8 +126,9 @@ exports.Lexer: class Lexer
|
|||
# preserve whitespace, but ignore indentation to the left.
|
||||
heredoc_token: ->
|
||||
return false unless match = @chunk.match(HEREDOC)
|
||||
doc: @sanitize_heredoc match[2] or match[4]
|
||||
@token 'STRING', "\"$doc\""
|
||||
quote: match[1].substr(0, 1)
|
||||
doc: @sanitize_heredoc match[2] or match[4], quote
|
||||
@interpolate_string "$quote$doc$quote"
|
||||
@line += count match[1], "\n"
|
||||
@i += match[1].length
|
||||
true
|
||||
|
@ -285,11 +286,11 @@ exports.Lexer: class Lexer
|
|||
|
||||
# Sanitize a heredoc by escaping internal double quotes and erasing all
|
||||
# external indentation on the left-hand side.
|
||||
sanitize_heredoc: (doc) ->
|
||||
sanitize_heredoc: (doc, quote) ->
|
||||
indent: (doc.match(HEREDOC_INDENT) or ['']).sort()[0]
|
||||
doc.replace(new RegExp("^" +indent, 'gm'), '')
|
||||
.replace(MULTILINER, "\\n")
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(new RegExp(quote, 'g'), '\\"')
|
||||
|
||||
# A source of ambiguity in our grammar used to be parameter lists in function
|
||||
# definitions versus argument lists in function calls. Walk backwards, tagging
|
||||
|
|
|
@ -50,3 +50,19 @@ ok a is "a\n\n\nb c"
|
|||
a: '''more"than"one"quote'''
|
||||
|
||||
ok a is 'more"than"one"quote'
|
||||
|
||||
|
||||
val: 10
|
||||
|
||||
a: """
|
||||
basic heredoc $val
|
||||
on two lines
|
||||
"""
|
||||
|
||||
b: '''
|
||||
basic heredoc $val
|
||||
on two lines
|
||||
'''
|
||||
|
||||
ok a is "basic heredoc 10\non two lines"
|
||||
ok b is "basic heredoc \$val\non two lines"
|
||||
|
|
Loading…
Reference in New Issue