1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

Changed multiline string literals

This commit is contained in:
xixixao 2013-11-18 04:32:15 +00:00
parent 9e9c83f788
commit efe8c68c75
5 changed files with 68 additions and 25 deletions

View file

@ -96,8 +96,7 @@
return new Value($1); return new Value($1);
}), o('ObjAssignable : Expression', function() { }), o('ObjAssignable : Expression', function() {
return new Assign(LOC(1)(new Value($1)), $3, 'object'); return new Assign(LOC(1)(new Value($1)), $3, 'object');
}), o('ObjAssignable :\ }), o('ObjAssignable : INDENT Expression OUTDENT', function() {
INDENT Expression OUTDENT', function() {
return new Assign(LOC(1)(new Value($1)), $4, 'object'); return new Assign(LOC(1)(new Value($1)), $4, 'object');
}), o('Comment') }), o('Comment')
], ],
@ -573,14 +572,11 @@
} else { } else {
return new Op($2, $1, $3); return new Op($2, $1, $3);
} }
}), o('SimpleAssignable COMPOUND_ASSIGN\ }), o('SimpleAssignable COMPOUND_ASSIGN Expression', function() {
Expression', function() {
return new Assign($1, $3, $2); return new Assign($1, $3, $2);
}), o('SimpleAssignable COMPOUND_ASSIGN\ }), o('SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT', function() {
INDENT Expression OUTDENT', function() {
return new Assign($1, $4, $2); return new Assign($1, $4, $2);
}), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR\ }), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression', function() {
Expression', function() {
return new Assign($1, $4, $2); return new Assign($1, $4, $2);
}), o('SimpleAssignable EXTENDS Expression', function() { }), o('SimpleAssignable EXTENDS Expression', function() {
return new Extends($1, $3); return new Extends($1, $3);

View file

@ -173,7 +173,7 @@
return 0; return 0;
} }
string = match[0]; string = match[0];
this.token('STRING', string.replace(MULTILINER, '\\\n'), 0, string.length); this.token('STRING', this.trimAndEscapeLines(string), 0, string.length);
break; break;
case '"': case '"':
if (!(string = this.balancedString(this.chunk, '"'))) { if (!(string = this.balancedString(this.chunk, '"'))) {
@ -185,7 +185,7 @@
lexedLength: string.length lexedLength: string.length
}); });
} else { } else {
this.token('STRING', this.escapeLines(string), 0, string.length); this.token('STRING', this.trimAndEscapeLines(string), 0, string.length);
} }
break; break;
default: default:
@ -762,16 +762,24 @@
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === '?::' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS'); return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === '?::' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
}; };
Lexer.prototype.trimAndEscapeLines = function(str) {
return this.escapeLines(str.replace(/^(.)\s*\n\s*/, '$1').replace(/\s*\n\s*(.)$/, '$1'));
};
Lexer.prototype.escapeLines = function(str, heredoc) { Lexer.prototype.escapeLines = function(str, heredoc) {
return str.replace(MULTILINER, heredoc ? '\\n' : ''); if (heredoc) {
return str.replace(MULTILINER, '\\n');
} else {
return str.replace(/\\\n\s*/g, '').replace(/\s*\n\s*/g, ' ');
}
}; };
Lexer.prototype.makeString = function(body, quote, heredoc) { Lexer.prototype.makeString = function(body, quote, heredoc) {
if (!body) { if (!body) {
return quote + quote; return quote + quote;
} }
body = body.replace(/\\([\s\S])/g, function(match, contents) { body = body.replace(/\\([^])/g, function(match, contents) {
if (contents === '\n' || contents === quote) { if (contents === quote || heredoc && contents === '\n') {
return contents; return contents;
} else { } else {
return match; return match;
@ -852,7 +860,7 @@
MULTI_DENT = /^(?:\n[^\n\S]*)+/; MULTI_DENT = /^(?:\n[^\n\S]*)+/;
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/; SIMPLESTR = /^'[^\\']*(?:\\[^][^\\']*)*'/;
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/; JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;

View file

@ -190,13 +190,13 @@ exports.Lexer = class Lexer
when "'" when "'"
return 0 unless match = SIMPLESTR.exec @chunk return 0 unless match = SIMPLESTR.exec @chunk
string = match[0] string = match[0]
@token 'STRING', string.replace(MULTILINER, '\\\n'), 0, string.length @token 'STRING', @trimAndEscapeLines(string), 0, string.length
when '"' when '"'
return 0 unless string = @balancedString @chunk, '"' return 0 unless string = @balancedString @chunk, '"'
if 0 < string.indexOf '#{', 1 if 0 < string.indexOf '#{', 1
@interpolateString string[1...-1], strOffset: 1, lexedLength: string.length @interpolateString string[1...-1], strOffset: 1, lexedLength: string.length
else else
@token 'STRING', @escapeLines(string), 0, string.length @token 'STRING', @trimAndEscapeLines(string), 0, string.length
else else
return 0 return 0
if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string
@ -684,15 +684,23 @@ exports.Lexer = class Lexer
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION' @tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
'COMPARE', 'LOGIC', 'THROW', 'EXTENDS'] 'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
# Remove newlines from beginning and end of string literals.
# `str` includes quotes.
trimAndEscapeLines: (str) ->
@escapeLines str.replace(/^(.)\s*\n\s*/, '$1').replace(/\s*\n\s*(.)$/, '$1')
# Converts newlines for string literals. # Converts newlines for string literals.
escapeLines: (str, heredoc) -> escapeLines: (str, heredoc) ->
str.replace MULTILINER, if heredoc then '\\n' else '' if heredoc
str.replace MULTILINER, '\\n'
else
str.replace(/\\\n\s*/g, '').replace(/\s*\n\s*/g, ' ')
# Constructs a string token by escaping quotes and newlines. # Constructs a string token by escaping quotes and newlines.
makeString: (body, quote, heredoc) -> makeString: (body, quote, heredoc) ->
return quote + quote unless body return quote + quote unless body
body = body.replace /\\([\s\S])/g, (match, contents) -> body = body.replace /\\([^])/g, (match, contents) ->
if contents in ['\n', quote] then contents else match if contents is quote or heredoc and contents is '\n' then contents else match
body = body.replace /// #{quote} ///g, '\\$&' body = body.replace /// #{quote} ///g, '\\$&'
quote + @escapeLines(body, heredoc) + quote quote + @escapeLines(body, heredoc) + quote
@ -787,7 +795,7 @@ CODE = /^[-=]>/
MULTI_DENT = /^(?:\n[^\n\S]*)+/ MULTI_DENT = /^(?:\n[^\n\S]*)+/
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/ SIMPLESTR = /^'[^\\']*(?:\\[^][^\\']*)*'/
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/ JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/

View file

@ -30,7 +30,7 @@ eq "#{6 / 2}", '3'
eq "#{6 / 2}#{6 / 2}", '33' # parsed as division eq "#{6 / 2}#{6 / 2}", '33' # parsed as division
eq "#{6 + /2}#{6/ + 2}", '6/2}#{6/2' # parsed as a regex eq "#{6 + /2}#{6/ + 2}", '6/2}#{6/2' # parsed as a regex
eq "#{6/2} eq "#{6/2}
#{6/2}", '3 3' # newline cannot be part of a regex, so it's division #{6/2}", '3 3' # newline cannot be part of a regex, so it's division
eq "#{/// "'/'"/" ///}", '/"\'\\/\'"\\/"/' # heregex, stuffed with spicy characters eq "#{/// "'/'"/" ///}", '/"\'\\/\'"\\/"/' # heregex, stuffed with spicy characters
eq "#{/\\'/}", "/\\\\'/" eq "#{/\\'/}", "/\\\\'/"

View file

@ -18,6 +18,38 @@ eq "four five", 'four
five' five'
test "#3229, multine strings", ->
eq 'one
two', 'one two'
eq "one
two", 'one two'
eq 'a \
b\
c \
d', 'a bc d'
eq "a \
b\
c \
d", 'a bc d'
eq 'one
two', 'one two'
eq "one
two", 'one two'
eq '
a
b
', 'a b'
eq "
a
b
", 'a b'
eq "interpolation #{1}
follows #{2} \
too #{3}\
!", 'interpolation 1 follows 2 too 3!'
#647 #647
eq "''Hello, World\\''", ''' eq "''Hello, World\\''", '''
'\'Hello, World\\\'' '\'Hello, World\\\''
@ -91,10 +123,9 @@ ok a is "one\ntwo\n"
eq ''' line 0 eq ''' line 0
should not be relevant should not be relevant
to the indent level to the indent level
''', ' ''', ' line 0\n\
line 0\n should not be relevant\n \
should not be relevant\n to the indent level
to the indent level
' '
eq ''' '\\\' ''', " '\\' " eq ''' '\\\' ''', " '\\' "