summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-10-26 04:24:29 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-10-26 04:24:29 +0000
commite7576a777c32fdf04f6e014a225025b5e2b45553 (patch)
treefb08221fb8510d2781f897dd00fbc4a028e5eaf2 /parse.y
parente6c5b9f30840ae985c4bdcb91435e9c2c06fb7ef (diff)
parse.y: concatenated literals
* parse.y (literal_concat_gen): merge fixed strings across concatenated literals, after an interpolation. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37331 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y22
1 files changed, 21 insertions, 1 deletions
diff --git a/parse.y b/parse.y
index 7eaab6b1b8..8549cb1378 100644
--- a/parse.y
+++ b/parse.y
@@ -8246,6 +8246,8 @@ static NODE *
literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
{
enum node_type htype;
+ NODE *headlast;
+ VALUE lit;
if (!head) return tail;
if (!tail) return head;
@@ -8254,11 +8256,20 @@ literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
if (htype == NODE_EVSTR) {
NODE *node = NEW_DSTR(Qnil);
head = list_append(node, head);
+ htype = NODE_DSTR;
}
switch (nd_type(tail)) {
case NODE_STR:
+ if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
+ nd_type(headlast) == NODE_STR) {
+ htype = NODE_STR;
+ lit = headlast->nd_lit;
+ }
+ else {
+ lit = head->nd_lit;
+ }
if (htype == NODE_STR) {
- if (!literal_concat0(parser, head->nd_lit, tail->nd_lit)) {
+ if (!literal_concat0(parser, lit, tail->nd_lit)) {
error:
rb_gc_force_recycle((VALUE)head);
rb_gc_force_recycle((VALUE)tail);
@@ -8280,11 +8291,20 @@ literal_concat_gen(struct parser_params *parser, NODE *head, NODE *tail)
head = tail;
}
else if (NIL_P(tail->nd_lit)) {
+ append:
head->nd_alen += tail->nd_alen - 1;
head->nd_next->nd_end->nd_next = tail->nd_next;
head->nd_next->nd_end = tail->nd_next->nd_end;
rb_gc_force_recycle((VALUE)tail);
}
+ else if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
+ nd_type(headlast) == NODE_STR) {
+ lit = headlast->nd_lit;
+ if (!literal_concat0(parser, lit, tail->nd_lit))
+ goto error;
+ tail->nd_lit = Qnil;
+ goto append;
+ }
else {
nd_set_type(tail, NODE_ARRAY);
tail->nd_head = NEW_STR(tail->nd_lit);