1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

parse.y: lex_state trace by yydebug

* parse.y (trace_lex_state): trace lex_state changes if yydebug is
  set, and send the messages to rb_stdout.
* parse.y (rb_parser_printf): store YYPRINTF messages per lines
  so that lex_state traces do not mix.
* tool/ytab.sed: add parser argument to yy_stack_print too.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53095 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-12-13 14:46:09 +00:00
parent ada76728f6
commit 0f076affb6
5 changed files with 83 additions and 31 deletions

View file

@ -1,3 +1,23 @@
Sun Dec 13 23:46:10 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (trace_lex_state): trace lex_state changes if yydebug is
set, and send the messages to rb_stdout.
* parse.y (rb_parser_printf): store YYPRINTF messages per lines
so that lex_state traces do not mix.
* tool/ytab.sed: add parser argument to yy_stack_print too.
Sun Dec 13 23:45:19 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (trace_lex_state): trace lex_state changes if yydebug is
set, and send the messages to rb_stdout.
* parse.y (rb_parser_printf): store YYPRINTF messages per lines
so that lex_state traces do not mix.
* tool/ytab.sed: add parser argument to yy_stack_print too.
Sun Dec 13 20:41:16 2015 Nobuyoshi Nakada <nobu@ruby-lang.org> Sun Dec 13 20:41:16 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (build_lex_state_name, trace_lex_state): lex_state is * parse.y (build_lex_state_name, trace_lex_state): lex_state is

1
node.h
View file

@ -506,6 +506,7 @@ void *rb_parser_malloc(struct parser_params *, size_t);
void *rb_parser_realloc(struct parser_params *, void *, size_t); void *rb_parser_realloc(struct parser_params *, void *, size_t);
void *rb_parser_calloc(struct parser_params *, size_t, size_t); void *rb_parser_calloc(struct parser_params *, size_t, size_t);
void rb_parser_free(struct parser_params *, void *); void rb_parser_free(struct parser_params *, void *);
void rb_parser_printf(struct parser_params *parser, const char *fmt, ...);
RUBY_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END

65
parse.y
View file

@ -44,6 +44,12 @@
#define YYREALLOC(ptr, size) rb_parser_realloc(parser, (ptr), (size)) #define YYREALLOC(ptr, size) rb_parser_realloc(parser, (ptr), (size))
#define YYCALLOC(nelem, size) rb_parser_calloc(parser, (nelem), (size)) #define YYCALLOC(nelem, size) rb_parser_calloc(parser, (nelem), (size))
#define YYFREE(ptr) rb_parser_free(parser, (ptr)) #define YYFREE(ptr) rb_parser_free(parser, (ptr))
#ifdef HAVE_VA_ARGS_MACRO
# define YYFPRINTF(f, fmt, ...) rb_parser_printf(parser, fmt, ##__VA_ARGS__)
#else
# define YYFPRINTF rb_parser_printf
# define stderr parser
#endif
#undef malloc #undef malloc
#undef realloc #undef realloc
#undef calloc #undef calloc
@ -95,11 +101,9 @@ enum lex_state_e {
# define SET_LEX_STATE(ls) \ # define SET_LEX_STATE(ls) \
(lex_state = trace_lex_state(lex_state, (ls), __LINE__)) (lex_state = trace_lex_state(lex_state, (ls), __LINE__))
#if PARSER_DEBUG
static enum lex_state_e trace_lex_state(enum lex_state_e from, enum lex_state_e to, int line); static enum lex_state_e trace_lex_state(enum lex_state_e from, enum lex_state_e to, int line);
#else # define trace_lex_state(from, to, line) \
# define trace_lex_state(from, to, line) (to) (yydebug ? trace_lex_state(from, to, line) : (to))
#endif
typedef VALUE stack_type; typedef VALUE stack_type;
@ -274,6 +278,8 @@ struct parser_params {
token_info *token_info; token_info *token_info;
VALUE compile_option; VALUE compile_option;
VALUE debug_buffer;
ID cur_arg; ID cur_arg;
int last_cr_line; int last_cr_line;
@ -9179,54 +9185,47 @@ id_is_var_gen(struct parser_params *parser, ID id)
} }
#endif /* !RIPPER */ #endif /* !RIPPER */
#if PARSER_DEBUG
static const char lex_state_names[][13] = { static const char lex_state_names[][13] = {
"EXPR_BEG", "EXPR_END", "EXPR_ENDARG", "EXPR_ENDFN", "EXPR_ARG", "EXPR_BEG", "EXPR_END", "EXPR_ENDARG", "EXPR_ENDFN", "EXPR_ARG",
"EXPR_CMDARG", "EXPR_MID", "EXPR_FNAME", "EXPR_DOT", "EXPR_CLASS", "EXPR_CMDARG", "EXPR_MID", "EXPR_FNAME", "EXPR_DOT", "EXPR_CLASS",
"EXPR_LABEL", "EXPR_LABELED", "EXPR_LABEL", "EXPR_LABELED",
}; };
static const char * static VALUE
build_lex_state_name(enum lex_state_e state, char *buf, size_t size) append_lex_state_name(enum lex_state_e state, VALUE buf)
{ {
int i, sep = 0; int i, sep = 0;
char *p = buf;
unsigned int mask = 1; unsigned int mask = 1;
size_t n;
static const char none[] = "EXPR_NONE"; static const char none[] = "EXPR_NONE";
for (i = 0; i < EXPR_MAX_STATE; ++i, mask <<= 1) { for (i = 0; i < EXPR_MAX_STATE; ++i, mask <<= 1) {
if ((unsigned)state & mask) { if ((unsigned)state & mask) {
if (sep) { if (sep) {
if (size < 2) break; rb_str_cat(buf, "|", 1);
--size;
*p++ = '|';
} }
sep = 1; sep = 1;
n = strlcpy(p, lex_state_names[i], size); rb_str_cat_cstr(buf, lex_state_names[i]);
if (n >= size) break;
size -= n;
p += n;
} }
} }
if (p == buf && size >= sizeof(none)) { if (!sep) {
n = strlcpy(buf, none, size); rb_str_cat(buf, none, sizeof(none)-1);
p += n;
} }
*p = '\0';
return buf; return buf;
} }
#undef trace_lex_state
static enum lex_state_e static enum lex_state_e
trace_lex_state(enum lex_state_e from, enum lex_state_e to, int line) trace_lex_state(enum lex_state_e from, enum lex_state_e to, int line)
{ {
char buf1[sizeof(lex_state_names)], buf2[sizeof(lex_state_names)]; VALUE mesg;
build_lex_state_name(from, buf1, sizeof(buf1)); mesg = rb_str_new_cstr("lex_state: ");
build_lex_state_name(to, buf2, sizeof(buf2)); append_lex_state_name(from, mesg);
printf("lex_state: %s -> %s at L%d\n", buf1, buf2, line); rb_str_cat_cstr(mesg, " -> ");
append_lex_state_name(to, mesg);
rb_str_catf(mesg, " at line %d\n", line);
rb_io_write(rb_stdout, mesg);
return to; return to;
} }
#endif
#ifdef RIPPER #ifdef RIPPER
static VALUE static VALUE
@ -10776,6 +10775,7 @@ parser_initialize(struct parser_params *parser)
parser->result = Qnil; parser->result = Qnil;
parser->parsing_thread = Qnil; parser->parsing_thread = Qnil;
#endif #endif
parser->debug_buffer = Qnil;
parser->enc = rb_utf8_encoding(); parser->enc = rb_utf8_encoding();
} }
@ -11034,6 +11034,21 @@ rb_parser_free(struct parser_params *parser, void *ptr)
xfree(ptr); xfree(ptr);
} }
#endif #endif
void
rb_parser_printf(struct parser_params *parser, const char *fmt, ...)
{
va_list ap;
VALUE mesg = parser->debug_buffer;
if (NIL_P(mesg)) parser->debug_buffer = mesg = rb_str_new(0, 0);
va_start(ap, fmt);
rb_str_vcatf(mesg, fmt, ap);
va_end(ap);
if (RSTRING_END(mesg)[-1] == '\n') {
rb_io_write(rb_stdout, mesg);
}
}
#endif #endif
#ifdef RIPPER #ifdef RIPPER

View file

@ -191,13 +191,13 @@ class TestRubyOptions < Test::Unit::TestCase
def test_yydebug def test_yydebug
assert_in_out_err(["-ye", ""]) do |r, e| assert_in_out_err(["-ye", ""]) do |r, e|
assert_equal([], r) assert_not_equal([], r)
assert_not_equal([], e) assert_equal([], e)
end end
assert_in_out_err(%w(--yydebug -e) + [""]) do |r, e| assert_in_out_err(%w(--yydebug -e) + [""]) do |r, e|
assert_equal([], r) assert_not_equal([], r)
assert_not_equal([], e) assert_equal([], e)
end end
end end

View file

@ -14,7 +14,7 @@ a\
/^yydestruct.*yymsg/,/#endif/{ /^yydestruct.*yymsg/,/#endif/{
/^yydestruct/{ /^yydestruct/{
/parser/!{ /parser/!{
h H
s/^/ruby_parser_&/ s/^/ruby_parser_&/
s/)$/, parser)/ s/)$/, parser)/
/\*/s/parser)$/struct parser_params *&/ /\*/s/parser)$/struct parser_params *&/
@ -22,7 +22,7 @@ a\
} }
/^#endif/{ /^#endif/{
x x
/^./{ /yydestruct/{
i\ i\
struct parser_params *parser; struct parser_params *parser;
a\ a\
@ -31,6 +31,22 @@ a\
x x
} }
} }
/^yy_stack_print/{
/parser/!{
H
s/)$/, parser)/
/\*/s/parser)$/struct parser_params *&/
}
}
/yy_stack_print.*;/{
x
/yy_stack_print/{
x
s/\(yy_stack_print *\)(\(.*\));/\1(\2, parser);/
x
}
x
}
s/^\([ ]*\)\(yyerror[ ]*([ ]*parser,\)/\1parser_\2/ s/^\([ ]*\)\(yyerror[ ]*([ ]*parser,\)/\1parser_\2/
s!^ *extern char \*getenv();!/* & */! s!^ *extern char \*getenv();!/* & */!
s/^\(#.*\)".*\.tab\.c"/\1"parse.c"/ s/^\(#.*\)".*\.tab\.c"/\1"parse.c"/