diff options
Diffstat (limited to 'mrbgems/mruby-compiler/core/parse.y')
| -rw-r--r-- | mrbgems/mruby-compiler/core/parse.y | 206 |
1 files changed, 158 insertions, 48 deletions
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 7838b6dfb..37d4d1bf1 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -10,13 +10,7 @@ # define YYDEBUG 1 #endif #define YYERROR_VERBOSE 1 -/* - * Force yacc to use our memory management. This is a little evil because - * the macros assume that "parser_state *p" is in scope - */ -#define YYMALLOC(n) mrb_malloc(p->mrb, (n)) -#define YYFREE(o) mrb_free(p->mrb, (o)) -#define YYSTACK_USE_ALLOCA 0 +#define YYSTACK_USE_ALLOCA 1 #include <ctype.h> #include <errno.h> @@ -76,6 +70,24 @@ typedef unsigned int stack_type; #define nint(x) ((node*)(intptr_t)(x)) #define intn(x) ((int)(intptr_t)(x)) +#if defined(MRB_COMPLEX_NUMBERS) || defined(MRB_RATIONAL_NUMBERS) + #define MRB_SUFFIX_SUPPORT + + #ifdef MRB_RATIONAL_NUMBERS + #define NUM_SUFFIX_R (1<<0) + #else + #define NUM_SUFFIX_R 0 + #endif + + #ifdef MRB_COMPLEX_NUMBERS + #define NUM_SUFFIX_I (1<<1) + #else + #define NUM_SUFFIX_I 0 + #endif + + #define NUM_SUFFIX_ALL (NUM_SUFFIX_R | NUM_SUFFIX_I) +#endif + static inline mrb_sym intern_cstr_gen(parser_state *p, const char *s) { @@ -842,19 +854,57 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b) return list4((node*)NODE_OP_ASGN, a, nsym(op), b); } +#ifdef MRB_COMPLEX_NUMBERS +static node* +new_imaginary(parser_state *p, node *imaginary) +{ + return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1); +} +#endif + +#ifdef MRB_RATIONAL_NUMBERS +static node* +new_rational(parser_state *p, node *rational) +{ + return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Rational"), list1(list1(rational)), 1); +} +#endif + /* (:int . i) */ static node* -new_int(parser_state *p, const char *s, int base) +new_int(parser_state *p, const char *s, int base, int suffix) { - return list3((node*)NODE_INT, (node*)strdup(s), nint(base)); + node* result = list3((node*)NODE_INT, (node*)strdup(s), nint(base)); +#ifdef MRB_RATIONAL_NUMBERS + if (suffix & NUM_SUFFIX_R) { + result = new_rational(p, result); + } +#endif +#ifdef MRB_COMPLEX_NUMBERS + if (suffix & NUM_SUFFIX_I) { + result = new_imaginary(p, result); + } +#endif + return result; } #ifndef MRB_WITHOUT_FLOAT /* (:float . i) */ static node* -new_float(parser_state *p, const char *s) +new_float(parser_state *p, const char *s, int suffix) { - return cons((node*)NODE_FLOAT, (node*)strdup(s)); + node* result = cons((node*)NODE_FLOAT, (node*)strdup(s)); +#ifdef MRB_RATIONAL_NUMBERS + if (suffix & NUM_SUFFIX_R) { + result = new_rational(p, result); + } +#endif +#ifdef MRB_COMPLEX_NUMBERS + if (suffix & NUM_SUFFIX_I) { + result = new_imaginary(p, result); + } +#endif + return result; } #endif @@ -913,40 +963,39 @@ concat_string(parser_state *p, node *a, node *b) } } } - else if (string_node_p(b)) { - /* a == NODE_DSTR && b == NODE_STR */ - - node *c; + else { + node *c; /* last node of a */ for (c = a; c->cdr != NULL; c = c->cdr) ; - if (string_node_p(c->car)) { - /* a->[..., NODE_STR] && b == NODE_STR */ - composite_string_node(p, c->car->cdr, b->cdr); - cons_free(b); - return a; - } - push(a, b); - return a; - } - else { - /* a == NODE_DSTR && b == NODE_DSTR */ + if (string_node_p(b)) { + /* a == NODE_DSTR && b == NODE_STR */ + if (string_node_p(c->car)) { + /* a->[..., NODE_STR] && b == NODE_STR */ + composite_string_node(p, c->car->cdr, b->cdr); + cons_free(b); + return a; + } - node *c, *d; - for (c = a; c->cdr != NULL; c = c->cdr) ; - if (string_node_p(c->car) && string_node_p(b->cdr->car)) { - /* a->[..., NODE_STR] && b->[NODE_STR, ...] */ - d = b->cdr; - cons_free(b); - composite_string_node(p, c->car->cdr, d->car->cdr); - cons_free(d->car); - c->cdr = d->cdr; - cons_free(d); + push(a, b); return a; } else { - c->cdr = b->cdr; - cons_free(b); - return a; + /* a == NODE_DSTR && b == NODE_DSTR */ + if (string_node_p(c->car) && string_node_p(b->cdr->car)) { + /* a->[..., NODE_STR] && b->[NODE_STR, ...] */ + node *d = b->cdr; + cons_free(b); + composite_string_node(p, c->car->cdr, d->car->cdr); + cons_free(d->car); + c->cdr = d->cdr; + cons_free(d); + return a; + } + else { + c->cdr = b->cdr; + cons_free(b); + return a; + } } } @@ -3193,7 +3242,7 @@ var_ref : variable char buf[16]; dump_int(p->lineno, buf); - $$ = new_int(p, buf, 10); + $$ = new_int(p, buf, 10, 0); } | keyword__ENCODING__ { @@ -4521,6 +4570,45 @@ parse_string(parser_state *p) return tSTRING; } +#ifdef MRB_SUFFIX_SUPPORT +static int +number_literal_suffix(parser_state *p, int mask) +{ + int c, result = 0; + node *list = 0; + int column = p->column; + + while ((c = nextc(p)) != -1) { + list = push(list, (node*)(intptr_t)c); + + if ((mask & NUM_SUFFIX_I) && c == 'i') { + result |= (mask & NUM_SUFFIX_I); + mask &= ~NUM_SUFFIX_I; + /* r after i, rational of complex is disallowed */ + mask &= ~NUM_SUFFIX_R; + continue; + } + if ((mask & NUM_SUFFIX_R) && c == 'r') { + result |= (mask & NUM_SUFFIX_R); + mask &= ~NUM_SUFFIX_R; + continue; + } + if (!ISASCII(c) || ISALPHA(c) || c == '_') { + p->column = column; + if (p->pb) { + p->pb = append((node*)list, p->pb); + } + else { + p->pb = list; + } + return 0; + } + pushback(p, c); + break; + } + return result; +} +#endif static int heredoc_identifier(parser_state *p) @@ -5095,6 +5183,7 @@ parser_yylex(parser_state *p) case '5': case '6': case '7': case '8': case '9': { int is_float, seen_point, seen_e, nondigit; + int suffix = 0; is_float = seen_point = seen_e = nondigit = 0; p->lstate = EXPR_ENDARG; @@ -5128,7 +5217,10 @@ parser_yylex(parser_state *p) no_digits(); } else if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 16); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 16, suffix); return tINTEGER; } if (c == 'b' || c == 'B') { @@ -5152,7 +5244,10 @@ parser_yylex(parser_state *p) no_digits(); } else if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 2); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 2, suffix); return tINTEGER; } if (c == 'd' || c == 'D') { @@ -5176,7 +5271,10 @@ parser_yylex(parser_state *p) no_digits(); } else if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 10); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 10, suffix); return tINTEGER; } if (c == '_') { @@ -5209,7 +5307,10 @@ parser_yylex(parser_state *p) pushback(p, c); tokfix(p); if (nondigit) goto trailing_uc; - pylval.nd = new_int(p, tok(p), 8); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 8, suffix); return tINTEGER; } if (nondigit) { @@ -5226,7 +5327,10 @@ parser_yylex(parser_state *p) } else { pushback(p, c); - pylval.nd = new_int(p, "0", 10); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, "0", 10, suffix); return tINTEGER; } } @@ -5300,7 +5404,7 @@ parser_yylex(parser_state *p) if (is_float) { #ifdef MRB_WITHOUT_FLOAT yywarning(p, "floating point numbers are not supported"); - pylval.nd = new_int(p, "0", 10); + pylval.nd = new_int(p, "0", 10, 0); return tINTEGER; #else double d; @@ -5315,11 +5419,17 @@ parser_yylex(parser_state *p) yywarning_s(p, "float out of range", tok(p)); errno = 0; } - pylval.nd = new_float(p, tok(p)); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_float(p, tok(p), suffix); return tFLOAT; #endif } - pylval.nd = new_int(p, tok(p), 10); + #ifdef MRB_SUFFIX_SUPPORT + suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); + #endif + pylval.nd = new_int(p, tok(p), 10, suffix); return tINTEGER; } |
