Backtick operation

This commit is contained in:
mattn
2013-03-21 19:45:47 +09:00
parent 605035bc42
commit 1ab4dbcbf3
4 changed files with 76 additions and 3 deletions
+2
View File
@@ -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 */
+20
View File
@@ -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;
+2
View File
@@ -65,6 +65,8 @@ enum node_type {
NODE_SYM,
NODE_STR,
NODE_DSTR,
NODE_XSTR,
NODE_DXSTR,
NODE_REGX,
NODE_DREGX,
NODE_DREGX_ONCE,
+52 -3
View File
@@ -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;