diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-02-17 23:08:58 -0800 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-02-17 23:08:58 -0800 |
| commit | 9b06a4506ed2ae222b19cafd184c66521b720581 (patch) | |
| tree | 7284c80d736823c33978dce1f217973d108a905f /src/parse.y | |
| parent | 7ba3275bf70fa62a34ea9015e2b03eefd180afe9 (diff) | |
| parent | e0f25b1fda0c9c67526885fafdabf35d4d4039b7 (diff) | |
| download | mruby-9b06a4506ed2ae222b19cafd184c66521b720581.tar.gz mruby-9b06a4506ed2ae222b19cafd184c66521b720581.zip | |
Merge pull request #850 from mattn/pluggable_regexp
Pluggable regexp
Diffstat (limited to 'src/parse.y')
| -rw-r--r-- | src/parse.y | 83 |
1 files changed, 79 insertions, 4 deletions
diff --git a/src/parse.y b/src/parse.y index 91fb1a8e8..9af8682c1 100644 --- a/src/parse.y +++ b/src/parse.y @@ -708,6 +708,13 @@ new_dsym(parser_state *p, node *a) return cons((node*)NODE_DSYM, new_dstr(p, a)); } +// (:str . (a . a)) +static node* +new_regx(parser_state *p, const char *p1, const char* p2) +{ + return cons((node*)NODE_REGX, cons((node*)p1, (node*)p2)); +} + // (:backref . n) static node* new_back_ref(parser_state *p, int n) @@ -743,13 +750,14 @@ call_bin_op(parser_state *p, node *recv, char *m, node *arg1) return new_call(p, recv, intern(m), list1(list1(arg1))); } +/* // (:match (a . b)) static node* match_op(parser_state *p, node *a, node *b) { return cons((node*)NODE_MATCH, cons((node*)a, (node*)b)); } - +*/ static void args_with_block(parser_state *p, node *a, node *b) @@ -1679,7 +1687,7 @@ arg : lhs '=' arg } | arg tMATCH arg { - $$ = match_op(p, $1, $3); + $$ = call_bin_op(p, $1, "=~", $3); #if 0 if (nd_type($1) == NODE_LIT && TYPE($1->nd_lit) == T_REGEXP) { $$ = reg_named_capture_assign($1->nd_lit, $$); @@ -2498,7 +2506,10 @@ string_interp : tSTRING_PART } ; -regexp : tREGEXP +regexp : tREGEXP_BEG tREGEXP + { + $$ = $2; + } ; symbol : basic_symbol @@ -3335,9 +3346,17 @@ read_escape(parser_state *p) return c; case 'b': /* backspace */ + if (p->regexp) { + tokadd(p, '\\'); + return 'b'; + } return '\010'; case 's': /* space */ + if (p->regexp) { + tokadd(p, '\\'); + return 's'; + } return ' '; case 'M': @@ -3375,6 +3394,9 @@ read_escape(parser_state *p) return '\0'; default: + if (p->regexp) { + tokadd(p, '\\'); + } return c; } } @@ -3385,7 +3407,6 @@ parse_string(parser_state *p, int term) int c; newtok(p); - while ((c = nextc(p)) != term) { if (c == -1) { yyerror(p, "unterminated string meets end of file"); @@ -3422,6 +3443,40 @@ parse_string(parser_state *p, int term) tokfix(p); p->lstate = EXPR_END; p->sterm = 0; + + if (p->regexp) { + int f = 0; + int c; + char* s; + s = strndup(tok(p), toklen(p)); + newtok(p); + while (c = nextc(p), ISALPHA(c)) { + switch (c) { + case 'i': f |= 1; break; + case 'x': f |= 2; break; + case 'm': f |= 4; break; + default: tokadd(p, c); break; + } + } + pushback(p, c); + if (toklen(p)) { + char msg[128]; + free(s); + tokfix(p); + snprintf(msg, sizeof(msg), "unknown regexp option %s - %s", + toklen(p) > 1 ? "s" : "", tok(p)); + yyerror(p, msg); + } + char flag[4] = {0}; + if (f & 1) strcat(flag, "i"); + if (f & 2) strcat(flag, "x"); + if (f & 4) strcat(flag, "m"); + yylval.nd = new_regx(p, s, strdup(flag)); + p->regexp = 0; + + return tREGEXP; + } + yylval.nd = new_str(p, tok(p), toklen(p)); return tSTRING; } @@ -4186,6 +4241,8 @@ parser_yylex(parser_state *p) #if 0 p->lex_strterm = new_strterm(p, str_regexp, '/', 0); #endif + p->regexp = 1; + p->sterm = '/'; return tREGEXP_BEG; } if ((c = nextc(p)) == '=') { @@ -4199,6 +4256,8 @@ parser_yylex(parser_state *p) #if 0 p->lex_strterm = new_strterm(p, str_regexp, '/', 0); #endif + p->regexp = 1; + p->sterm = '/'; return tREGEXP_BEG; } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { @@ -4381,6 +4440,8 @@ parser_yylex(parser_state *p) #if 0 p->lex_strterm = new_strterm(p, str_regexp, term, paren); #endif + p->regexp = 1; + p->sterm = '/'; return tREGEXP_BEG; case 's': @@ -5389,6 +5450,16 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("NODE_CONST %s\n", mrb_sym2name(mrb, sym(tree))); break; + case NODE_MATCH: + printf("NODE_MATCH:\n"); + dump_prefix(offset + 1); + printf("lhs:\n"); + parser_dump(mrb, tree->car, offset + 2); + dump_prefix(offset + 1); + printf("rhs:\n"); + parser_dump(mrb, tree->cdr, offset + 2); + break; + case NODE_BACK_REF: printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree); break; @@ -5428,6 +5499,10 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, tree, offset+1); break; + case NODE_REGX: + printf("NODE_REGX /%s/\n", (char*)tree->car->cdr->car); + break; + case NODE_SYM: printf("NODE_SYM :%s\n", mrb_sym2name(mrb, sym(tree))); break; |
