summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-compiler')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c119
-rw-r--r--mrbgems/mruby-compiler/core/keywords3
-rw-r--r--mrbgems/mruby-compiler/core/lex.def110
-rw-r--r--mrbgems/mruby-compiler/core/parse.y517
4 files changed, 531 insertions, 218 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index b3659863b..d397ace8c 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -8,6 +8,7 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <mruby.h>
#include <mruby/compile.h>
#include <mruby/proc.h>
@@ -61,7 +62,7 @@ typedef struct scope {
struct loopinfo *loop;
int ensure_level;
- char const *filename;
+ mrb_sym filename_sym;
uint16_t lineno;
mrb_code *iseq;
@@ -101,12 +102,14 @@ codegen_error(codegen_scope *s, const char *message)
while (s->prev) {
codegen_scope *tmp = s->prev;
mrb_free(s->mrb, s->iseq);
+ mrb_free(s->mrb, s->lines);
mrb_pool_close(s->mpool);
s = tmp;
}
#ifndef MRB_DISABLE_STDIO
- if (s->filename && s->lineno) {
- fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
+ if (s->filename_sym && s->lineno) {
+ const char *filename = mrb_sym2name_len(s->mrb, s->filename_sym, NULL);
+ fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
}
else {
fprintf(stderr, "codegen error: %s\n", message);
@@ -270,8 +273,7 @@ genop_W(codegen_scope *s, mrb_code i, uint32_t a)
#define NOVAL 0
#define VAL 1
-//static
-mrb_bool
+static mrb_bool
no_optimize(codegen_scope *s)
{
if (s && s->parser && s->parser->no_optimize)
@@ -289,7 +291,7 @@ on_eval(codegen_scope *s)
}
struct mrb_insn_data
-mrb_decode_insn(mrb_code *pc)
+mrb_decode_insn(const mrb_code *pc)
{
struct mrb_insn_data data = { 0 };
mrb_code insn = READ_B();
@@ -566,9 +568,12 @@ new_lit(codegen_scope *s, mrb_value val)
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
for (i=0; i<s->irep->plen; i++) {
+ mrb_float f1, f2;
pv = &s->irep->pool[i];
if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
- if (mrb_float(*pv) == mrb_float(val)) return i;
+ f1 = mrb_float(*pv);
+ f2 = mrb_float(val);
+ if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
}
break;
#endif
@@ -730,7 +735,10 @@ lambda_body(codegen_scope *s, node *tree, int blk)
lp->pc0 = new_label(s);
}
tree = tree->cdr;
- if (tree->car) {
+ if (tree->car == NULL) {
+ genop_W(s, OP_ENTER, 0);
+ }
+ else {
mrb_aspec a;
int ma, oa, ra, pa, ka, kd, ba;
int pos, i;
@@ -816,8 +824,8 @@ lambda_body(codegen_scope *s, node *tree, int blk)
mrb_assert(nint(kwd->car) == NODE_KW_ARG);
if (def_arg) {
- genop_2(s, OP_KEY_P, cursp(), new_sym(s, kwd_sym));
- jmpif_key_p = genjmp2(s, OP_JMPIF, cursp(), 0, 0);
+ genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
+ jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
codegen(s, def_arg, VAL);
pop();
gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
@@ -948,7 +956,12 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
}
else {
pop_n(n);
- genop_2(s, OP_ARRAY, cursp(), n);
+ if (n == 0 && is_splat) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
+ genop_2(s, OP_ARRAY, cursp(), n);
+ }
push();
codegen(s, t->car, VAL);
pop(); pop();
@@ -1392,13 +1405,14 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_error(s, "too complex expression");
}
if (s->irep && s->filename_index != tree->filename_index) {
- const char *filename = mrb_parser_get_filename(s->parser, s->filename_index);
+ mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
+ const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
filename, s->lines, s->debug_start_pos, s->pc);
s->debug_start_pos = s->pc;
s->filename_index = tree->filename_index;
- s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
+ s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
}
nt = nint(tree->car);
@@ -1564,18 +1578,17 @@ codegen(codegen_scope *s, node *tree, int val)
}
codegen(s, tree->car, VAL);
pop();
- pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
-
- codegen(s, tree->cdr->car, val);
- if (elsepart) {
- if (val) pop();
- pos2 = genjmp(s, OP_JMP, 0);
- dispatch(s, pos1);
- codegen(s, elsepart, val);
- dispatch(s, pos2);
- }
- else {
- if (val) {
+ if (val || tree->cdr->car) {
+ pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
+ codegen(s, tree->cdr->car, val);
+ if (elsepart) {
+ if (val) pop();
+ pos2 = genjmp(s, OP_JMP, 0);
+ dispatch(s, pos1);
+ codegen(s, elsepart, val);
+ dispatch(s, pos2);
+ }
+ else if (val) {
pop();
pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1);
@@ -1587,6 +1600,17 @@ codegen(codegen_scope *s, node *tree, int val)
dispatch(s, pos1);
}
}
+ else { /* empty then-part */
+ if (elsepart) {
+ pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
+ codegen(s, elsepart, val);
+ dispatch(s, pos1);
+ }
+ else if (val) {
+ genop_1(s, OP_LOADNIL, cursp());
+ push();
+ }
+ }
}
break;
@@ -2350,13 +2374,9 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_BACK_REF:
if (val) {
- char buf[3];
- int sym;
+ char buf[] = {'$', nchar(tree)};
+ int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
- buf[0] = '$';
- buf[1] = nchar(tree);
- buf[2] = 0;
- sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
genop_2(s, OP_GETGV, cursp(), sym);
push();
}
@@ -2368,7 +2388,7 @@ codegen(codegen_scope *s, node *tree, int val)
mrb_value str;
int sym;
- str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
+ str = mrb_format(mrb, "$%d", nint(tree));
sym = new_sym(s, mrb_intern_str(mrb, str));
genop_2(s, OP_GETGV, cursp(), sym);
push();
@@ -2802,7 +2822,10 @@ codegen(codegen_scope *s, node *tree, int val)
idx = new_sym(s, nsym(tree->car->cdr));
genop_2(s, OP_CLASS, cursp(), idx);
body = tree->cdr->cdr->car;
- if (!(nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL)) {
+ if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
idx = scope_body(s, body, val);
genop_2(s, OP_EXEC, cursp(), idx);
}
@@ -2830,8 +2853,11 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
idx = new_sym(s, nsym(tree->car->cdr));
genop_2(s, OP_MODULE, cursp(), idx);
- if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
- tree->cdr->car->cdr->cdr == NULL)) {
+ if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
+ tree->cdr->car->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
idx = scope_body(s, tree->cdr->car, val);
genop_2(s, OP_EXEC, cursp(), idx);
}
@@ -2848,8 +2874,11 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
genop_1(s, OP_SCLASS, cursp());
- if (!(nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
- tree->cdr->car->cdr->cdr == NULL)) {
+ if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
+ tree->cdr->car->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
idx = scope_body(s, tree->cdr->car, val);
genop_2(s, OP_EXEC, cursp(), idx);
}
@@ -2978,15 +3007,15 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
}
p->ai = mrb_gc_arena_save(mrb);
- p->filename = prev->filename;
- if (p->filename) {
+ p->filename_sym = prev->filename_sym;
+ if (p->filename_sym) {
p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
}
p->lineno = prev->lineno;
/* debug setting */
p->debug_start_pos = 0;
- if (p->filename) {
+ if (p->filename_sym) {
mrb_debug_info_alloc(mrb, p->irep);
}
else {
@@ -3006,6 +3035,9 @@ scope_finish(codegen_scope *s)
mrb_state *mrb = s->mrb;
mrb_irep *irep = s->irep;
+ if (s->nlocals >= 0x3ff) {
+ codegen_error(s, "too many local variables");
+ }
irep->flags = 0;
if (s->iseq) {
irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
@@ -3014,8 +3046,9 @@ scope_finish(codegen_scope *s)
irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
- if (s->filename) {
- const char *filename = mrb_parser_get_filename(s->parser, s->filename_index);
+ if (s->filename_sym) {
+ mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
+ const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
filename, s->lines, s->debug_start_pos, s->pc);
@@ -3124,7 +3157,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
}
scope->mrb = mrb;
scope->parser = p;
- scope->filename = p->filename;
+ scope->filename_sym = p->filename_sym;
scope->filename_index = p->current_filename_index;
MRB_TRY(&scope->jmp) {
diff --git a/mrbgems/mruby-compiler/core/keywords b/mrbgems/mruby-compiler/core/keywords
index 9cb86608c..a60ecd10a 100644
--- a/mrbgems/mruby-compiler/core/keywords
+++ b/mrbgems/mruby-compiler/core/keywords
@@ -1,8 +1,5 @@
%{
struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
-const struct kwtable *mrb_reserved_word(const char *, unsigned int);
-static const struct kwtable *reserved_word(const char *, unsigned int);
-#define mrb_reserved_word(str, len) reserved_word(str, len)
%}
struct kwtable;
diff --git a/mrbgems/mruby-compiler/core/lex.def b/mrbgems/mruby-compiler/core/lex.def
index 2ff266481..872bf40c1 100644
--- a/mrbgems/mruby-compiler/core/lex.def
+++ b/mrbgems/mruby-compiler/core/lex.def
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.4 */
+/* ANSI-C code produced by gperf version 3.1 */
/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' /home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -25,16 +25,13 @@
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
/* The character set is not based on ISO-646. */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <[email protected]>."
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <[email protected]>."
#endif
#line 1 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
-const struct kwtable *mrb_reserved_word(const char *, unsigned int);
-static const struct kwtable *reserved_word(const char *, unsigned int);
-#define mrb_reserved_word(str, len) reserved_word(str, len)
-#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 5 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
struct kwtable;
#define TOTAL_KEYWORDS 40
@@ -52,7 +49,7 @@ inline
#endif
#endif
static unsigned int
-hash (const char *str, unsigned int len)
+hash (register const char *str, register size_t len)
{
static const unsigned char asso_values[] =
{
@@ -83,7 +80,7 @@ hash (const char *str, unsigned int len)
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51
};
- int hval = len;
+ register unsigned int hval = len;
switch (hval)
{
@@ -98,109 +95,103 @@ hash (const char *str, unsigned int len)
return hval + asso_values[(unsigned char)str[len - 1]];
}
-#ifdef __GNUC__
-__inline
-#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-#endif
const struct kwtable *
-mrb_reserved_word (const char *str, unsigned int len)
+mrb_reserved_word (register const char *str, register size_t len)
{
static const struct kwtable wordlist[] =
{
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"break", {keyword_break, keyword_break}, EXPR_MID},
-#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"else", {keyword_else, keyword_else}, EXPR_BEG},
-#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"nil", {keyword_nil, keyword_nil}, EXPR_END},
-#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
-#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"end", {keyword_end, keyword_end}, EXPR_END},
-#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"then", {keyword_then, keyword_then}, EXPR_BEG},
-#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"not", {keyword_not, keyword_not}, EXPR_ARG},
-#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"false", {keyword_false, keyword_false}, EXPR_END},
-#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"self", {keyword_self, keyword_self}, EXPR_END},
-#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
-#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
-#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"true", {keyword_true, keyword_true}, EXPR_END},
-#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"until", {keyword_until, modifier_until}, EXPR_VALUE},
-#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
-#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"return", {keyword_return, keyword_return}, EXPR_MID},
-#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"def", {keyword_def, keyword_def}, EXPR_FNAME},
-#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"and", {keyword_and, keyword_and}, EXPR_VALUE},
-#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"do", {keyword_do, keyword_do}, EXPR_BEG},
-#line 49 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
-#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"for", {keyword_for, keyword_for}, EXPR_VALUE},
-#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
-#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"or", {keyword_or, keyword_or}, EXPR_VALUE},
-#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"in", {keyword_in, keyword_in}, EXPR_VALUE},
-#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"when", {keyword_when, keyword_when}, EXPR_VALUE},
-#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"retry", {keyword_retry, keyword_retry}, EXPR_END},
-#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"if", {keyword_if, modifier_if}, EXPR_VALUE},
-#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"case", {keyword_case, keyword_case}, EXPR_VALUE},
-#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"redo", {keyword_redo, keyword_redo}, EXPR_END},
-#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"next", {keyword_next, keyword_next}, EXPR_MID},
-#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"super", {keyword_super, keyword_super}, EXPR_ARG},
-#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"module", {keyword_module, keyword_module}, EXPR_VALUE},
-#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
-#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 9 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
-#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
-#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 7 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
-#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"END", {keyword_END, keyword_END}, EXPR_END},
-#line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
-#line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
{""},
-#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"class", {keyword_class, keyword_class}, EXPR_CLASS},
{""}, {""},
-#line 48 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"while", {keyword_while, modifier_while}, EXPR_VALUE}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
- int key = hash (str, len);
+ register unsigned int key = hash (str, len);
- if (key <= MAX_HASH_VALUE && key >= 0)
+ if (key <= MAX_HASH_VALUE)
{
- const char *s = wordlist[key].name;
+ register const char *s = wordlist[key].name;
if (*str == *s && !strcmp (str + 1, s + 1))
return &wordlist[key];
@@ -208,4 +199,5 @@ mrb_reserved_word (const char *str, unsigned int len)
}
return 0;
}
-#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index d143344c3..d26a29a27 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)
{
@@ -220,6 +232,26 @@ parser_strdup(parser_state *p, const char *s)
#undef strdup
#define strdup(s) parser_strdup(p, s)
+static void
+dump_int(uint16_t i, char *s)
+{
+ char *p = s;
+ char *t = s;
+
+ while (i > 0) {
+ *p++ = (i % 10)+'0';
+ i /= 10;
+ }
+ if (p == s) *p++ = '0';
+ *p = 0;
+ p--; /* point the last char */
+ while (t < p) {
+ char c = *t;
+ *t++ = *p;
+ *p-- = c;
+ }
+}
+
/* xxx ----------------------------- */
static node*
@@ -283,6 +315,20 @@ local_add(parser_state *p, mrb_sym sym)
}
}
+static void
+local_add_blk(parser_state *p, mrb_sym blk)
+{
+ /* allocate register for block */
+ local_add_f(p, blk ? blk : mrb_intern_lit(p->mrb, "&"));
+}
+
+static void
+local_add_kw(parser_state *p, mrb_sym kwd)
+{
+ /* allocate register for keywords hash */
+ local_add_f(p, kwd ? kwd : mrb_intern_lit(p->mrb, "**"));
+}
+
static node*
locals_node(parser_state *p)
{
@@ -726,13 +772,11 @@ new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
{
node *k;
- /* allocate register for keywords hash */
if (kws || kwrest) {
- local_add_f(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : mrb_intern_lit(p->mrb, "**"));
+ local_add_kw(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : 0);
}
- /* allocate register for block */
- local_add_f(p, blk? blk : mrb_intern_lit(p->mrb, "&"));
+ local_add_blk(p, blk);
// allocate register for keywords arguments
// order is for Proc#parameters
@@ -795,6 +839,13 @@ new_masgn(parser_state *p, node *a, node *b)
return cons((node*)NODE_MASGN, cons(a, b));
}
+/* (:masgn mlhs mrhs) no check */
+static node*
+new_masgn_param(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_MASGN, cons(a, b));
+}
+
/* (:asgn lhs rhs) */
static node*
new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
@@ -803,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
@@ -833,6 +922,86 @@ new_dstr(parser_state *p, node *a)
return cons((node*)NODE_DSTR, a);
}
+static int
+string_node_p(node *n)
+{
+ return (int)((enum node_type)(intptr_t)n->car == NODE_STR);
+}
+
+static node*
+composite_string_node(parser_state *p, node *a, node *b)
+{
+ size_t newlen = (size_t)a->cdr + (size_t)b->cdr;
+ char *str = (char*)mrb_pool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
+ memcpy(str + (size_t)a->cdr, b->car, (size_t)b->cdr);
+ str[newlen] = '\0';
+ a->car = (node*)str;
+ a->cdr = (node*)newlen;
+ cons_free(b);
+ return a;
+}
+
+static node*
+concat_string(parser_state *p, node *a, node *b)
+{
+ if (string_node_p(a)) {
+ if (string_node_p(b)) {
+ /* a == NODE_STR && b == NODE_STR */
+ composite_string_node(p, a->cdr, b->cdr);
+ cons_free(b);
+ return a;
+ }
+ else {
+ /* a == NODE_STR && b == NODE_DSTR */
+
+ if (string_node_p(b->cdr->car)) {
+ /* a == NODE_STR && b->[NODE_STR, ...] */
+ composite_string_node(p, a->cdr, b->cdr->car->cdr);
+ cons_free(b->cdr->car);
+ b->cdr->car = a;
+ return b;
+ }
+ }
+ }
+ else {
+ node *c; /* last node of a */
+ for (c = a; c->cdr != NULL; c = c->cdr) ;
+
+ 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;
+ }
+
+ push(a, b);
+ return a;
+ }
+ else {
+ /* 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;
+ }
+ }
+ }
+
+ return new_dstr(p, list2(a, b));
+}
+
/* (:str . (s . len)) */
static node*
new_xstr(parser_state *p, const char *s, int len)
@@ -1181,7 +1350,7 @@ heredoc_end(parser_state *p)
%token <nd> tNTH_REF tBACK_REF
%token <num> tREGEXP_END
-%type <nd> singleton string string_rep string_interp xstring regexp
+%type <nd> singleton string string_fragment 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
@@ -2560,9 +2729,9 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
- | f_arg ','
+ | f_arg ',' opt_block_args_tail
{
- $$ = new_args(p, $1, 0, 0, 0, 0);
+ $$ = new_args(p, $1, 0, 0, 0, $3);
}
| f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
@@ -2603,19 +2772,24 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
;
opt_block_param : none
- | block_param_def
{
+ local_add_blk(p, 0);
+ $$ = 0;
+ }
+ | block_param_def
+ {
p->cmd_start = TRUE;
$$ = $1;
}
;
-block_param_def : '|' opt_bv_decl '|'
+block_param_def : '|' {local_add_blk(p, 0);} opt_bv_decl '|'
{
$$ = 0;
}
| tOROP
{
+ local_add_blk(p, 0);
$$ = 0;
}
| '|' block_param opt_bv_decl '|'
@@ -2828,7 +3002,14 @@ literal : numeric
| symbols
;
-string : tCHAR
+string : string_fragment
+ | string string_fragment
+ {
+ $$ = concat_string(p, $1, $2);
+ }
+ ;
+
+string_fragment : tCHAR
| tSTRING
| tSTRING_BEG tSTRING
{
@@ -3050,7 +3231,7 @@ var_ref : variable
}
| keyword__FILE__
{
- const char *fn = p->filename;
+ const char *fn = mrb_sym2name_len(p->mrb, p->filename_sym, NULL);
if (!fn) {
fn = "(null)";
}
@@ -3060,8 +3241,8 @@ var_ref : variable
{
char buf[16];
- snprintf(buf, sizeof(buf), "%d", p->lineno);
- $$ = new_int(p, buf, 10);
+ dump_int(p->lineno, buf);
+ $$ = new_int(p, buf, 10, 0);
}
| keyword__ENCODING__
{
@@ -3302,7 +3483,7 @@ f_arg_item : f_norm_arg
}
f_margs rparen
{
- $$ = new_masgn(p, $3, p->locals->car);
+ $$ = new_masgn_param(p, $3, p->locals->car);
local_resume(p, $<nd>2);
local_add_f(p, 0);
}
@@ -3454,7 +3635,7 @@ assoc : arg tASSOC arg
void_expr_error(p, $3);
$$ = cons(new_sym(p, $1), $3);
}
- | string tLABEL_TAG arg
+ | string_fragment tLABEL_TAG arg
{
void_expr_error(p, $3);
if ($1->car == (node*)NODE_DSTR) {
@@ -3559,8 +3740,9 @@ yyerror(parser_state *p, const char *s)
if (! p->capture_errors) {
#ifndef MRB_DISABLE_STDIO
- if (p->filename) {
- fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
+ if (p->filename_sym) {
+ const char *filename = mrb_sym2name_len(p->mrb, p->filename_sym, NULL);
+ fprintf(stderr, "%s:%d:%d: %s\n", filename, p->lineno, p->column, s);
}
else {
fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
@@ -3579,11 +3761,13 @@ yyerror(parser_state *p, const char *s)
}
static void
-yyerror_i(parser_state *p, const char *fmt, int i)
+yyerror_c(parser_state *p, const char *msg, char c)
{
char buf[256];
- snprintf(buf, sizeof(buf), fmt, i);
+ strncpy(buf, msg, sizeof(buf) - 2);
+ buf[sizeof(buf) - 2] = '\0';
+ strncat(buf, &c, 1);
yyerror(p, buf);
}
@@ -3595,11 +3779,12 @@ yywarn(parser_state *p, const char *s)
if (! p->capture_errors) {
#ifndef MRB_DISABLE_STDIO
- if (p->filename) {
- fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
+ if (p->filename_sym) {
+ const char *filename = mrb_sym2name_len(p->mrb, p->filename_sym, NULL);
+ fprintf(stderr, "%s:%d:%d: warning: %s\n", filename, p->lineno, p->column, s);
}
else {
- fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
+ fprintf(stderr, "line %d:%d: warning: %s\n", p->lineno, p->column, s);
}
#endif
}
@@ -3621,11 +3806,14 @@ yywarning(parser_state *p, const char *s)
}
static void
-yywarning_s(parser_state *p, const char *fmt, const char *s)
+yywarning_s(parser_state *p, const char *msg, const char *s)
{
char buf[256];
- snprintf(buf, sizeof(buf), fmt, s);
+ strncpy(buf, msg, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1);
+ strncat(buf, s, sizeof(buf) - strlen(buf) - 1);
yywarning(p, buf);
}
@@ -3637,13 +3825,13 @@ backref_error(parser_state *p, node *n)
c = intn(n->car);
if (c == NODE_NTH_REF) {
- yyerror_i(p, "can't set variable $%" MRB_PRId, intn(n->cdr));
+ yyerror_c(p, "can't set variable $", (char)intn(n->cdr)+'0');
}
else if (c == NODE_BACK_REF) {
- yyerror_i(p, "can't set variable $%c", intn(n->cdr));
+ yyerror_c(p, "can't set variable $", (char)intn(n->cdr));
}
else {
- mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
+ mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %d", c);
}
}
@@ -3664,8 +3852,10 @@ void_expr_error(parser_state *p, node *n)
break;
case NODE_AND:
case NODE_OR:
- void_expr_error(p, n->cdr->car);
- void_expr_error(p, n->cdr->cdr);
+ if (n->cdr) {
+ void_expr_error(p, n->cdr->car);
+ void_expr_error(p, n->cdr->cdr);
+ }
break;
case NODE_BEGIN:
if (n->cdr) {
@@ -4182,8 +4372,17 @@ parse_string(parser_state *p)
}
if (c < 0) {
char buf[256];
- snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term);
- yyerror(p, buf);
+ const char s1[] = "can't find heredoc delimiter \"";
+ const char s2[] = "\" anywhere before EOF";
+
+ if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) {
+ yyerror(p, "can't find heredoc delimiter anywhere before EOF");
+ } else {
+ strcpy(buf, s1);
+ strcat(buf, hinf->term);
+ strcat(buf, s2);
+ yyerror(p, buf);
+ }
return 0;
}
pylval.nd = new_str(p, tok(p), toklen(p));
@@ -4333,9 +4532,14 @@ parse_string(parser_state *p)
pushback(p, re_opt);
if (toklen(p)) {
char msg[128];
+
+ strcpy(msg, "unknown regexp option");
tokfix(p);
- snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
- toklen(p) > 1 ? "s" : "", tok(p));
+ if (toklen(p) > 1) {
+ strcat(msg, "s");
+ }
+ strcat(msg, " - ");
+ strncat(msg, tok(p), sizeof(msg) - strlen(msg) - 1);
yyerror(p, msg);
}
if (f != 0) {
@@ -4366,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)
@@ -4486,52 +4729,66 @@ parser_yylex(parser_state *p)
/* fall through */
case -2: /* end of a file */
case '\n':
- maybe_heredoc:
+ maybe_heredoc:
heredoc_treat_nextline(p);
- switch (p->lstate) {
- case EXPR_BEG:
- case EXPR_FNAME:
- case EXPR_DOT:
- case EXPR_CLASS:
- case EXPR_VALUE:
- p->lineno++;
p->column = 0;
- if (p->parsing_heredoc != NULL) {
- if (p->lex_strterm) {
- return parse_string(p);
+ switch (p->lstate) {
+ case EXPR_BEG:
+ case EXPR_FNAME:
+ case EXPR_DOT:
+ case EXPR_CLASS:
+ case EXPR_VALUE:
+ p->lineno++;
+ if (p->parsing_heredoc != NULL) {
+ if (p->lex_strterm) {
+ return parse_string(p);
+ }
}
- }
- goto retry;
- default:
- break;
- }
- if (p->parsing_heredoc != NULL) {
- return '\n';
- }
- while ((c = nextc(p))) {
- switch (c) {
- case ' ': case '\t': case '\f': case '\r':
- case '\13': /* '\v' */
- space_seen = 1;
+ goto retry;
+ default:
break;
- case '.':
- if ((c = nextc(p)) != '.') {
- pushback(p, c);
- pushback(p, '.');
+ }
+ if (p->parsing_heredoc != NULL) {
+ return '\n';
+ }
+ while ((c = nextc(p))) {
+ switch (c) {
+ case ' ': case '\t': case '\f': case '\r':
+ case '\13': /* '\v' */
+ space_seen = 1;
+ break;
+ case '#': /* comment as a whitespace */
+ pushback(p, '#');
+ p->lineno++;
goto retry;
+ case '.':
+ if (!peek(p, '.')) {
+ pushback(p, '.');
+ p->lineno++;
+ goto retry;
+ }
+ pushback(p, c);
+ goto normal_newline;
+ case '&':
+ if (peek(p, '.')) {
+ pushback(p, '&');
+ p->lineno++;
+ goto retry;
+ }
+ pushback(p, c);
+ goto normal_newline;
+ case -1: /* EOF */
+ case -2: /* end of a file */
+ goto normal_newline;
+ default:
+ pushback(p, c);
+ goto normal_newline;
}
- case -1: /* EOF */
- case -2: /* end of a file */
- goto normal_newline;
- default:
- pushback(p, c);
- goto normal_newline;
}
- }
normal_newline:
- p->cmd_start = TRUE;
- p->lstate = EXPR_BEG;
- return '\n';
+ p->cmd_start = TRUE;
+ p->lstate = EXPR_BEG;
+ return '\n';
case '*':
if ((c = nextc(p)) == '*') {
@@ -4542,7 +4799,7 @@ parser_yylex(parser_state *p)
}
pushback(p, c);
if (IS_SPCARG(c)) {
- yywarning(p, "`**' interpreted as argument prefix");
+ yywarning(p, "'**' interpreted as argument prefix");
c = tDSTAR;
}
else if (IS_BEG()) {
@@ -4763,7 +5020,10 @@ parser_yylex(parser_state *p)
}
if (c2) {
char buf[256];
- snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
+ char cc[] = { (char)c2, '\0' };
+
+ strcpy(buf, "invalid character syntax; use ?\\");
+ strncat(buf, cc, 2);
yyerror(p, buf);
}
}
@@ -4774,10 +5034,10 @@ parser_yylex(parser_state *p)
}
newtok(p);
/* need support UTF-8 if configured */
- if ((isalnum(c) || c == '_')) {
+ if ((ISALNUM(c) || c == '_')) {
int c2 = nextc(p);
pushback(p, c2);
- if ((isalnum(c2) || c2 == '_')) {
+ if ((ISALNUM(c2) || c2 == '_')) {
goto ternary;
}
}
@@ -4937,6 +5197,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;
@@ -4970,7 +5231,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') {
@@ -4994,7 +5258,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') {
@@ -5018,7 +5285,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 == '_') {
@@ -5051,7 +5321,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) {
@@ -5068,7 +5341,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;
}
}
@@ -5136,13 +5412,13 @@ parser_yylex(parser_state *p)
pushback(p, c);
if (nondigit) {
trailing_uc:
- yyerror_i(p, "trailing '%c' in number", nondigit);
+ yyerror_c(p, "trailing non digit in number: ", (char)nondigit);
}
tokfix(p);
if (is_float) {
#ifdef MRB_WITHOUT_FLOAT
yywarning_s(p, "floating point numbers are not supported", tok(p));
- pylval.nd = new_int(p, "0", 10);
+ pylval.nd = new_int(p, "0", 10, 0);
return tINTEGER;
#else
double d;
@@ -5151,17 +5427,23 @@ parser_yylex(parser_state *p)
errno = 0;
d = mrb_float_read(tok(p), &endp);
if (d == 0 && endp == tok(p)) {
- yywarning_s(p, "corrupted float value %s", tok(p));
+ yywarning_s(p, "corrupted float value", tok(p));
}
else if (errno == ERANGE) {
- yywarning_s(p, "float %s out of range", tok(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;
}
@@ -5345,7 +5627,7 @@ parser_yylex(parser_state *p)
}
else {
term = nextc(p);
- if (isalnum(term)) {
+ if (ISALNUM(term)) {
yyerror(p, "unknown type of %string");
return 0;
}
@@ -5489,14 +5771,14 @@ parser_yylex(parser_state *p)
do {
tokadd(p, c);
c = nextc(p);
- } while (c >= 0 && isdigit(c));
+ } while (c >= 0 && ISDIGIT(c));
pushback(p, c);
if (last_state == EXPR_FNAME) goto gvar;
tokfix(p);
{
unsigned long n = strtoul(tok(p), NULL, 10);
if (n > INT_MAX) {
- yyerror_i(p, "capture group index must be <= %d", INT_MAX);
+ yyerror(p, "capture group index must be <= " MRB_STRINGIZE(INT_MAX));
return 0;
}
pylval.nd = new_nth_ref(p, (int)n);
@@ -5531,12 +5813,12 @@ parser_yylex(parser_state *p)
}
return 0;
}
- else if (isdigit(c)) {
+ else if (ISDIGIT(c)) {
if (p->tidx == 1) {
- yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
+ yyerror_c(p, "wrong instance variable name: @", c);
}
else {
- yyerror_i(p, "'@@%c' is not allowed as a class variable name", c);
+ yyerror_c(p, "wrong class variable name: @@", c);
}
return 0;
}
@@ -5552,7 +5834,15 @@ parser_yylex(parser_state *p)
default:
if (!identchar(c)) {
- yyerror_i(p, "Invalid char '\\x%02X' in expression", c);
+ char buf[36];
+ const char s[] = "Invalid char in expression: 0x";
+ const char hexdigits[] = "0123456789ABCDEF";
+
+ strcpy(buf, s);
+ buf[sizeof(s)-1] = hexdigits[(c & 0xf0) >> 4];
+ buf[sizeof(s)] = hexdigits[(c & 0x0f)];
+ buf[sizeof(s)+1] = 0;
+ yyerror(p, buf);
goto retry;
}
@@ -5688,7 +5978,7 @@ parser_yylex(parser_state *p)
mrb_sym ident = intern_cstr(tok(p));
pylval.id = ident;
- if (last_state != EXPR_DOT && islower(tok(p)[0]) && local_var_p(p, ident)) {
+ if (last_state != EXPR_DOT && ISLOWER(tok(p)[0]) && local_var_p(p, ident)) {
p->lstate = EXPR_END;
}
}
@@ -5898,7 +6188,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
mrb_sym* new_table;
sym = mrb_intern_cstr(p->mrb, f);
- p->filename = mrb_sym2name_len(p->mrb, sym, NULL);
+ p->filename_sym = sym;
p->lineno = (p->filename_table_length > 0)? 0 : 1;
for (i = 0; i < p->filename_table_length; ++i) {
@@ -5922,11 +6212,11 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
p->filename_table[p->filename_table_length - 1] = sym;
}
-MRB_API char const*
+MRB_API mrb_sym
mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) {
- if (idx >= p->filename_table_length) return NULL;
+ if (idx >= p->filename_table_length) return 0;
else {
- return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL);
+ return p->filename_table[idx];
}
}
@@ -5981,11 +6271,12 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
if (c) c->parser_nerr = p->nerr;
if (p->capture_errors) {
char buf[256];
- int n;
- n = snprintf(buf, sizeof(buf), "line %d: %s\n",
- p->error_buffer[0].lineno, p->error_buffer[0].message);
- mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
+ strcpy(buf, "line ");
+ dump_int(p->error_buffer[0].lineno, buf+5);
+ strcat(buf, ": ");
+ strncat(buf, p->error_buffer[0].message, sizeof(buf) - strlen(buf) - 1);
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf)));
mrb_parser_free(p);
return mrb_undef_value();
}