diff options
| author | Yukihiro Matz Matsumoto <[email protected]> | 2013-03-02 15:13:52 +0900 |
|---|---|---|
| committer | Yukihiro Matz Matsumoto <[email protected]> | 2013-03-02 15:13:52 +0900 |
| commit | 0c9d42e08074538abde910419e9f08297054f47b (patch) | |
| tree | 8e2fb85ffcf0218cac86e1ff56c07c34f1307f56 /src | |
| parent | 8f5a09ba159f4175048b8721d689f43effc6388b (diff) | |
| download | mruby-0c9d42e08074538abde910419e9f08297054f47b.tar.gz mruby-0c9d42e08074538abde910419e9f08297054f47b.zip | |
string interpolation in regex
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.c | 64 | ||||
| -rw-r--r-- | src/parse.y | 20 |
2 files changed, 81 insertions, 3 deletions
diff --git a/src/codegen.c b/src/codegen.c index 88bce7dac..ff7e87c28 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1935,7 +1935,7 @@ codegen(codegen_scope *s, node *tree, int val) int ai = mrb_gc_arena_save(s->mrb); int sym = new_sym(s, mrb_intern(s->mrb, REGEXP_CLASS)); int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1))); - int n = 1; + int argc = 1; genop(s, MKOP_A(OP_OCLASS, cursp())); genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); @@ -1945,15 +1945,73 @@ codegen(codegen_scope *s, node *tree, int val) push(); off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2))); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - n++; + argc++; + pop(); + } + pop(); + sym = new_sym(s, mrb_intern(s->mrb, "compile")); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); + mrb_gc_arena_restore(s->mrb, ai); + push(); + } + break; + + case NODE_DREGX: + if (val) { + node *n = tree->car; + int ai = mrb_gc_arena_save(s->mrb); + int sym = new_sym(s, mrb_intern(s->mrb, REGEXP_CLASS)); + int argc = 1; + int off; + char *p; + + genop(s, MKOP_A(OP_OCLASS, cursp())); + genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + push(); + codegen(s, n->car, VAL); + n = n->cdr; + while (n) { + codegen(s, n->car, VAL); + pop(); pop(); + genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1)); + push(); + n = n->cdr; + } + n = tree->cdr->cdr; + if (n->car) { + p = (char*)n->car; + off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p))); + codegen(s, tree->car, VAL); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + pop(); + genop(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1)); + } + if (n->cdr) { + char *p2 = (char*)n->cdr; + int off; + + push(); + off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2))); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + argc++; pop(); } pop(); sym = new_sym(s, mrb_intern(s->mrb, "compile")); - genop(s, MKOP_ABC(OP_SEND, cursp(), sym, n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); } + else { + node *n = tree->car; + + while (n) { + if ((intptr_t)n->car->car != NODE_STR) { + codegen(s, n->car, NOVAL); + } + n = n->cdr; + } + } break; case NODE_SYM: diff --git a/src/parse.y b/src/parse.y index 2c5690ea3..7bca4a4d6 100644 --- a/src/parse.y +++ b/src/parse.y @@ -715,6 +715,13 @@ new_regx(parser_state *p, const char *p1, const char* p2) return cons((node*)NODE_REGX, cons((node*)p1, (node*)p2)); } +// (:dregx . a) +static node* +new_dregx(parser_state *p, node *a, node *b) +{ + return cons((node*)NODE_DREGX, cons(a, b)); +} + // (:backref . n) static node* new_back_ref(parser_state *p, int n) @@ -2510,6 +2517,10 @@ regexp : tREGEXP_BEG tREGEXP { $$ = $2; } + | tREGEXP_BEG string_interp tREGEXP + { + $$ = new_dregx(p, $2, $3); + } ; symbol : basic_symbol @@ -5502,6 +5513,15 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr); break; + case NODE_DREGX: + printf("NODE_DREGX\n"); + dump_recur(mrb, tree->car, offset+1); + dump_prefix(offset); + printf("tail: %s\n", (char*)tree->cdr->cdr->car); + dump_prefix(offset); + printf("opt: %s\n", (char*)tree->cdr->cdr->cdr); + break; + case NODE_SYM: printf("NODE_SYM :%s\n", mrb_sym2name(mrb, sym(tree))); break; |
