summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormattn <[email protected]>2013-03-21 19:45:47 +0900
committermattn <[email protected]>2013-03-21 19:45:47 +0900
commit1ab4dbcbf365d0ef75d08d28478c06fcf8628afe (patch)
treedf456fe8f936e1d5c02549402c32aad9caff9184
parent605035bc4261f25063ecf77765b9f844b6e98357 (diff)
downloadmruby-1ab4dbcbf365d0ef75d08d28478c06fcf8628afe.tar.gz
mruby-1ab4dbcbf365d0ef75d08d28478c06fcf8628afe.zip
Backtick operation
-rw-r--r--include/mruby/compile.h2
-rw-r--r--src/codegen.c20
-rw-r--r--src/node.h2
-rw-r--r--src/parse.y55
4 files changed, 76 insertions, 3 deletions
diff --git a/include/mruby/compile.h b/include/mruby/compile.h
index 8b0743fa3..0df0d3d0a 100644
--- a/include/mruby/compile.h
+++ b/include/mruby/compile.h
@@ -65,6 +65,7 @@ struct mrb_parser_message {
#define STR_FUNC_SYMBOL 0x10
#define STR_FUNC_ARRAY 0x20
#define STR_FUNC_HEREDOC 0x40
+#define STR_FUNC_XQUOTE 0x80
enum mrb_string_type {
str_not_parsing = (0),
@@ -77,6 +78,7 @@ enum mrb_string_type {
str_ssymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY),
str_dsymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
str_heredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC),
+ str_xquote = (STR_FUNC_PARSING|STR_FUNC_XQUOTE|STR_FUNC_EXPAND),
};
/* heredoc structure */
diff --git a/src/codegen.c b/src/codegen.c
index 7a91d597d..1e4802d01 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_intern(s->mrb, "Kernel"));
+ 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_intern(s->mrb, "__backtick__"));
+ 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 ee95cfb73..9b2ddf9ed 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:
@@ -3648,6 +3675,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;
@@ -3995,6 +4027,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;
@@ -4635,6 +4671,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;
@@ -5700,6 +5740,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;