summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-compiler')
-rw-r--r--mrbgems/mruby-compiler/bintest/mrbc.rb9
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c133
-rw-r--r--mrbgems/mruby-compiler/core/parse.y282
3 files changed, 269 insertions, 155 deletions
diff --git a/mrbgems/mruby-compiler/bintest/mrbc.rb b/mrbgems/mruby-compiler/bintest/mrbc.rb
index e4dc6a9a8..e27365edb 100644
--- a/mrbgems/mruby-compiler/bintest/mrbc.rb
+++ b/mrbgems/mruby-compiler/bintest/mrbc.rb
@@ -10,3 +10,12 @@ assert('Compiling multiple files without new line in last line. #2361') do
assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
assert_equal 0, $?.exitstatus
end
+
+assert('parsing function with void argument') do
+ a, out = Tempfile.new('a.rb'), Tempfile.new('out.mrb')
+ a.write('f ()')
+ a.flush
+ result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} 2>&1`
+ assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
+ assert_equal 0, $?.exitstatus
+end
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 9b064b867..23e036d49 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -93,6 +93,7 @@ codegen_error(codegen_scope *s, const char *message)
if (!s) return;
while (s->prev) {
codegen_scope *tmp = s->prev;
+ mrb_free(s->mrb, s->iseq);
mrb_pool_close(s->mpool);
s = tmp;
}
@@ -387,6 +388,9 @@ dispatch(codegen_scope *s, int pc)
scope_error(s);
break;
}
+ if (diff > MAXARG_sBx) {
+ codegen_error(s, "too distant jump address");
+ }
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
}
@@ -500,7 +504,12 @@ new_lit(codegen_scope *s, mrb_value val)
return i;
}
-static inline int
+/* method symbols should be fit in 9 bits */
+#define MAXMSYMLEN 512
+/* maximum symbol numbers */
+#define MAXSYMLEN 65536
+
+static int
new_msym(codegen_scope *s, mrb_sym sym)
{
size_t i, len;
@@ -508,20 +517,20 @@ new_msym(codegen_scope *s, mrb_sym sym)
mrb_assert(s->irep);
len = s->irep->slen;
- if (len > 256) len = 256;
+ if (len > MAXMSYMLEN) len = MAXMSYMLEN;
for (i=0; i<len; i++) {
if (s->irep->syms[i] == sym) return i;
if (s->irep->syms[i] == 0) break;
}
- if (i == 256) {
- codegen_error(s, "too many symbols (max 256)");
+ if (i == MAXMSYMLEN) {
+ codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")");
}
s->irep->syms[i] = sym;
if (i == s->irep->slen) s->irep->slen++;
return i;
}
-static inline int
+static int
new_sym(codegen_scope *s, mrb_sym sym)
{
size_t i;
@@ -529,13 +538,18 @@ new_sym(codegen_scope *s, mrb_sym sym)
for (i=0; i<s->irep->slen; i++) {
if (s->irep->syms[i] == sym) return i;
}
- if (s->irep->slen > 125 && s->irep->slen < 256) {
- s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536);
- for (i = 0; i < 256 - s->irep->slen; i++) {
+ if (s->irep->slen == MAXSYMLEN) {
+ codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")");
+ }
+
+ if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) {
+ s->scapa = MAXSYMLEN;
+ s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN);
+ for (i = s->irep->slen; i < MAXMSYMLEN; i++) {
static const mrb_sym mrb_sym_zero = { 0 };
- s->irep->syms[i + s->irep->slen] = mrb_sym_zero;
+ s->irep->syms[i] = mrb_sym_zero;
}
- s->irep->slen = 256;
+ s->irep->slen = MAXMSYMLEN;
}
s->irep->syms[s->irep->slen] = sym;
return s->irep->slen++;
@@ -588,9 +602,6 @@ for_body(codegen_scope *s, node *tree)
push(); /* push for a block parameter */
- lp = loop_push(s, LOOP_FOR);
- lp->pc1 = new_label(s);
-
/* generate loop variable */
n2 = tree->car;
genop(s, MKOP_Ax(OP_ENTER, 0x40000));
@@ -600,6 +611,11 @@ for_body(codegen_scope *s, node *tree)
else {
gen_vmassignment(s, n2, 1, VAL);
}
+ /* construct loop */
+ lp = loop_push(s, LOOP_FOR);
+ lp->pc2 = new_label(s);
+
+ /* loop body */
codegen(s, tree->cdr->cdr->car, VAL);
pop();
if (s->pc > 0) {
@@ -650,6 +666,9 @@ lambda_body(codegen_scope *s, node *tree, int blk)
ka = kd = 0;
ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
+ if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
+ codegen_error(s, "too many formal arguments");
+ }
a = ((mrb_aspec)(ma & 0x1f) << 18)
| ((mrb_aspec)(oa & 0x1f) << 13)
| ((ra & 1) << 12)
@@ -770,6 +789,8 @@ attrsym(codegen_scope *s, mrb_sym a)
return mrb_intern(s->mrb, name2, len+1);
}
+#define CALL_MAXARGS 127
+
static int
gen_values(codegen_scope *s, node *t, int val)
{
@@ -778,7 +799,9 @@ gen_values(codegen_scope *s, node *t, int val)
while (t) {
is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
- if (n >= 127 || is_splat) {
+ if (
+ n >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
+ || is_splat) {
if (val) {
if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) {
codegen(s, t->car->cdr, VAL);
@@ -812,8 +835,6 @@ gen_values(codegen_scope *s, node *t, int val)
}
}
else {
- codegen(s, t->car->cdr, NOVAL);
- t = t->cdr;
while (t) {
codegen(s, t->car, NOVAL);
t = t->cdr;
@@ -829,8 +850,6 @@ gen_values(codegen_scope *s, node *t, int val)
return n;
}
-#define CALL_MAXARGS 127
-
static void
gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
{
@@ -1057,7 +1076,9 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
n++;
}
}
- push();
+ if (!val) {
+ push();
+ }
}
}
@@ -1360,6 +1381,10 @@ codegen(codegen_scope *s, node *tree, int val)
int pos1, pos2;
node *e = tree->cdr->cdr->car;
+ if (!tree->car) {
+ codegen(s, e, val);
+ return;
+ }
switch ((intptr_t)tree->car->car) {
case NODE_TRUE:
case NODE_INT:
@@ -1510,7 +1535,9 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_LOADNIL, cursp()));
if (pos3) dispatch_linked(s, pos3);
if (head) pop();
- genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ if (cursp() != pos) {
+ genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ }
push();
}
else {
@@ -1655,7 +1682,6 @@ codegen(codegen_scope *s, node *tree, int val)
}
tree = tree->car;
if (tree->car) { /* pre */
- int first = TRUE;
t = tree->car;
n = 0;
while (t) {
@@ -1664,10 +1690,7 @@ codegen(codegen_scope *s, node *tree, int val)
n++;
}
else {
- if (first) {
- genop(s, MKOP_A(OP_LOADNIL, rhs+n));
- first = FALSE;
- }
+ genop(s, MKOP_A(OP_LOADNIL, rhs+n));
gen_assignment(s, t->car, rhs+n, NOVAL);
}
t = t->cdr;
@@ -1746,6 +1769,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_RESCUE, exc));
genop(s, MKOP_A(OP_LOADF, exc));
dispatch(s, noexc);
+ loop_pop(s, NOVAL);
}
else if ((intptr_t)tree->car->car == NODE_CALL) {
node *n = tree->car->cdr;
@@ -1795,8 +1819,10 @@ codegen(codegen_scope *s, node *tree, int val)
int pos;
pop();
- if (val && vsp >= 0) {
- genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ if (val) {
+ if (vsp >= 0) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ }
pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
}
else {
@@ -2012,7 +2038,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_REDO:
- if (!s->loop) {
+ if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
raise_error(s, "unexpected redo");
}
else {
@@ -2021,6 +2047,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
}
+ if (val) push();
break;
case NODE_RETRY:
@@ -2055,6 +2082,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
}
}
+ if (val) push();
}
break;
@@ -2194,7 +2222,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_FLOAT:
if (val) {
char *p = (char*)tree;
- mrb_float f = str_to_mrb_float(p);
+ mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, f));
genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
@@ -2208,9 +2236,9 @@ codegen(codegen_scope *s, node *tree, int val)
tree = tree->cdr;
switch (nt) {
case NODE_FLOAT:
- {
+ if (val) {
char *p = (char*)tree;
- mrb_float f = str_to_mrb_float(p);
+ mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, -f));
genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
@@ -2219,7 +2247,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_INT:
- {
+ if (val) {
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
mrb_int i;
@@ -2248,7 +2276,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
default:
- {
+ if (val) {
int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
@@ -2257,6 +2285,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop(); pop();
genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
}
+ else {
+ codegen(s, tree, NOVAL);
+ }
break;
}
}
@@ -2282,7 +2313,11 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
node *n = tree;
- if (!n) break;
+ if (!n) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ break;
+ }
codegen(s, n->car, VAL);
n = n->cdr;
while (n) {
@@ -2539,13 +2574,31 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_TCLASS, cursp()));
push();
while (t) {
- int symbol = new_msym(s, sym(t->car));
+ int symbol;
+ if (num >= CALL_MAXARGS - 1) {
+ pop_n(num);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
+ while (t) {
+ symbol = new_msym(s, sym(t->car));
+ push();
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
+ pop();
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ t = t->cdr;
+ }
+ num = CALL_MAXARGS;
+ break;
+ }
+ symbol = new_msym(s, sym(t->car));
genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
push();
t = t->cdr;
num++;
}
- pop_n(num + 1);
+ pop();
+ if (num < CALL_MAXARGS) {
+ pop_n(num);
+ }
genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
if (val) {
push();
@@ -2713,13 +2766,13 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
p->icapa = 1024;
p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
- p->irep->iseq = p->iseq;
+ p->irep->iseq = NULL;
p->pcapa = 32;
p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
p->irep->plen = 0;
- p->scapa = 256;
+ p->scapa = MAXMSYMLEN;
p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
p->irep->slen = 0;
@@ -2797,6 +2850,7 @@ scope_finish(codegen_scope *s)
memcpy(fname, s->filename, fname_len);
fname[fname_len] = '\0';
irep->filename = fname;
+ irep->own_filename = TRUE;
}
irep->nlocals = s->nlocals;
@@ -2904,9 +2958,6 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
return proc;
}
MRB_CATCH(&scope->jmp) {
- if (scope->filename == scope->irep->filename) {
- scope->irep->filename = NULL;
- }
mrb_irep_decref(mrb, scope->irep);
mrb_pool_close(scope->mpool);
return NULL;
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index 426c262fb..f8e4eb72f 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -41,6 +41,7 @@ static void yyerror(parser_state *p, const char *s);
static void yywarn(parser_state *p, const char *s);
static void yywarning(parser_state *p, const char *s);
static void backref_error(parser_state *p, node *n);
+static void void_expr_error(parser_state *p, node *n);
static void tokadd(parser_state *p, int32_t c);
#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
@@ -870,6 +871,7 @@ call_with_block(parser_state *p, node *a, node *b)
break;
case NODE_CALL:
case NODE_FCALL:
+ case NODE_SCALL:
n = a->cdr->cdr->cdr;
if (!n->car) n->car = cons(0, b);
else {
@@ -1097,7 +1099,7 @@ heredoc_end(parser_state *p)
%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
-%type <nd> expr_value arg_value arg_rhs primary_value
+%type <nd> expr_value arg_rhs primary_value
%type <nd> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
%type <nd> args call_args opt_call_args
%type <nd> paren_args opt_paren_args variable
@@ -1322,7 +1324,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
{
$$ = new_asgn(p, $1, new_array(p, $3));
}
- | mlhs '=' arg_value
+ | mlhs '=' arg
{
$$ = new_masgn(p, $1, $3);
}
@@ -1401,7 +1403,10 @@ expr : command_call
expr_value : expr
{
if (!$1) $$ = new_nil(p);
- else $$ = $1;
+ else {
+ void_expr_error(p, $1);
+ $$ = $1;
+ }
}
;
@@ -1907,20 +1912,13 @@ arg : lhs '=' arg_rhs
}
;
-arg_value : arg
- {
- $$ = $1;
- if (!$$) $$ = new_nil(p);
- }
- ;
-
aref_args : none
| args trailer
{
$$ = $1;
NODE_LINENO($$, $1);
}
- | args ',' assocs trailer
+ | args comma assocs trailer
{
$$ = push($1, new_hash(p, $3));
}
@@ -1931,9 +1929,14 @@ aref_args : none
}
;
-arg_rhs : arg %prec tOP_ASGN
+arg_rhs : arg %prec tOP_ASGN
+ {
+ void_expr_error(p, $1);
+ $$ = $1;
+ }
| arg modifier_rescue arg
{
+ void_expr_error(p, $1);
$$ = new_mod_rescue(p, $1, $3);
}
;
@@ -1955,7 +1958,7 @@ opt_call_args : none
$$ = cons($1,0);
NODE_LINENO($$, $1);
}
- | args ',' assocs ','
+ | args comma assocs ','
{
$$ = cons(push($1, new_hash(p, $3)), 0);
NODE_LINENO($$, $1);
@@ -1982,7 +1985,7 @@ call_args : command
$$ = cons(list1(new_hash(p, $1)), $2);
NODE_LINENO($$, $1);
}
- | args ',' assocs opt_block_arg
+ | args comma assocs opt_block_arg
{
$$ = cons(push($1, new_hash(p, $3)), $4);
NODE_LINENO($$, $1);
@@ -2005,13 +2008,13 @@ command_args : {
}
;
-block_arg : tAMPER arg_value
+block_arg : tAMPER arg
{
$$ = new_block_arg(p, $2);
}
;
-opt_block_arg : ',' block_arg
+opt_block_arg : comma block_arg
{
$$ = $2;
}
@@ -2021,44 +2024,47 @@ opt_block_arg : ',' block_arg
}
;
-args : arg_value
+comma : ','
+ | ',' heredoc_bodies
+ ;
+
+args : arg
{
+ void_expr_error(p, $1);
$$ = cons($1, 0);
NODE_LINENO($$, $1);
}
- | tSTAR arg_value
+ | tSTAR arg
{
+ void_expr_error(p, $2);
$$ = cons(new_splat(p, $2), 0);
NODE_LINENO($$, $2);
}
- | args ',' arg_value
+ | args comma arg
{
+ void_expr_error(p, $3);
$$ = push($1, $3);
}
- | args ',' tSTAR arg_value
+ | args comma tSTAR arg
{
+ void_expr_error(p, $4);
$$ = push($1, new_splat(p, $4));
}
- | args ',' heredoc_bodies arg_value
- {
- $$ = push($1, $4);
- }
- | args ',' heredoc_bodies tSTAR arg_value
- {
- $$ = push($1, new_splat(p, $5));
- }
;
-mrhs : args ',' arg_value
+mrhs : args comma arg
{
+ void_expr_error(p, $3);
$$ = push($1, $3);
}
- | args ',' tSTAR arg_value
+ | args comma tSTAR arg
{
+ void_expr_error(p, $4);
$$ = push($1, new_splat(p, $4));
}
- | tSTAR arg_value
+ | tSTAR arg
{
+ void_expr_error(p, $2);
$$ = list1(new_splat(p, $2));
}
;
@@ -2097,7 +2103,7 @@ primary : literal
}
| tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen
{
- $$ = 0;
+ $$ = new_nil(p);
}
| tLPAREN compstmt ')'
{
@@ -2125,17 +2131,9 @@ primary : literal
{
$$ = new_return(p, 0);
}
- | keyword_yield '(' call_args rparen
+ | keyword_yield opt_paren_args
{
- $$ = new_yield(p, $3);
- }
- | keyword_yield '(' rparen
- {
- $$ = new_yield(p, 0);
- }
- | keyword_yield
- {
- $$ = new_yield(p, 0);
+ $$ = new_yield(p, $2);
}
| keyword_not '(' expr rparen
{
@@ -2450,7 +2448,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
}
| f_arg ','
{
- $$ = new_args(p, $1, 0, 1, 0, 0);
+ $$ = new_args(p, $1, 0, 0, 0, 0);
}
| f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
{
@@ -2688,7 +2686,7 @@ opt_rescue : keyword_rescue exc_list exc_var then
| none
;
-exc_list : arg_value
+exc_list : arg
{
$$ = list1($1);
}
@@ -2783,10 +2781,6 @@ regexp : tREGEXP_BEG tREGEXP
heredoc : tHEREDOC_BEG
;
-opt_heredoc_bodies : /* none */
- | heredoc_bodies
- ;
-
heredoc_bodies : heredoc_body
| heredoc_bodies heredoc_body
;
@@ -3115,7 +3109,7 @@ f_opt_asgn : tIDENTIFIER '='
}
;
-f_opt : f_opt_asgn arg_value
+f_opt : f_opt_asgn arg
{
$$ = cons(nsym($1), $2);
}
@@ -3233,23 +3227,23 @@ assocs : assoc
}
;
-assoc : arg_value tASSOC arg_value
+assoc : arg tASSOC arg
{
$$ = cons($1, $3);
}
- | tLABEL arg_value
+ | tLABEL arg
{
$$ = cons(new_sym(p, $1), $2);
}
- | tLABEL_END arg_value
+ | tLABEL_END arg
{
$$ = cons(new_sym(p, new_strsym(p, $1)), $2);
}
- | tSTRING_BEG tLABEL_END arg_value
+ | tSTRING_BEG tLABEL_END arg
{
$$ = cons(new_sym(p, new_strsym(p, $2)), $3);
}
- | tSTRING_BEG string_rep tLABEL_END arg_value
+ | tSTRING_BEG string_rep tLABEL_END arg
{
$$ = cons(new_dsym(p, push($2, $3)), $4);
}
@@ -3308,11 +3302,12 @@ rbracket : opt_nl ']'
trailer : /* none */
| nl
- | ','
+ | comma
;
term : ';' {yyerrok;}
| nl
+ | heredoc_body
;
nl : '\n'
@@ -3320,10 +3315,10 @@ nl : '\n'
p->lineno++;
p->column = 0;
}
- opt_heredoc_bodies
+ ;
terms : term
- | terms ';' {yyerrok;}
+ | terms term
;
none : /* none */
@@ -3430,6 +3425,26 @@ backref_error(parser_state *p, node *n)
}
}
+static void
+void_expr_error(parser_state *p, node *n)
+{
+ int c;
+
+ if (n == NULL) return;
+ c = (int)(intptr_t)n->car;
+ switch (c) {
+ case NODE_BREAK:
+ case NODE_RETURN:
+ case NODE_NEXT:
+ case NODE_REDO:
+ case NODE_RETRY:
+ yyerror(p, "void value expression");
+ break;
+ default:
+ break;
+ }
+}
+
static void pushback(parser_state *p, int c);
static mrb_bool peeks(parser_state *p, const char *s);
static mrb_bool skips(parser_state *p, const char *s);
@@ -3730,6 +3745,44 @@ scan_hex(const int *start, int len, int *retlen)
return retval;
}
+static int32_t
+read_escape_unicode(parser_state *p, int limit)
+{
+ int32_t c;
+ int buf[9];
+ int i;
+
+ /* Look for opening brace */
+ i = 0;
+ buf[0] = nextc(p);
+ if (buf[0] < 0) goto eof;
+ if (ISXDIGIT(buf[0])) {
+ /* \uxxxx form */
+ for (i=1; i<limit; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] < 0) goto eof;
+ if (!ISXDIGIT(buf[i])) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ }
+ else {
+ pushback(p, buf[0]);
+ }
+ c = scan_hex(buf, i, &i);
+ if (i == 0) {
+ eof:
+ yyerror(p, "Invalid escape character syntax");
+ return -1;
+ }
+ if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
+ yyerror(p, "Invalid Unicode code point");
+ return -1;
+ }
+ return c;
+}
+
/* Return negative to indicate Unicode code point */
static int32_t
read_escape(parser_state *p)
@@ -3802,53 +3855,17 @@ read_escape(parser_state *p)
return c;
case 'u': /* Unicode */
- {
- int buf[9];
- int i;
-
- /* Look for opening brace */
- i = 0;
- buf[0] = nextc(p);
- if (buf[0] < 0) goto eof;
- if (buf[0] == '{') {
+ if (peek(p, '{')) {
/* \u{xxxxxxxx} form */
- for (i=0; i<9; i++) {
- buf[i] = nextc(p);
- if (buf[i] < 0) goto eof;
- if (buf[i] == '}') {
- break;
- }
- else if (!ISXDIGIT(buf[i])) {
- yyerror(p, "Invalid escape character syntax");
- pushback(p, buf[i]);
- return 0;
- }
- }
- }
- else if (ISXDIGIT(buf[0])) {
- /* \uxxxx form */
- for (i=1; i<4; i++) {
- buf[i] = nextc(p);
- if (buf[i] < 0) goto eof;
- if (!ISXDIGIT(buf[i])) {
- pushback(p, buf[i]);
- break;
- }
- }
+ nextc(p);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) return 0;
+ if (nextc(p) != '}') goto eof;
}
else {
- pushback(p, buf[0]);
+ c = read_escape_unicode(p, 4);
+ if (c < 0) return 0;
}
- c = scan_hex(buf, i, &i);
- if (i == 0) {
- yyerror(p, "Invalid escape character syntax");
- return 0;
- }
- if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
- yyerror(p, "Invalid Unicode code point");
- return 0;
- }
- }
return -c;
case 'b':/* backspace */
@@ -3906,7 +3923,10 @@ parse_string(parser_state *p)
int beg = (intptr_t)p->lex_strterm->cdr->cdr->car;
int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
+ int cmd_state = p->cmd_start;
+ if (beg == 0) beg = -3; /* should never happen */
+ if (end == 0) end = -3;
newtok(p);
while ((c = nextc(p)) != end || nest_level != 0) {
if (hinf && (c == '\n' || c < 0)) {
@@ -3928,7 +3948,12 @@ parse_string(parser_state *p)
}
}
if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
- return tHEREDOC_END;
+ if (c < 0) {
+ p->parsing_heredoc = NULL;
+ }
+ else {
+ return tHEREDOC_END;
+ }
}
}
if (c < 0) {
@@ -3969,6 +3994,20 @@ parse_string(parser_state *p)
tokadd(p, '\\');
tokadd(p, c);
}
+ else if (c == 'u' && peek(p, '{')) {
+ /* \u{xxxx xxxx xxxx} form */
+ nextc(p);
+ while (1) {
+ do c = nextc(p); while (ISSPACE(c));
+ if (c == '}') break;
+ pushback(p, c);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) break;
+ tokadd(p, -c);
+ }
+ if (hinf)
+ hinf->line_head = FALSE;
+ }
else {
pushback(p, c);
tokadd(p, read_escape(p));
@@ -4093,10 +4132,12 @@ parse_string(parser_state *p)
return tREGEXP;
}
yylval.nd = new_str(p, tok(p), toklen(p));
- if (IS_LABEL_SUFFIX(0)) {
- p->lstate = EXPR_BEG;
- nextc(p);
- return tLABEL_END;
+ if (IS_LABEL_POSSIBLE()) {
+ if (IS_LABEL_SUFFIX(0)) {
+ p->lstate = EXPR_BEG;
+ nextc(p);
+ return tLABEL_END;
+ }
}
return tSTRING;
@@ -4871,7 +4912,7 @@ parser_yylex(parser_state *p)
char *endp;
errno = 0;
- d = strtod(tok(p), &endp);
+ d = mrb_float_read(tok(p), &endp);
if (d == 0 && endp == tok(p)) {
yywarning_s(p, "corrupted float value %s", tok(p));
}
@@ -5477,7 +5518,10 @@ mrb_parser_parse(parser_state *p, mrbc_context *c)
p->lex_strterm = NULL;
parser_init_cxt(p, c);
- yyparse(p);
+ if (yyparse(p) != 0 || p->nerr > 0) {
+ p->tree = 0;
+ return;
+ }
if (!p->tree) {
p->tree = new_nil(p);
}
@@ -5657,8 +5701,8 @@ mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c)
return mrb_parse_nstring(mrb, s, strlen(s), c);
}
-static mrb_value
-load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
+MRB_API mrb_value
+mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
{
struct RClass *target = mrb->object_class;
struct RProc *proc;
@@ -5717,7 +5761,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
MRB_API mrb_value
mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
{
- return load_exec(mrb, mrb_parse_file(mrb, f, c), c);
+ return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c);
}
MRB_API mrb_value
@@ -5730,7 +5774,7 @@ mrb_load_file(mrb_state *mrb, FILE *f)
MRB_API mrb_value
mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
{
- return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
+ return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
}
MRB_API mrb_value
@@ -6024,7 +6068,17 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_FCALL:
case NODE_CALL:
- printf("NODE_CALL:\n");
+ case NODE_SCALL:
+ switch (nodetype) {
+ case NODE_FCALL:
+ printf("NODE_FCALL:\n"); break;
+ case NODE_CALL:
+ printf("NODE_CALL(.):\n"); break;
+ case NODE_SCALL:
+ printf("NODE_SCALL(&.):\n"); break;
+ default:
+ break;
+ }
mrb_parser_dump(mrb, tree->car, offset+1);
dump_prefix(tree, offset+1);
printf("method='%s' (%d)\n",
@@ -6504,8 +6558,8 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_HEREDOC:
- printf("NODE_HEREDOC:\n");
- mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
+ printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term);
+ dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
break;
default: