зеркало из https://github.com/github/ruby.git
[Universal Parser] Reduce dependence on RArray in parse.y
- Introduce `rb_parser_ary_t` structure to partly eliminate RArray from parse.y - In this patch, `parser_params->tokens` and `parser_params->ast->node_buffer->tokens` are now `rb_parser_ary_t *` - Instead, `ast_node_all_tokens()` internally creates a Ruby Array object from the `rb_parser_ary_t` - Also, delete `rb_ast_tokens()` and `rb_ast_set_tokens()` in node.c - Implement `rb_parser_str_escape()` - This is a port of the `rb_str_escape()` function in string.c - `rb_parser_str_escape()` does not depend on `VALUE` (RString) - Instead, it uses `rb_parser_stirng_t *` - This function works when --dump=y option passed - Because WIP of the universal parser, similar functions like `rb_parser_tokens_free()` exist in both node.c and parse.y. Refactoring them may be needed in some way in the future - Although we considered redesigning the structure: `ast->node_buffer->tokens` into `ast->tokens`, we leave it as it is because `rb_ast_t` is an imemo. (We will address it in the future)
This commit is contained in:
Родитель
f42164e037
Коммит
9a19cfd4cd
27
ast.c
27
ast.c
|
@ -774,10 +774,35 @@ ast_node_last_column(rb_execution_context_t *ec, VALUE self)
|
|||
static VALUE
|
||||
ast_node_all_tokens(rb_execution_context_t *ec, VALUE self)
|
||||
{
|
||||
long i;
|
||||
struct ASTNodeData *data;
|
||||
rb_parser_ary_t *parser_tokens;
|
||||
rb_parser_ast_token_t *parser_token;
|
||||
VALUE str, loc, token, all_tokens;
|
||||
|
||||
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
||||
|
||||
return rb_ast_tokens(data->ast);
|
||||
parser_tokens = data->ast->node_buffer->tokens;
|
||||
if (parser_tokens == NULL) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
all_tokens = rb_ary_new2(parser_tokens->len);
|
||||
for (i = 0; i < parser_tokens->len; i++) {
|
||||
parser_token = parser_tokens->data[i];
|
||||
str = rb_str_new(parser_token->str->ptr, parser_token->str->len);
|
||||
loc = rb_ary_new_from_args(4,
|
||||
INT2FIX(parser_token->loc.beg_pos.lineno),
|
||||
INT2FIX(parser_token->loc.beg_pos.column),
|
||||
INT2FIX(parser_token->loc.end_pos.lineno),
|
||||
INT2FIX(parser_token->loc.end_pos.column)
|
||||
);
|
||||
token = rb_ary_new_from_args(4, INT2FIX(parser_token->id), ID2SYM(rb_intern(parser_token->type_name)), str, loc);
|
||||
rb_ary_push(all_tokens, token);
|
||||
}
|
||||
rb_obj_freeze(all_tokens);
|
||||
|
||||
return all_tokens;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
|
37
node.c
37
node.c
|
@ -69,7 +69,7 @@ rb_node_buffer_new(void)
|
|||
init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1], ruby_xmalloc);
|
||||
init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size), ruby_xmalloc);
|
||||
nb->local_tables = 0;
|
||||
nb->tokens = Qnil;
|
||||
nb->tokens = 0;
|
||||
#ifdef UNIVERSAL_PARSER
|
||||
nb->config = config;
|
||||
#endif
|
||||
|
@ -176,6 +176,24 @@ parser_string_free(rb_ast_t *ast, rb_parser_string_t *str)
|
|||
xfree(str);
|
||||
}
|
||||
|
||||
static void
|
||||
parser_ast_token_free(rb_ast_t *ast, rb_parser_ast_token_t *token)
|
||||
{
|
||||
if (!token) return;
|
||||
parser_string_free(ast, token->str);
|
||||
xfree(token);
|
||||
}
|
||||
|
||||
static void
|
||||
parser_tokens_free(rb_ast_t *ast, rb_parser_ary_t *tokens)
|
||||
{
|
||||
for (long i = 0; i < tokens->len; i++) {
|
||||
parser_ast_token_free(ast, tokens->data[i]);
|
||||
}
|
||||
xfree(tokens->data);
|
||||
xfree(tokens);
|
||||
}
|
||||
|
||||
static void
|
||||
free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
|
||||
{
|
||||
|
@ -228,6 +246,9 @@ free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
|
|||
static void
|
||||
rb_node_buffer_free(rb_ast_t *ast, node_buffer_t *nb)
|
||||
{
|
||||
if (ast->node_buffer && ast->node_buffer->tokens) {
|
||||
parser_tokens_free(ast, ast->node_buffer->tokens);
|
||||
}
|
||||
iterate_node_values(ast, &nb->unmarkable, free_ast_value, NULL);
|
||||
node_buffer_list_free(ast, &nb->unmarkable);
|
||||
node_buffer_list_free(ast, &nb->markable);
|
||||
|
@ -388,8 +409,6 @@ void
|
|||
rb_ast_mark_and_move(rb_ast_t *ast, bool reference_updating)
|
||||
{
|
||||
if (ast->node_buffer) {
|
||||
rb_gc_mark_and_move(&ast->node_buffer->tokens);
|
||||
|
||||
node_buffer_t *nb = ast->node_buffer;
|
||||
iterate_node_values(ast, &nb->markable, mark_and_move_ast_value, NULL);
|
||||
|
||||
|
@ -438,18 +457,6 @@ rb_ast_dispose(rb_ast_t *ast)
|
|||
rb_ast_free(ast);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_ast_tokens(rb_ast_t *ast)
|
||||
{
|
||||
return ast->node_buffer->tokens;
|
||||
}
|
||||
|
||||
void
|
||||
rb_ast_set_tokens(rb_ast_t *ast, VALUE tokens)
|
||||
{
|
||||
RB_OBJ_WRITE(ast, &ast->node_buffer->tokens, tokens);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_node_set_type(NODE *n, enum node_type t)
|
||||
{
|
||||
|
|
4
node.h
4
node.h
|
@ -40,7 +40,7 @@ struct node_buffer_struct {
|
|||
// - text of token
|
||||
// - location info
|
||||
// Array, whose entry is array
|
||||
VALUE tokens;
|
||||
rb_parser_ary_t *tokens;
|
||||
#ifdef UNIVERSAL_PARSER
|
||||
const rb_parser_config_t *config;
|
||||
#endif
|
||||
|
@ -55,7 +55,6 @@ rb_ast_t *rb_ast_new(void);
|
|||
#endif
|
||||
size_t rb_ast_memsize(const rb_ast_t*);
|
||||
void rb_ast_dispose(rb_ast_t*);
|
||||
VALUE rb_ast_tokens(rb_ast_t *ast);
|
||||
#if RUBY_DEBUG
|
||||
void rb_ast_node_type_change(NODE *n, enum node_type type);
|
||||
#endif
|
||||
|
@ -65,7 +64,6 @@ void rb_node_init(NODE *n, enum node_type type);
|
|||
void rb_ast_mark_and_move(rb_ast_t *ast, bool reference_updating);
|
||||
void rb_ast_update_references(rb_ast_t*);
|
||||
void rb_ast_free(rb_ast_t*);
|
||||
void rb_ast_set_tokens(rb_ast_t*, VALUE);
|
||||
NODE *rb_ast_newnode(rb_ast_t*, enum node_type type, size_t size, size_t alignment);
|
||||
void rb_ast_delete_node(rb_ast_t*, NODE *n);
|
||||
rb_ast_id_table_t *rb_ast_new_local_table(rb_ast_t*, int);
|
||||
|
|
526
parse.y
526
parse.y
|
@ -634,7 +634,7 @@ struct parser_params {
|
|||
/* id for terms */
|
||||
int token_id;
|
||||
/* Array for term tokens */
|
||||
VALUE tokens;
|
||||
rb_parser_ary_t *tokens;
|
||||
#else
|
||||
/* Ripper only */
|
||||
|
||||
|
@ -875,170 +875,170 @@ peek_end_expect_token_locations(struct parser_params *p)
|
|||
return p->end_expect_token_locations;
|
||||
}
|
||||
|
||||
static ID
|
||||
parser_token2id(struct parser_params *p, enum yytokentype tok)
|
||||
static const char *
|
||||
parser_token2char(struct parser_params *p, enum yytokentype tok)
|
||||
{
|
||||
switch ((int) tok) {
|
||||
#define TOKEN2ID(tok) case tok: return rb_intern(#tok);
|
||||
#define TOKEN2ID2(tok, name) case tok: return rb_intern(name);
|
||||
TOKEN2ID2(' ', "words_sep")
|
||||
TOKEN2ID2('!', "!")
|
||||
TOKEN2ID2('%', "%");
|
||||
TOKEN2ID2('&', "&");
|
||||
TOKEN2ID2('*', "*");
|
||||
TOKEN2ID2('+', "+");
|
||||
TOKEN2ID2('-', "-");
|
||||
TOKEN2ID2('/', "/");
|
||||
TOKEN2ID2('<', "<");
|
||||
TOKEN2ID2('=', "=");
|
||||
TOKEN2ID2('>', ">");
|
||||
TOKEN2ID2('?', "?");
|
||||
TOKEN2ID2('^', "^");
|
||||
TOKEN2ID2('|', "|");
|
||||
TOKEN2ID2('~', "~");
|
||||
TOKEN2ID2(':', ":");
|
||||
TOKEN2ID2(',', ",");
|
||||
TOKEN2ID2('.', ".");
|
||||
TOKEN2ID2(';', ";");
|
||||
TOKEN2ID2('`', "`");
|
||||
TOKEN2ID2('\n', "nl");
|
||||
TOKEN2ID2('{', "{");
|
||||
TOKEN2ID2('}', "}");
|
||||
TOKEN2ID2('[', "[");
|
||||
TOKEN2ID2(']', "]");
|
||||
TOKEN2ID2('(', "(");
|
||||
TOKEN2ID2(')', ")");
|
||||
TOKEN2ID2('\\', "backslash");
|
||||
TOKEN2ID(keyword_class);
|
||||
TOKEN2ID(keyword_module);
|
||||
TOKEN2ID(keyword_def);
|
||||
TOKEN2ID(keyword_undef);
|
||||
TOKEN2ID(keyword_begin);
|
||||
TOKEN2ID(keyword_rescue);
|
||||
TOKEN2ID(keyword_ensure);
|
||||
TOKEN2ID(keyword_end);
|
||||
TOKEN2ID(keyword_if);
|
||||
TOKEN2ID(keyword_unless);
|
||||
TOKEN2ID(keyword_then);
|
||||
TOKEN2ID(keyword_elsif);
|
||||
TOKEN2ID(keyword_else);
|
||||
TOKEN2ID(keyword_case);
|
||||
TOKEN2ID(keyword_when);
|
||||
TOKEN2ID(keyword_while);
|
||||
TOKEN2ID(keyword_until);
|
||||
TOKEN2ID(keyword_for);
|
||||
TOKEN2ID(keyword_break);
|
||||
TOKEN2ID(keyword_next);
|
||||
TOKEN2ID(keyword_redo);
|
||||
TOKEN2ID(keyword_retry);
|
||||
TOKEN2ID(keyword_in);
|
||||
TOKEN2ID(keyword_do);
|
||||
TOKEN2ID(keyword_do_cond);
|
||||
TOKEN2ID(keyword_do_block);
|
||||
TOKEN2ID(keyword_do_LAMBDA);
|
||||
TOKEN2ID(keyword_return);
|
||||
TOKEN2ID(keyword_yield);
|
||||
TOKEN2ID(keyword_super);
|
||||
TOKEN2ID(keyword_self);
|
||||
TOKEN2ID(keyword_nil);
|
||||
TOKEN2ID(keyword_true);
|
||||
TOKEN2ID(keyword_false);
|
||||
TOKEN2ID(keyword_and);
|
||||
TOKEN2ID(keyword_or);
|
||||
TOKEN2ID(keyword_not);
|
||||
TOKEN2ID(modifier_if);
|
||||
TOKEN2ID(modifier_unless);
|
||||
TOKEN2ID(modifier_while);
|
||||
TOKEN2ID(modifier_until);
|
||||
TOKEN2ID(modifier_rescue);
|
||||
TOKEN2ID(keyword_alias);
|
||||
TOKEN2ID(keyword_defined);
|
||||
TOKEN2ID(keyword_BEGIN);
|
||||
TOKEN2ID(keyword_END);
|
||||
TOKEN2ID(keyword__LINE__);
|
||||
TOKEN2ID(keyword__FILE__);
|
||||
TOKEN2ID(keyword__ENCODING__);
|
||||
TOKEN2ID(tIDENTIFIER);
|
||||
TOKEN2ID(tFID);
|
||||
TOKEN2ID(tGVAR);
|
||||
TOKEN2ID(tIVAR);
|
||||
TOKEN2ID(tCONSTANT);
|
||||
TOKEN2ID(tCVAR);
|
||||
TOKEN2ID(tLABEL);
|
||||
TOKEN2ID(tINTEGER);
|
||||
TOKEN2ID(tFLOAT);
|
||||
TOKEN2ID(tRATIONAL);
|
||||
TOKEN2ID(tIMAGINARY);
|
||||
TOKEN2ID(tCHAR);
|
||||
TOKEN2ID(tNTH_REF);
|
||||
TOKEN2ID(tBACK_REF);
|
||||
TOKEN2ID(tSTRING_CONTENT);
|
||||
TOKEN2ID(tREGEXP_END);
|
||||
TOKEN2ID(tDUMNY_END);
|
||||
TOKEN2ID(tSP);
|
||||
TOKEN2ID(tUPLUS);
|
||||
TOKEN2ID(tUMINUS);
|
||||
TOKEN2ID(tPOW);
|
||||
TOKEN2ID(tCMP);
|
||||
TOKEN2ID(tEQ);
|
||||
TOKEN2ID(tEQQ);
|
||||
TOKEN2ID(tNEQ);
|
||||
TOKEN2ID(tGEQ);
|
||||
TOKEN2ID(tLEQ);
|
||||
TOKEN2ID(tANDOP);
|
||||
TOKEN2ID(tOROP);
|
||||
TOKEN2ID(tMATCH);
|
||||
TOKEN2ID(tNMATCH);
|
||||
TOKEN2ID(tDOT2);
|
||||
TOKEN2ID(tDOT3);
|
||||
TOKEN2ID(tBDOT2);
|
||||
TOKEN2ID(tBDOT3);
|
||||
TOKEN2ID(tAREF);
|
||||
TOKEN2ID(tASET);
|
||||
TOKEN2ID(tLSHFT);
|
||||
TOKEN2ID(tRSHFT);
|
||||
TOKEN2ID(tANDDOT);
|
||||
TOKEN2ID(tCOLON2);
|
||||
TOKEN2ID(tCOLON3);
|
||||
TOKEN2ID(tOP_ASGN);
|
||||
TOKEN2ID(tASSOC);
|
||||
TOKEN2ID(tLPAREN);
|
||||
TOKEN2ID(tLPAREN_ARG);
|
||||
TOKEN2ID(tRPAREN);
|
||||
TOKEN2ID(tLBRACK);
|
||||
TOKEN2ID(tLBRACE);
|
||||
TOKEN2ID(tLBRACE_ARG);
|
||||
TOKEN2ID(tSTAR);
|
||||
TOKEN2ID(tDSTAR);
|
||||
TOKEN2ID(tAMPER);
|
||||
TOKEN2ID(tLAMBDA);
|
||||
TOKEN2ID(tSYMBEG);
|
||||
TOKEN2ID(tSTRING_BEG);
|
||||
TOKEN2ID(tXSTRING_BEG);
|
||||
TOKEN2ID(tREGEXP_BEG);
|
||||
TOKEN2ID(tWORDS_BEG);
|
||||
TOKEN2ID(tQWORDS_BEG);
|
||||
TOKEN2ID(tSYMBOLS_BEG);
|
||||
TOKEN2ID(tQSYMBOLS_BEG);
|
||||
TOKEN2ID(tSTRING_END);
|
||||
TOKEN2ID(tSTRING_DEND);
|
||||
TOKEN2ID(tSTRING_DBEG);
|
||||
TOKEN2ID(tSTRING_DVAR);
|
||||
TOKEN2ID(tLAMBEG);
|
||||
TOKEN2ID(tLABEL_END);
|
||||
TOKEN2ID(tIGNORED_NL);
|
||||
TOKEN2ID(tCOMMENT);
|
||||
TOKEN2ID(tEMBDOC_BEG);
|
||||
TOKEN2ID(tEMBDOC);
|
||||
TOKEN2ID(tEMBDOC_END);
|
||||
TOKEN2ID(tHEREDOC_BEG);
|
||||
TOKEN2ID(tHEREDOC_END);
|
||||
TOKEN2ID(k__END__);
|
||||
TOKEN2ID(tLOWEST);
|
||||
TOKEN2ID(tUMINUS_NUM);
|
||||
TOKEN2ID(tLAST_TOKEN);
|
||||
#undef TOKEN2ID
|
||||
#undef TOKEN2ID2
|
||||
#define TOKEN2CHAR(tok) case tok: return (#tok);
|
||||
#define TOKEN2CHAR2(tok, name) case tok: return (name);
|
||||
TOKEN2CHAR2(' ', "word_sep");
|
||||
TOKEN2CHAR2('!', "!")
|
||||
TOKEN2CHAR2('%', "%");
|
||||
TOKEN2CHAR2('&', "&");
|
||||
TOKEN2CHAR2('*', "*");
|
||||
TOKEN2CHAR2('+', "+");
|
||||
TOKEN2CHAR2('-', "-");
|
||||
TOKEN2CHAR2('/', "/");
|
||||
TOKEN2CHAR2('<', "<");
|
||||
TOKEN2CHAR2('=', "=");
|
||||
TOKEN2CHAR2('>', ">");
|
||||
TOKEN2CHAR2('?', "?");
|
||||
TOKEN2CHAR2('^', "^");
|
||||
TOKEN2CHAR2('|', "|");
|
||||
TOKEN2CHAR2('~', "~");
|
||||
TOKEN2CHAR2(':', ":");
|
||||
TOKEN2CHAR2(',', ",");
|
||||
TOKEN2CHAR2('.', ".");
|
||||
TOKEN2CHAR2(';', ";");
|
||||
TOKEN2CHAR2('`', "`");
|
||||
TOKEN2CHAR2('\n', "nl");
|
||||
TOKEN2CHAR2('{', "\"{\"");
|
||||
TOKEN2CHAR2('}', "\"}\"");
|
||||
TOKEN2CHAR2('[', "\"[\"");
|
||||
TOKEN2CHAR2(']', "\"]\"");
|
||||
TOKEN2CHAR2('(', "\"(\"");
|
||||
TOKEN2CHAR2(')', "\")\"");
|
||||
TOKEN2CHAR2('\\', "backslash");
|
||||
TOKEN2CHAR(keyword_class);
|
||||
TOKEN2CHAR(keyword_module);
|
||||
TOKEN2CHAR(keyword_def);
|
||||
TOKEN2CHAR(keyword_undef);
|
||||
TOKEN2CHAR(keyword_begin);
|
||||
TOKEN2CHAR(keyword_rescue);
|
||||
TOKEN2CHAR(keyword_ensure);
|
||||
TOKEN2CHAR(keyword_end);
|
||||
TOKEN2CHAR(keyword_if);
|
||||
TOKEN2CHAR(keyword_unless);
|
||||
TOKEN2CHAR(keyword_then);
|
||||
TOKEN2CHAR(keyword_elsif);
|
||||
TOKEN2CHAR(keyword_else);
|
||||
TOKEN2CHAR(keyword_case);
|
||||
TOKEN2CHAR(keyword_when);
|
||||
TOKEN2CHAR(keyword_while);
|
||||
TOKEN2CHAR(keyword_until);
|
||||
TOKEN2CHAR(keyword_for);
|
||||
TOKEN2CHAR(keyword_break);
|
||||
TOKEN2CHAR(keyword_next);
|
||||
TOKEN2CHAR(keyword_redo);
|
||||
TOKEN2CHAR(keyword_retry);
|
||||
TOKEN2CHAR(keyword_in);
|
||||
TOKEN2CHAR(keyword_do);
|
||||
TOKEN2CHAR(keyword_do_cond);
|
||||
TOKEN2CHAR(keyword_do_block);
|
||||
TOKEN2CHAR(keyword_do_LAMBDA);
|
||||
TOKEN2CHAR(keyword_return);
|
||||
TOKEN2CHAR(keyword_yield);
|
||||
TOKEN2CHAR(keyword_super);
|
||||
TOKEN2CHAR(keyword_self);
|
||||
TOKEN2CHAR(keyword_nil);
|
||||
TOKEN2CHAR(keyword_true);
|
||||
TOKEN2CHAR(keyword_false);
|
||||
TOKEN2CHAR(keyword_and);
|
||||
TOKEN2CHAR(keyword_or);
|
||||
TOKEN2CHAR(keyword_not);
|
||||
TOKEN2CHAR(modifier_if);
|
||||
TOKEN2CHAR(modifier_unless);
|
||||
TOKEN2CHAR(modifier_while);
|
||||
TOKEN2CHAR(modifier_until);
|
||||
TOKEN2CHAR(modifier_rescue);
|
||||
TOKEN2CHAR(keyword_alias);
|
||||
TOKEN2CHAR(keyword_defined);
|
||||
TOKEN2CHAR(keyword_BEGIN);
|
||||
TOKEN2CHAR(keyword_END);
|
||||
TOKEN2CHAR(keyword__LINE__);
|
||||
TOKEN2CHAR(keyword__FILE__);
|
||||
TOKEN2CHAR(keyword__ENCODING__);
|
||||
TOKEN2CHAR(tIDENTIFIER);
|
||||
TOKEN2CHAR(tFID);
|
||||
TOKEN2CHAR(tGVAR);
|
||||
TOKEN2CHAR(tIVAR);
|
||||
TOKEN2CHAR(tCONSTANT);
|
||||
TOKEN2CHAR(tCVAR);
|
||||
TOKEN2CHAR(tLABEL);
|
||||
TOKEN2CHAR(tINTEGER);
|
||||
TOKEN2CHAR(tFLOAT);
|
||||
TOKEN2CHAR(tRATIONAL);
|
||||
TOKEN2CHAR(tIMAGINARY);
|
||||
TOKEN2CHAR(tCHAR);
|
||||
TOKEN2CHAR(tNTH_REF);
|
||||
TOKEN2CHAR(tBACK_REF);
|
||||
TOKEN2CHAR(tSTRING_CONTENT);
|
||||
TOKEN2CHAR(tREGEXP_END);
|
||||
TOKEN2CHAR(tDUMNY_END);
|
||||
TOKEN2CHAR(tSP);
|
||||
TOKEN2CHAR(tUPLUS);
|
||||
TOKEN2CHAR(tUMINUS);
|
||||
TOKEN2CHAR(tPOW);
|
||||
TOKEN2CHAR(tCMP);
|
||||
TOKEN2CHAR(tEQ);
|
||||
TOKEN2CHAR(tEQQ);
|
||||
TOKEN2CHAR(tNEQ);
|
||||
TOKEN2CHAR(tGEQ);
|
||||
TOKEN2CHAR(tLEQ);
|
||||
TOKEN2CHAR(tANDOP);
|
||||
TOKEN2CHAR(tOROP);
|
||||
TOKEN2CHAR(tMATCH);
|
||||
TOKEN2CHAR(tNMATCH);
|
||||
TOKEN2CHAR(tDOT2);
|
||||
TOKEN2CHAR(tDOT3);
|
||||
TOKEN2CHAR(tBDOT2);
|
||||
TOKEN2CHAR(tBDOT3);
|
||||
TOKEN2CHAR(tAREF);
|
||||
TOKEN2CHAR(tASET);
|
||||
TOKEN2CHAR(tLSHFT);
|
||||
TOKEN2CHAR(tRSHFT);
|
||||
TOKEN2CHAR(tANDDOT);
|
||||
TOKEN2CHAR(tCOLON2);
|
||||
TOKEN2CHAR(tCOLON3);
|
||||
TOKEN2CHAR(tOP_ASGN);
|
||||
TOKEN2CHAR(tASSOC);
|
||||
TOKEN2CHAR(tLPAREN);
|
||||
TOKEN2CHAR(tLPAREN_ARG);
|
||||
TOKEN2CHAR(tRPAREN);
|
||||
TOKEN2CHAR(tLBRACK);
|
||||
TOKEN2CHAR(tLBRACE);
|
||||
TOKEN2CHAR(tLBRACE_ARG);
|
||||
TOKEN2CHAR(tSTAR);
|
||||
TOKEN2CHAR(tDSTAR);
|
||||
TOKEN2CHAR(tAMPER);
|
||||
TOKEN2CHAR(tLAMBDA);
|
||||
TOKEN2CHAR(tSYMBEG);
|
||||
TOKEN2CHAR(tSTRING_BEG);
|
||||
TOKEN2CHAR(tXSTRING_BEG);
|
||||
TOKEN2CHAR(tREGEXP_BEG);
|
||||
TOKEN2CHAR(tWORDS_BEG);
|
||||
TOKEN2CHAR(tQWORDS_BEG);
|
||||
TOKEN2CHAR(tSYMBOLS_BEG);
|
||||
TOKEN2CHAR(tQSYMBOLS_BEG);
|
||||
TOKEN2CHAR(tSTRING_END);
|
||||
TOKEN2CHAR(tSTRING_DEND);
|
||||
TOKEN2CHAR(tSTRING_DBEG);
|
||||
TOKEN2CHAR(tSTRING_DVAR);
|
||||
TOKEN2CHAR(tLAMBEG);
|
||||
TOKEN2CHAR(tLABEL_END);
|
||||
TOKEN2CHAR(tIGNORED_NL);
|
||||
TOKEN2CHAR(tCOMMENT);
|
||||
TOKEN2CHAR(tEMBDOC_BEG);
|
||||
TOKEN2CHAR(tEMBDOC);
|
||||
TOKEN2CHAR(tEMBDOC_END);
|
||||
TOKEN2CHAR(tHEREDOC_BEG);
|
||||
TOKEN2CHAR(tHEREDOC_END);
|
||||
TOKEN2CHAR(k__END__);
|
||||
TOKEN2CHAR(tLOWEST);
|
||||
TOKEN2CHAR(tUMINUS_NUM);
|
||||
TOKEN2CHAR(tLAST_TOKEN);
|
||||
#undef TOKEN2CHAR
|
||||
#undef TOKEN2CHAR2
|
||||
}
|
||||
|
||||
rb_bug("parser_token2id: unknown token %d", tok);
|
||||
|
@ -2565,8 +2565,8 @@ rb_parser_str_resize(struct parser_params *p, rb_parser_string_t *str, long len)
|
|||
return str;
|
||||
}
|
||||
|
||||
#ifndef UNIVERSAL_PARSER
|
||||
#ifndef RIPPER
|
||||
#ifndef UNIVERSAL_PARSER
|
||||
# define PARSER_ENC_STRING_GETMEM(str, ptrvar, lenvar, encvar) \
|
||||
((ptrvar) = str->ptr, \
|
||||
(lenvar) = str->len, \
|
||||
|
@ -2587,7 +2587,73 @@ rb_parser_string_hash_cmp(rb_parser_string_t *str1, rb_parser_string_t *str2)
|
|||
memcmp(ptr1, ptr2, len1) != 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void
|
||||
rb_parser_ary_extend(rb_parser_t *p, rb_parser_ary_t *ary, long len)
|
||||
{
|
||||
long i;
|
||||
if (ary->capa < len) {
|
||||
ary->capa = len;
|
||||
ary->data = xrealloc(ary->data, sizeof(void *) * len);
|
||||
for (i = ary->len; i < len; i++) {
|
||||
ary->data[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rb_parser_ary_t *
|
||||
rb_parser_ary_new_capa(rb_parser_t *p, long len)
|
||||
{
|
||||
if (len < 0) {
|
||||
rb_bug("negative array size (or size too big): %ld", len);
|
||||
}
|
||||
rb_parser_ary_t *ary = xcalloc(1, sizeof(rb_parser_ary_t));
|
||||
ary->len = 0;
|
||||
ary->capa = len;
|
||||
if (0 < len) {
|
||||
ary->data = (rb_parser_ast_token_t **)xcalloc(len, sizeof(rb_parser_ast_token_t *));
|
||||
}
|
||||
else {
|
||||
ary->data = NULL;
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
#define rb_parser_ary_new2 rb_parser_ary_new_capa
|
||||
|
||||
inline static rb_parser_ary_t *
|
||||
rb_parser_ary_new(rb_parser_t *p)
|
||||
{
|
||||
return rb_parser_ary_new_capa(p, 0);
|
||||
}
|
||||
|
||||
static rb_parser_ary_t *
|
||||
rb_parser_ary_push(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ast_token_t *val)
|
||||
{
|
||||
if (ary->len == ary->capa) {
|
||||
rb_parser_ary_extend(p, ary, ary->len == 0 ? 1 : ary->len * 2);
|
||||
}
|
||||
ary->data[ary->len++] = val;
|
||||
return ary;
|
||||
}
|
||||
|
||||
static void
|
||||
rb_parser_ast_token_free(rb_parser_t *p, rb_parser_ast_token_t *token)
|
||||
{
|
||||
if (!token) return;
|
||||
rb_parser_string_free(p, token->str);
|
||||
xfree(token);
|
||||
}
|
||||
|
||||
static void
|
||||
rb_parser_tokens_free(rb_parser_t *p, rb_parser_ary_t *tokens)
|
||||
{
|
||||
for (long i = 0; i < tokens->len; i++) {
|
||||
rb_parser_ast_token_free(p, tokens->data[i]);
|
||||
}
|
||||
xfree(tokens);
|
||||
}
|
||||
|
||||
#endif /* !RIPPER */
|
||||
%}
|
||||
|
||||
%expect 0
|
||||
|
@ -7035,35 +7101,100 @@ parser_has_token(struct parser_params *p)
|
|||
return pcur > ptok;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
code_loc_to_ary(struct parser_params *p, const rb_code_location_t *loc)
|
||||
static const char *
|
||||
escaped_char(int c)
|
||||
{
|
||||
VALUE ary = rb_ary_new_from_args(4,
|
||||
INT2NUM(loc->beg_pos.lineno), INT2NUM(loc->beg_pos.column),
|
||||
INT2NUM(loc->end_pos.lineno), INT2NUM(loc->end_pos.column));
|
||||
rb_obj_freeze(ary);
|
||||
switch (c) {
|
||||
case '"': return "\\\"";
|
||||
case '\\': return "\\\\";
|
||||
case '\0': return "\\0";
|
||||
case '\n': return "\\n";
|
||||
case '\r': return "\\r";
|
||||
case '\t': return "\\t";
|
||||
case '\f': return "\\f";
|
||||
case '\013': return "\\v";
|
||||
case '\010': return "\\b";
|
||||
case '\007': return "\\a";
|
||||
case '\033': return "\\e";
|
||||
case '\x7f': return "\\c?";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ary;
|
||||
static rb_parser_string_t *
|
||||
rb_parser_str_escape(struct parser_params *p, rb_parser_string_t *str)
|
||||
{
|
||||
rb_encoding *enc = p->enc;
|
||||
const char *ptr = str->ptr;
|
||||
const char *pend = ptr + str->len;
|
||||
const char *prev = ptr;
|
||||
char charbuf[5] = {'\\', 'x', 0, 0, 0};
|
||||
rb_parser_string_t * result = rb_parser_string_new(p, 0, 0);
|
||||
int asciicompat = rb_enc_asciicompat(enc);
|
||||
|
||||
while (ptr < pend) {
|
||||
unsigned int c;
|
||||
const char *cc;
|
||||
int n = rb_enc_precise_mbclen(ptr, pend, enc);
|
||||
if (!MBCLEN_CHARFOUND_P(n)) {
|
||||
if (ptr > prev) rb_parser_str_buf_cat(p, result, prev, ptr - prev);
|
||||
n = rb_enc_mbminlen(enc);
|
||||
if (pend < ptr + n)
|
||||
n = (int)(pend - ptr);
|
||||
while (n--) {
|
||||
c = *ptr & 0xf0 >> 4;
|
||||
charbuf[2] = (c < 10) ? '0' + c : 'A' + c - 10;
|
||||
c = *ptr & 0x0f;
|
||||
charbuf[3] = (c < 10) ? '0' + c : 'A' + c - 10;
|
||||
rb_parser_str_buf_cat(p, result, charbuf, 4);
|
||||
prev = ++ptr;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
n = MBCLEN_CHARFOUND_LEN(n);
|
||||
c = rb_enc_mbc_to_codepoint(ptr, pend, enc);
|
||||
ptr += n;
|
||||
cc = escaped_char(c);
|
||||
if (cc) {
|
||||
if (ptr - n > prev) rb_parser_str_buf_cat(p, result, prev, ptr - n - prev);
|
||||
rb_parser_str_buf_cat(p, result, cc, strlen(cc));
|
||||
prev = ptr;
|
||||
}
|
||||
else if (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c)) {
|
||||
}
|
||||
else {
|
||||
if (ptr - n > prev) {
|
||||
rb_parser_str_buf_cat(p, result, prev, ptr - n - prev);
|
||||
prev = ptr - n;
|
||||
}
|
||||
rb_parser_str_buf_cat(p, result, prev, ptr - prev);
|
||||
prev = ptr;
|
||||
}
|
||||
}
|
||||
if (ptr > prev) rb_parser_str_buf_cat(p, result, prev, ptr - prev);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
parser_append_tokens(struct parser_params *p, VALUE str, enum yytokentype t, int line)
|
||||
parser_append_tokens(struct parser_params *p, rb_parser_string_t *str, enum yytokentype t, int line)
|
||||
{
|
||||
VALUE ary;
|
||||
int token_id;
|
||||
|
||||
ary = rb_ary_new2(4);
|
||||
token_id = p->token_id;
|
||||
rb_ary_push(ary, INT2FIX(token_id));
|
||||
rb_ary_push(ary, ID2SYM(parser_token2id(p, t)));
|
||||
rb_ary_push(ary, str);
|
||||
rb_ary_push(ary, code_loc_to_ary(p, p->yylloc));
|
||||
rb_obj_freeze(ary);
|
||||
rb_ary_push(p->tokens, ary);
|
||||
rb_parser_ast_token_t *token = xcalloc(1, sizeof(rb_parser_ast_token_t));
|
||||
token->id = p->token_id;
|
||||
token->type_name = parser_token2char(p, t);
|
||||
token->str = str;
|
||||
token->loc.beg_pos = p->yylloc->beg_pos;
|
||||
token->loc.end_pos = p->yylloc->end_pos;
|
||||
rb_parser_ary_push(p, p->tokens, token);
|
||||
p->token_id++;
|
||||
|
||||
if (p->debug) {
|
||||
rb_parser_printf(p, "Append tokens (line: %d) %"PRIsVALUE"\n", line, ary);
|
||||
rb_parser_string_t *str_escaped = rb_parser_str_escape(p, str);
|
||||
rb_parser_printf(p, "Append tokens (line: %d) [%d, :%s, \"%s\", [%d, %d, %d, %d]]\n",
|
||||
line, token->id, token->type_name, str_escaped->ptr,
|
||||
token->loc.beg_pos.lineno, token->loc.beg_pos.column,
|
||||
token->loc.end_pos.lineno, token->loc.end_pos.column);
|
||||
rb_parser_string_free(p, str_escaped);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7077,7 +7208,7 @@ parser_dispatch_scan_event(struct parser_params *p, enum yytokentype t, int line
|
|||
RUBY_SET_YYLLOC(*p->yylloc);
|
||||
|
||||
if (p->keep_tokens) {
|
||||
VALUE str = STR_NEW(p->lex.ptok, p->lex.pcur - p->lex.ptok);
|
||||
rb_parser_string_t *str = rb_parser_encoding_string_new(p, p->lex.ptok, p->lex.pcur - p->lex.ptok, p->enc);
|
||||
parser_append_tokens(p, str, t, line);
|
||||
}
|
||||
|
||||
|
@ -7095,7 +7226,8 @@ parser_dispatch_delayed_token(struct parser_params *p, enum yytokentype t, int l
|
|||
RUBY_SET_YYLLOC_OF_DELAYED_TOKEN(*p->yylloc);
|
||||
|
||||
if (p->keep_tokens) {
|
||||
parser_append_tokens(p, p->delayed.token, t, line);
|
||||
rb_parser_string_t *str = rb_str_to_parser_string(p, p->delayed.token);
|
||||
parser_append_tokens(p, str, t, line);
|
||||
}
|
||||
|
||||
p->delayed.token = Qnil;
|
||||
|
@ -7607,7 +7739,7 @@ yycompile0(VALUE arg)
|
|||
tree = NEW_NIL(&NULL_LOC);
|
||||
}
|
||||
else {
|
||||
VALUE tokens = p->tokens;
|
||||
rb_parser_ary_t *tokens = p->tokens;
|
||||
NODE *prelude;
|
||||
NODE *body = parser_append_options(p, RNODE_SCOPE(tree)->nd_body);
|
||||
prelude = block_append(p, p->eval_tree_begin, body);
|
||||
|
@ -7615,8 +7747,8 @@ yycompile0(VALUE arg)
|
|||
p->ast->body.frozen_string_literal = p->frozen_string_literal;
|
||||
p->ast->body.coverage_enabled = cov;
|
||||
if (p->keep_tokens) {
|
||||
rb_obj_freeze(tokens);
|
||||
rb_ast_set_tokens(p->ast, tokens);
|
||||
p->ast->node_buffer->tokens = tokens;
|
||||
p->tokens = NULL;
|
||||
}
|
||||
}
|
||||
p->ast->body.root = tree;
|
||||
|
@ -9230,7 +9362,7 @@ parser_dispatch_heredoc_end(struct parser_params *p, int line)
|
|||
dispatch_delayed_token(p, tSTRING_CONTENT);
|
||||
|
||||
if (p->keep_tokens) {
|
||||
VALUE str = STR_NEW(p->lex.ptok, p->lex.pend - p->lex.ptok);
|
||||
rb_parser_string_t *str = rb_parser_encoding_string_new(p, p->lex.ptok, p->lex.pend - p->lex.ptok, p->enc);
|
||||
RUBY_SET_YYLLOC_OF_HEREDOC_END(*p->yylloc);
|
||||
parser_append_tokens(p, str, tHEREDOC_END, line);
|
||||
}
|
||||
|
@ -15973,7 +16105,7 @@ parser_initialize(struct parser_params *p)
|
|||
p->error_buffer = Qfalse;
|
||||
p->end_expect_token_locations = NULL;
|
||||
p->token_id = 0;
|
||||
p->tokens = Qnil;
|
||||
p->tokens = NULL;
|
||||
#else
|
||||
p->result = Qnil;
|
||||
p->parsing_thread = Qnil;
|
||||
|
@ -16006,7 +16138,6 @@ rb_ruby_parser_mark(void *ptr)
|
|||
#ifndef RIPPER
|
||||
rb_gc_mark(p->debug_lines);
|
||||
rb_gc_mark(p->error_buffer);
|
||||
rb_gc_mark(p->tokens);
|
||||
#else
|
||||
rb_gc_mark(p->value);
|
||||
rb_gc_mark(p->result);
|
||||
|
@ -16028,6 +16159,12 @@ rb_ruby_parser_free(void *ptr)
|
|||
struct parser_params *p = (struct parser_params*)ptr;
|
||||
struct local_vars *local, *prev;
|
||||
|
||||
#ifndef RIPPER
|
||||
if (p->tokens) {
|
||||
rb_parser_tokens_free(p, p->tokens);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p->tokenbuf) {
|
||||
ruby_sized_xfree(p->tokenbuf, p->toksiz);
|
||||
}
|
||||
|
@ -16145,8 +16282,7 @@ void
|
|||
rb_ruby_parser_keep_tokens(rb_parser_t *p)
|
||||
{
|
||||
p->keep_tokens = 1;
|
||||
// TODO
|
||||
p->tokens = rb_ary_new();
|
||||
p->tokens = rb_parser_ary_new_capa(p, 10);
|
||||
}
|
||||
|
||||
#ifndef UNIVERSAL_PARSER
|
||||
|
|
|
@ -461,6 +461,27 @@ str_coderange_scan_restartable(const char *s, const char *e, void *enc, int *cr)
|
|||
return rb_str_coderange_scan_restartable(s, e, (rb_encoding *)enc, cr);
|
||||
}
|
||||
|
||||
static int
|
||||
enc_mbminlen(void *enc)
|
||||
{
|
||||
return rb_enc_mbminlen((rb_encoding *)enc);
|
||||
}
|
||||
|
||||
static bool
|
||||
enc_isascii(OnigCodePoint c, void *enc)
|
||||
{
|
||||
return rb_enc_isascii(c, (rb_encoding *)enc);
|
||||
}
|
||||
|
||||
static OnigCodePoint
|
||||
enc_mbc_to_codepoint(const char *p, const char *e, void *enc)
|
||||
{
|
||||
const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p);
|
||||
const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e);
|
||||
|
||||
return ONIGENC_MBC_TO_CODE((rb_encoding *)enc, up, ue);
|
||||
}
|
||||
|
||||
VALUE rb_io_gets_internal(VALUE io);
|
||||
extern VALUE rb_eArgError;
|
||||
extern VALUE rb_mRubyVMFrozenCore;
|
||||
|
@ -596,6 +617,10 @@ static const rb_parser_config_t rb_global_parser_config = {
|
|||
.encoding_set = encoding_set,
|
||||
.encoding_is_ascii8bit = encoding_is_ascii8bit,
|
||||
.usascii_encoding = usascii_encoding,
|
||||
.enc_coderange_broken = ENC_CODERANGE_BROKEN,
|
||||
.enc_mbminlen = enc_mbminlen,
|
||||
.enc_isascii = enc_isascii,
|
||||
.enc_mbc_to_codepoint = enc_mbc_to_codepoint,
|
||||
|
||||
.ractor_make_shareable = rb_ractor_make_shareable,
|
||||
|
||||
|
|
20
rubyparser.h
20
rubyparser.h
|
@ -189,6 +189,22 @@ typedef struct rb_code_location_struct {
|
|||
rb_code_position_t end_pos;
|
||||
} rb_code_location_t;
|
||||
|
||||
typedef struct rb_parser_ast_token {
|
||||
int id;
|
||||
const char *type_name;
|
||||
rb_parser_string_t *str;
|
||||
rb_code_location_t loc;
|
||||
} rb_parser_ast_token_t;
|
||||
|
||||
/*
|
||||
* Array-like object for parser
|
||||
*/
|
||||
typedef struct rb_parser_ary {
|
||||
rb_parser_ast_token_t **data;
|
||||
long len; // current size
|
||||
long capa; // capacity
|
||||
} rb_parser_ary_t;
|
||||
|
||||
/* Header part of AST Node */
|
||||
typedef struct RNode {
|
||||
VALUE flags;
|
||||
|
@ -1340,6 +1356,10 @@ typedef struct rb_parser_config_struct {
|
|||
void (*encoding_set)(VALUE obj, int encindex);
|
||||
int (*encoding_is_ascii8bit)(VALUE obj);
|
||||
rb_encoding *(*usascii_encoding)(void);
|
||||
int enc_coderange_broken;
|
||||
int (*enc_mbminlen)(rb_encoding *enc);
|
||||
bool (*enc_isascii)(OnigCodePoint c, rb_encoding *enc);
|
||||
OnigCodePoint (*enc_mbc_to_codepoint)(const char *p, const char *e, rb_encoding *enc);
|
||||
|
||||
/* Ractor */
|
||||
VALUE (*ractor_make_shareable)(VALUE obj);
|
||||
|
|
|
@ -293,6 +293,9 @@ struct rb_imemo_tmpbuf_struct {
|
|||
#define rb_mRubyVMFrozenCore p->config->mRubyVMFrozenCore()
|
||||
#undef rb_long2int
|
||||
#define rb_long2int p->config->long2int
|
||||
#define rb_enc_mbminlen p->config->enc_mbminlen
|
||||
#define rb_enc_isascii p->config->enc_isascii
|
||||
#define rb_enc_mbc_to_codepoint p->config->enc_mbc_to_codepoint
|
||||
|
||||
#define rb_node_case_when_optimizable_literal p->config->node_case_when_optimizable_literal
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче