diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-03-21 23:25:03 -0700 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-03-21 23:25:03 -0700 |
| commit | ab7bd61596e0d684c27d08088e51cca092291751 (patch) | |
| tree | e7af45d8632180b7c6b56db0df7013b0a1ff1013 /src | |
| parent | f6646f44c2a33147b7f491d1551243c96f72ab25 (diff) | |
| parent | 4be161c43c4c22c9d3e081e30cf5964ab970a0a7 (diff) | |
| download | mruby-ab7bd61596e0d684c27d08088e51cca092291751.tar.gz mruby-ab7bd61596e0d684c27d08088e51cca092291751.zip | |
Merge pull request #1040 from mattn/backtick
xquote operator
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.c | 20 | ||||
| -rw-r--r-- | src/node.h | 2 | ||||
| -rw-r--r-- | src/parse.y | 55 |
3 files changed, 74 insertions, 3 deletions
diff --git a/src/codegen.c b/src/codegen.c index 7a91d597d..8fb1eebe9 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -2031,6 +2031,26 @@ codegen(codegen_scope *s, node *tree, int val) gen_literal_array(s, tree, TRUE, val); break; + case NODE_XSTR: + if (val) { + char *p = (char*)tree->car; + size_t len = (intptr_t)tree->cdr; + int ai = mrb_gc_arena_save(s->mrb); + int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6)); + int off = new_lit(s, mrb_str_new(s->mrb, p, len)); + + genop(s, MKOP_A(OP_OCLASS, cursp())); + genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + push(); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + pop(); + sym = new_sym(s, mrb_intern2(s->mrb, "`", 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); + mrb_gc_arena_restore(s->mrb, ai); + push(); + } + break; + case NODE_REGX: if (val) { char *p1 = (char*)tree->car; diff --git a/src/node.h b/src/node.h index 4f9db8265..df27c431f 100644 --- a/src/node.h +++ b/src/node.h @@ -65,6 +65,8 @@ enum node_type { NODE_SYM, NODE_STR, NODE_DSTR, + NODE_XSTR, + NODE_DXSTR, NODE_REGX, NODE_DREGX, NODE_DREGX_ONCE, diff --git a/src/parse.y b/src/parse.y index 8f1241d33..506e6e279 100644 --- a/src/parse.y +++ b/src/parse.y @@ -702,6 +702,20 @@ new_dstr(parser_state *p, node *a) return cons((node*)NODE_DSTR, a); } +// (:str . (s . len)) +static node* +new_xstr(parser_state *p, const char *s, int len) +{ + return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len)); +} + +// (:xstr . a) +static node* +new_dxstr(parser_state *p, node *a) +{ + return cons((node*)NODE_DXSTR, a); +} + // (:dsym . a) static node* new_dsym(parser_state *p, node *a) @@ -974,12 +988,12 @@ heredoc_end(parser_state *p) keyword__ENCODING__ %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL -%token <nd> tINTEGER tFLOAT tCHAR tREGEXP +%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP %token <nd> tSTRING tSTRING_PART tSTRING_MID %token <nd> tNTH_REF tBACK_REF %token <num> tREGEXP_END -%type <nd> singleton string string_rep string_interp regexp +%type <nd> singleton string string_rep string_interp xstring regexp %type <nd> literal numeric cpath symbol %type <nd> top_compstmt top_stmts top_stmt %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call @@ -1028,7 +1042,7 @@ heredoc_end(parser_state *p) %token tAMPER /* & */ %token tLAMBDA /* -> */ %token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG -%token tSTRING_BEG tSTRING_DVAR tLAMBEG +%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG %token <nd> tHEREDOC_BEG /* <<, <<- */ %token tHEREDOC_END tLITERAL_DELIM @@ -1936,6 +1950,7 @@ mrhs : args ',' arg_value primary : literal | string + | xstring | regexp | heredoc | var_ref @@ -2585,6 +2600,16 @@ string_interp : tSTRING_MID } ; +xstring : tXSTRING_BEG tXSTRING + { + $$ = $2; + } + | tXSTRING_BEG string_rep tXSTRING + { + $$ = new_dxstr(p, push($2, $3)); + } + ; + regexp : tREGEXP_BEG tREGEXP { $$ = $2; @@ -2985,6 +3010,8 @@ singleton : var_ref switch ((enum node_type)(int)(intptr_t)$3->car) { case NODE_STR: case NODE_DSTR: + case NODE_XSTR: + case NODE_DXSTR: case NODE_DREGX: case NODE_MATCH: case NODE_FLOAT: @@ -3641,6 +3668,11 @@ parse_string(parser_state *p) p->lstate = EXPR_END; end_strterm(p); + if (type & STR_FUNC_XQUOTE) { + yylval.nd = new_xstr(p, tok(p), toklen(p)); + return tXSTRING; + } + if (type & STR_FUNC_REGEXP) { int f = 0; int c; @@ -3988,6 +4020,10 @@ parser_yylex(parser_state *p) p->lex_strterm = new_strterm(p, str_squote, '\'', 0); return parse_string(p); + case '`': + p->lex_strterm = new_strterm(p, str_xquote, '`', 0); + return tXSTRING_BEG; + case '?': if (IS_END()) { p->lstate = EXPR_VALUE; @@ -4628,6 +4664,10 @@ parser_yylex(parser_state *p) p->lex_strterm = new_strterm(p, str_sword, term, paren); return tWORDS_BEG; + case 'x': + p->lex_strterm = new_strterm(p, str_xquote, term, paren); + return tXSTRING_BEG; + case 'r': p->lex_strterm = new_strterm(p, str_regexp, term, paren); return tREGEXP_BEG; @@ -5693,6 +5733,15 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, tree, offset+1); break; + case NODE_XSTR: + printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr); + break; + + case NODE_DXSTR: + printf("NODE_DXSTR\n"); + dump_recur(mrb, tree, offset+1); + break; + case NODE_REGX: printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr); break; |
