15#define PM_TAB_WHITESPACE_SIZE 8
17#ifndef PM_DEBUG_LOGGING
23#define PM_DEBUG_LOGGING 0
75 fprintf(stderr,
"CONTEXTS: ");
77 if (context_node != NULL) {
78 while (context_node != NULL) {
79 fprintf(stderr,
"%s", debug_context(context_node->
context));
80 context_node = context_node->
prev;
81 if (context_node != NULL) {
82 fprintf(stderr,
" <- ");
86 fprintf(stderr,
"NONE");
89 fprintf(stderr,
"\n");
95 pm_prettyprint(&output_buffer, parser, node);
97 fprintf(stderr,
"%.*s", (
int) output_buffer.
length, output_buffer.
value);
98 pm_buffer_free(&output_buffer);
106 while (lex_mode != NULL) {
110 fprintf(stderr,
" <- ");
113 switch (lex_mode->
mode) {
114 case PM_LEX_DEFAULT: fprintf(stderr,
"DEFAULT");
break;
115 case PM_LEX_EMBEXPR: fprintf(stderr,
"EMBEXPR");
break;
116 case PM_LEX_EMBVAR: fprintf(stderr,
"EMBVAR");
break;
117 case PM_LEX_HEREDOC: fprintf(stderr,
"HEREDOC");
break;
118 case PM_LEX_LIST: fprintf(stderr,
"LIST (terminator=%c, interpolation=%d)", lex_mode->
as.list.
terminator, lex_mode->
as.list.
interpolation);
break;
119 case PM_LEX_REGEXP: fprintf(stderr,
"REGEXP (terminator=%c)", lex_mode->
as.regexp.
terminator);
break;
120 case PM_LEX_STRING: fprintf(stderr,
"STRING (terminator=%c, interpolation=%d)", lex_mode->
as.string.
terminator, lex_mode->
as.string.
interpolation);
break;
123 lex_mode = lex_mode->
prev;
126 fprintf(stderr,
"\n");
131 fprintf(stderr,
"STATE: ");
134 if (parser->
lex_state == PM_LEX_STATE_NONE) {
135 fprintf(stderr,
"NONE\n");
139#define CHECK_STATE(state) \
140 if (parser->lex_state & state) { \
141 if (!first) fprintf(stderr, "|"); \
142 fprintf(stderr, "%s", #state); \
146 CHECK_STATE(PM_LEX_STATE_BEG)
147 CHECK_STATE(PM_LEX_STATE_END)
148 CHECK_STATE(PM_LEX_STATE_ENDARG)
149 CHECK_STATE(PM_LEX_STATE_ENDFN)
150 CHECK_STATE(PM_LEX_STATE_ARG)
151 CHECK_STATE(PM_LEX_STATE_CMDARG)
152 CHECK_STATE(PM_LEX_STATE_MID)
153 CHECK_STATE(PM_LEX_STATE_FNAME)
154 CHECK_STATE(PM_LEX_STATE_DOT)
155 CHECK_STATE(PM_LEX_STATE_CLASS)
156 CHECK_STATE(PM_LEX_STATE_LABEL)
157 CHECK_STATE(PM_LEX_STATE_LABELED)
158 CHECK_STATE(PM_LEX_STATE_FITEM)
162 fprintf(stderr,
"\n");
167 fprintf(stderr,
"%s: \"%.*s\"\n",
pm_token_type_to_str(token->type), (
int) (token->end - token->start), token->start);
173#define MIN(a,b) (((a)<(b))?(a):(b))
174#define MAX(a,b) (((a)>(b))?(a):(b))
185lex_mode_incrementor(
const uint8_t start) {
202lex_mode_terminator(
const uint8_t start) {
244lex_mode_push_list(
pm_parser_t *parser,
bool interpolation, uint8_t delimiter) {
245 uint8_t incrementor = lex_mode_incrementor(delimiter);
246 uint8_t terminator = lex_mode_terminator(delimiter);
252 .interpolation = interpolation,
253 .incrementor = incrementor,
254 .terminator = terminator
261 memcpy(breakpoints,
"\\ \t\f\r\v\n\0\0\0",
sizeof(lex_mode.
as.list.
breakpoints));
265 breakpoints[index++] = terminator;
270 breakpoints[index++] =
'#';
274 if (incrementor !=
'\0') {
275 breakpoints[index++] = incrementor;
279 return lex_mode_push(parser, lex_mode);
289 return lex_mode_push_list(parser,
false,
'\0');
296lex_mode_push_regexp(
pm_parser_t *parser, uint8_t incrementor, uint8_t terminator) {
298 .mode = PM_LEX_REGEXP,
301 .incrementor = incrementor,
302 .terminator = terminator
310 memcpy(breakpoints,
"\n\\#\0\0",
sizeof(lex_mode.
as.regexp.
breakpoints));
313 breakpoints[3] = terminator;
316 if (incrementor !=
'\0') {
317 breakpoints[4] = incrementor;
320 return lex_mode_push(parser, lex_mode);
327lex_mode_push_string(
pm_parser_t *parser,
bool interpolation,
bool label_allowed, uint8_t incrementor, uint8_t terminator) {
329 .mode = PM_LEX_STRING,
332 .interpolation = interpolation,
333 .label_allowed = label_allowed,
334 .incrementor = incrementor,
335 .terminator = terminator
342 memcpy(breakpoints,
"\n\\\0\0\0",
sizeof(lex_mode.
as.string.
breakpoints));
346 breakpoints[index++] = terminator;
351 breakpoints[index++] =
'#';
356 if (incrementor !=
'\0') {
357 breakpoints[index++] = incrementor;
361 return lex_mode_push(parser, lex_mode);
371 return lex_mode_push_string(parser,
false,
false,
'\0',
'\0');
403 PM_IGNORED_NEWLINE_NONE = 0,
404 PM_IGNORED_NEWLINE_ALL,
405 PM_IGNORED_NEWLINE_PATTERN
406} pm_ignored_newline_type_t;
408static inline pm_ignored_newline_type_t
410 bool ignored = lex_state_p(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_CLASS | PM_LEX_STATE_FNAME | PM_LEX_STATE_DOT) && !lex_state_p(parser, PM_LEX_STATE_LABELED);
413 return PM_IGNORED_NEWLINE_ALL;
414 }
else if ((parser->
lex_state & ~((
unsigned int) PM_LEX_STATE_LABEL)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) {
415 return PM_IGNORED_NEWLINE_PATTERN;
417 return PM_IGNORED_NEWLINE_NONE;
423 return lex_state_p(parser, PM_LEX_STATE_BEG_ANY) || ((parser->
lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED));
428 return lex_state_p(parser, PM_LEX_STATE_ARG_ANY);
432lex_state_spcarg_p(
pm_parser_t *parser,
bool space_seen) {
436 return lex_state_arg_p(parser) && space_seen && !pm_char_is_whitespace(*parser->
current.end);
441 return lex_state_p(parser, PM_LEX_STATE_END_ANY);
449 return lex_state_p(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_DOT);
464 fprintf(stderr,
"Caller: %s:%d\nPrevious: ", caller_name, line_number);
466 lex_state_set(parser, state);
467 fprintf(stderr,
"Now: ");
469 fprintf(stderr,
"\n");
472#define lex_state_set(parser, state) debug_lex_state_set(parser, state, __func__, __LINE__)
484 pm_diagnostic_list_append(&parser->
error_list, start, end, diag_id);
490#define PM_PARSER_ERR_FORMAT(parser, start, end, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, start, end, diag_id, __VA_ARGS__)
498 pm_parser_err(parser, parser->
current.start, parser->
current.end, diag_id);
505#define PM_PARSER_ERR_LOCATION_FORMAT(parser, location, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, (location)->start, (location)->end, diag_id, __VA_ARGS__)
520#define PM_PARSER_ERR_NODE_FORMAT(parser, node, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, node->location.start, node->location.end, diag_id, __VA_ARGS__)
537 pm_parser_err(parser, token->start, token->end, diag_id);
544#define PM_PARSER_ERR_TOKEN_FORMAT(parser, token, diag_id, ...) pm_diagnostic_list_append_format(&parser->error_list, (token).start, (token).end, diag_id, __VA_ARGS__)
552 pm_diagnostic_list_append(&parser->
warning_list, start, end, diag_id);
562 pm_parser_warn(parser, token->start, token->end, diag_id);
573pm_parser_constant_id_location(
pm_parser_t *parser,
const uint8_t *start,
const uint8_t *end) {
574 return pm_constant_pool_insert_shared(&parser->
constant_pool, start, (
size_t) (end - start));
581pm_parser_constant_id_owned(
pm_parser_t *parser,
const uint8_t *start,
size_t length) {
582 return pm_constant_pool_insert_owned(&parser->
constant_pool, start, length);
589pm_parser_constant_id_constant(
pm_parser_t *parser,
const char *start,
size_t length) {
590 return pm_constant_pool_insert_constant(&parser->
constant_pool, (
const uint8_t *) start, length);
598 return pm_parser_constant_id_location(parser, token->start, token->end);
616pm_check_value_expression(
pm_node_t *node) {
619 while (node != NULL) {
627 return void_node != NULL ? void_node : node;
654 if (void_node == NULL) {
669 if (void_node == NULL) {
700 pm_node_t *void_node = pm_check_value_expression(node);
701 if (void_node != NULL) {
702 pm_parser_err_node(parser, void_node, PM_ERR_VOID_EXPRESSION);
716pm_conditional_predicate(
pm_node_t *node) {
720 pm_conditional_predicate(cast->
left);
721 pm_conditional_predicate(cast->
right);
726 pm_conditional_predicate(cast->
left);
727 pm_conditional_predicate(cast->
right);
735 if (statements->body.size == 1) pm_conditional_predicate(statements->body.nodes[0]);
743 pm_conditional_predicate(cast->
left);
746 pm_conditional_predicate(cast->
right);
791#define PM_LOCATION_NULL_VALUE(parser) ((pm_location_t) { .start = parser->start, .end = parser->start })
792#define PM_LOCATION_TOKEN_VALUE(token) ((pm_location_t) { .start = (token)->start, .end = (token)->end })
793#define PM_LOCATION_NODE_VALUE(node) ((pm_location_t) { .start = (node)->location.start, .end = (node)->location.end })
794#define PM_LOCATION_NODE_BASE_VALUE(node) ((pm_location_t) { .start = (node)->base.location.start, .end = (node)->base.location.end })
795#define PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE ((pm_location_t) { .start = NULL, .end = NULL })
796#define PM_OPTIONAL_LOCATION_TOKEN_VALUE(token) ((token)->type == PM_TOKEN_NOT_PROVIDED ? PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE : PM_LOCATION_TOKEN_VALUE(token))
821static inline const uint8_t *
823 if (arguments->
block != NULL) {
864 pm_parser_err_node(parser, (
pm_node_t *) block, PM_ERR_ARGUMENT_UNEXPECTED_BLOCK);
898parse_decimal_number(
pm_parser_t *parser,
const uint8_t *start,
const uint8_t *end) {
899 ptrdiff_t diff = end - start;
900 assert(diff > 0 && ((
unsigned long) diff < SIZE_MAX));
901 size_t length = (size_t) diff;
903 char *digits = calloc(length + 1,
sizeof(
char));
904 memcpy(digits, start, length);
905 digits[length] =
'\0';
909 unsigned long value = strtoul(digits, &endptr, 10);
911 if ((digits == endptr) || (*endptr !=
'\0') || (
errno == ERANGE)) {
912 pm_parser_err(parser, start, end, PM_ERR_INVALID_NUMBER_DECIMAL);
918 if (value > UINT32_MAX) {
919 pm_parser_err(parser, start, end, PM_ERR_INVALID_NUMBER_DECIMAL);
923 return (uint32_t) value;
931#define PM_REGULAR_EXPRESSION_ENCODING_MASK ~(PM_REGULAR_EXPRESSION_FLAGS_EUC_JP | PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT | PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J | PM_REGULAR_EXPRESSION_FLAGS_UTF_8)
937pm_regular_expression_flags_create(
const pm_token_t *closing) {
941 for (
const uint8_t *flag = closing->
start + 1; flag < closing->end; flag++) {
953 default: assert(
false &&
"unreachable");
961#undef PM_REGULAR_EXPRESSION_ENCODING_MASK
978 void *memory = calloc(1, size);
979 if (memory == NULL) {
980 fprintf(stderr,
"Failed to allocate %zu bytes\n", size);
986#define PM_ALLOC_NODE(parser, type) (type *) pm_alloc_node(parser, sizeof(type))
992pm_missing_node_create(
pm_parser_t *parser,
const uint8_t *start,
const uint8_t *end) {
1010 .start = keyword->
start,
1014 .new_name = new_name,
1015 .old_name = old_name,
1016 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
1034 .start = keyword->
start,
1038 .new_name = new_name,
1039 .old_name = old_name,
1040 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
1063 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
1074 pm_assert_value_expression(parser, left);
1087 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
1104 .location = PM_LOCATION_NULL_VALUE(parser)
1125 if (pm_arguments_node_size(node) == 0) {
1130 pm_node_list_append(&node->
arguments, argument);
1143 .flags = PM_NODE_FLAG_STATIC_LITERAL,
1144 .location = PM_LOCATION_TOKEN_VALUE(opening)
1146 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
1147 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
1171 pm_node_list_append(&node->
elements, element);
1177 pm_node_flag_unset((
pm_node_t *)node, PM_NODE_FLAG_STATIC_LITERAL);
1192 node->
closing_loc = PM_LOCATION_TOKEN_VALUE(closing);
1215 .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
1216 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
1221 bool found_rest =
false;
1222 for (
size_t index = 0; index < nodes->
size; index++) {
1228 }
else if (found_rest) {
1229 pm_node_list_append(&node->
posts, child);
1231 pm_node_list_append(&node->
requireds, child);
1254 .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
1255 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
1277 .constant = constant,
1279 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
1280 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
1300 .start = opening->
start,
1306 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
1307 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
1317 pm_node_list_append(&node->
requireds, inner);
1328 if (value != NULL) {
1331 end =
operator->end;
1333 end = key->location.end;
1340 flags = key->flags & value->
flags & PM_NODE_FLAG_STATIC_LITERAL;
1348 .start = key->location.start,
1353 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator),
1372 .start =
operator->start,
1373 .end = value == NULL ?
operator->end : value->
location.
end
1377 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
1394 .location = PM_LOCATION_TOKEN_VALUE(name),
1396 .name = pm_parser_constant_id_token(parser, name)
1413 .start = begin_keyword->
start,
1417 .begin_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(begin_keyword),
1418 .statements = statements,
1419 .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
1464 node->
end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword);
1478 .start =
operator->start,
1479 .end = expression == NULL ?
operator->end : expression->
location.
end
1482 .expression = expression,
1483 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
1499 .location = { .start = opening->
start, .end = closing->
end },
1502 .locals_body_index = locals_body_index,
1503 .parameters = parameters,
1505 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
1506 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
1524 .start =
operator->start,
1528 .name = pm_parser_optional_constant_id_token(parser, name),
1529 .name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
1530 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
1543 const uint8_t *start;
1545 start = opening->
start;
1546 }
else if (parameters != NULL) {
1553 if (parameters != NULL) {
1569 .parameters = parameters,
1570 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
1571 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
1586 node->
closing_loc = PM_LOCATION_TOKEN_VALUE(closing);
1600 .location = PM_LOCATION_TOKEN_VALUE(name),
1602 .name = pm_parser_constant_id_token(parser, name)
1631 .start = keyword->
start,
1635 .arguments = arguments,
1636 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
1654 .location = PM_LOCATION_NULL_VALUE(parser),
1657 .call_operator_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
1658 .message_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
1659 .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
1661 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
1675 pm_assert_value_expression(parser, receiver);
1691 node->
name = pm_parser_constant_id_constant(parser,
"[]", 2);
1700 pm_assert_value_expression(parser, receiver);
1701 pm_assert_value_expression(parser, argument);
1709 node->
message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator);
1712 pm_arguments_node_arguments_append(arguments, argument);
1715 node->
name = pm_parser_constant_id_token(parser,
operator);
1724 pm_assert_value_expression(parser, receiver);
1729 const uint8_t *end = pm_arguments_end(arguments);
1737 node->
message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(message);
1747 node->
name = pm_parser_constant_id_token(parser, message);
1762 node->
message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(message);
1768 node->
name = pm_parser_constant_id_token(parser, message);
1777 pm_assert_value_expression(parser, receiver);
1789 node->
message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(message);
1794 node->
name = pm_parser_constant_id_constant(parser,
"!", 1);
1803 pm_assert_value_expression(parser, receiver);
1821 node->
name = pm_parser_constant_id_constant(parser,
"call", 4);
1830 pm_assert_value_expression(parser, receiver);
1838 node->
message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator);
1840 node->
name = pm_parser_constant_id_constant(parser, name, strlen(name));
1852 node->
base.
location = PM_LOCATION_TOKEN_VALUE(message);
1853 node->
message_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(message);
1855 node->
name = pm_parser_constant_id_token(parser, message);
1895 (node->
block == NULL)
1906 if (write_constant->
length > 0) {
1907 size_t length = write_constant->
length - 1;
1909 void *memory = malloc(length);
1910 memcpy(memory, write_constant->
start, length);
1912 *read_name = pm_constant_pool_insert_owned(&parser->
constant_pool, (uint8_t *) memory, length);
1915 *read_name = pm_parser_constant_id_constant(parser,
"", 0);
1924 assert(target->
block == NULL);
1941 .write_name = target->
name,
1942 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
1978 .block = target->
block,
1979 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
1996 assert(target->
block == NULL);
2012 .write_name = target->
name,
2013 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1),
2014 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2049 .block = target->
block,
2050 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1),
2051 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2068 assert(target->
block == NULL);
2085 .write_name = target->
name,
2086 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2122 .block = target->
block,
2123 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2151 .name = target->
name,
2181 .block = target->
block
2209 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
2226 .start = case_keyword->
start,
2227 .end = end_keyword->
end
2230 .predicate = predicate,
2232 .case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
2233 .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
2247 pm_node_list_append(&node->
conditions, condition);
2280 .start = case_keyword->
start,
2281 .end = end_keyword->
end
2284 .predicate = predicate,
2286 .case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
2287 .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
2301 pm_node_list_append(&node->
conditions, condition);
2333 .location = { .start = class_keyword->
start, .end = end_keyword->
end },
2336 .class_keyword_loc = PM_LOCATION_TOKEN_VALUE(class_keyword),
2337 .constant_path = constant_path,
2338 .inheritance_operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(inheritance_operator),
2339 .superclass = superclass,
2341 .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
2342 .name = pm_parser_constant_id_token(parser, name)
2364 .name = target->
name,
2366 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2388 .name = target->
name,
2390 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2392 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1)
2414 .name = target->
name,
2416 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2434 .location = PM_LOCATION_TOKEN_VALUE(token)
2436 .name = pm_parser_constant_id_token(parser, token)
2457 .name = read_node->
name,
2458 .name_loc = PM_LOCATION_NODE_VALUE((
pm_node_t *) read_node),
2459 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator),
2483 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2506 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2508 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1)
2531 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2543 pm_assert_value_expression(parser, parent);
2557 .delimiter_loc = PM_LOCATION_TOKEN_VALUE(delimiter)
2579 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator),
2602 .name = target->
name,
2604 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2626 .name = target->
name,
2628 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2630 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1)
2652 .name = target->
name,
2654 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2672 .location = PM_LOCATION_TOKEN_VALUE(name)
2674 .name = pm_parser_constant_id_token(parser, name)
2695 .name = target->
name,
2697 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator),
2715 uint32_t locals_body_index,
2729 end = end_keyword->
end;
2735 .location = { .start = def_keyword->
start, .end = end },
2737 .name = pm_parser_constant_id_token(parser, name),
2738 .name_loc = PM_LOCATION_TOKEN_VALUE(name),
2739 .receiver = receiver,
2740 .parameters = parameters,
2743 .locals_body_index = locals_body_index,
2744 .def_keyword_loc = PM_LOCATION_TOKEN_VALUE(def_keyword),
2745 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator),
2746 .lparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(lparen),
2747 .rparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(rparen),
2748 .equal_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(equal),
2749 .end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
2766 .start = keyword_loc->
start,
2770 .lparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(lparen),
2772 .rparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(rparen),
2773 .keyword_loc = *keyword_loc
2785 const uint8_t *end = NULL;
2789 end = end_keyword->
end;
2796 .start = else_keyword->
start,
2800 .else_keyword_loc = PM_LOCATION_TOKEN_VALUE(else_keyword),
2801 .statements = statements,
2802 .end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
2819 .start = opening->
start,
2823 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
2824 .statements = statements,
2825 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
2842 .start =
operator->start,
2846 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
2847 .variable = variable
2864 .start = ensure_keyword->
start,
2865 .end = end_keyword->
end
2868 .ensure_keyword_loc = PM_LOCATION_TOKEN_VALUE(ensure_keyword),
2869 .statements = statements,
2870 .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword)
2886 .flags = PM_NODE_FLAG_STATIC_LITERAL,
2887 .location = PM_LOCATION_TOKEN_VALUE(token)
2904 if (nodes->
size == 1) {
2922 .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
2923 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
2929 for (
size_t index = 1; index < nodes->
size - 1; index++) {
2946 .flags = PM_NODE_FLAG_STATIC_LITERAL,
2947 .location = PM_LOCATION_TOKEN_VALUE(token)
2964 .flags = PM_NODE_FLAG_STATIC_LITERAL,
2965 .location = PM_LOCATION_TOKEN_VALUE(token)
2969 .start = token->start,
2970 .end = token->end - 1
2988 .flags = PM_NODE_FLAG_STATIC_LITERAL,
2989 .location = PM_LOCATION_TOKEN_VALUE(token)
2993 .start = token->start,
2994 .end = token->end - 1
3013 .flags = PM_NODE_FLAG_STATIC_LITERAL,
3014 .location = PM_LOCATION_TOKEN_VALUE(token)
3018 .start = token->start,
3019 .end = token->end - 1
3046 .start = for_keyword->
start,
3047 .end = end_keyword->
end
3051 .collection = collection,
3052 .statements = statements,
3053 .for_keyword_loc = PM_LOCATION_TOKEN_VALUE(for_keyword),
3054 .in_keyword_loc = PM_LOCATION_TOKEN_VALUE(in_keyword),
3055 .do_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(do_keyword),
3056 .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword)
3094 if (arguments->
block != NULL) {
3102 .start = token->start,
3124 .start = opening->
start,
3129 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
3130 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
3145 const uint8_t *start;
3148 if (elements->
size > 0) {
3157 assert(rest != NULL);
3173 .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
3174 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
3177 for (
size_t index = 0; index < elements->
size; index++) {
3179 pm_node_list_append(&node->
elements, element);
3200 assert(
false &&
"unreachable");
3221 .name = pm_global_variable_write_name(parser, target),
3223 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
3245 .name = pm_global_variable_write_name(parser, target),
3247 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
3249 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1)
3271 .name = pm_global_variable_write_name(parser, target),
3273 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
3290 .location = PM_LOCATION_TOKEN_VALUE(name),
3292 .name = pm_parser_constant_id_token(parser, name)
3313 .name = pm_global_variable_write_name(parser, target),
3314 .name_loc = PM_LOCATION_NODE_VALUE(target),
3315 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator),
3327 assert(opening != NULL);
3333 .flags = PM_NODE_FLAG_STATIC_LITERAL,
3334 .location = PM_LOCATION_TOKEN_VALUE(opening)
3336 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
3337 .closing_loc = PM_LOCATION_NULL_VALUE(parser),
3349 pm_node_list_append(&hash->elements, element);
3352 if (static_literal) {
3355 static_literal = static_literal &&
PM_NODE_FLAG_P(assoc->
key, PM_NODE_FLAG_STATIC_LITERAL);
3356 static_literal = static_literal &&
PM_NODE_FLAG_P(assoc, PM_NODE_FLAG_STATIC_LITERAL);
3359 if (!static_literal) {
3360 pm_node_flag_unset((
pm_node_t *)hash, PM_NODE_FLAG_STATIC_LITERAL);
3366 hash->base.location.end = token->end;
3367 hash->closing_loc = PM_LOCATION_TOKEN_VALUE(token);
3382 pm_conditional_predicate(predicate);
3387 end = end_keyword->
end;
3388 }
else if (consequent != NULL) {
3390 }
else if (pm_statements_node_body_length(statements) != 0) {
3399 .flags = PM_NODE_FLAG_NEWLINE,
3401 .start = if_keyword->
start,
3405 .if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
3406 .predicate = predicate,
3407 .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
3408 .statements = statements,
3409 .consequent = consequent,
3410 .end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
3421 pm_conditional_predicate(predicate);
3425 pm_statements_node_body_append(statements, statement);
3430 .flags = PM_NODE_FLAG_NEWLINE,
3436 .if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
3437 .predicate = predicate,
3438 .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
3439 .statements = statements,
3441 .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
3452 pm_assert_value_expression(parser, predicate);
3453 pm_conditional_predicate(predicate);
3456 pm_statements_node_body_append(if_statements, true_expression);
3459 pm_statements_node_body_append(else_statements, false_expression);
3461 pm_token_t end_keyword = not_provided(parser);
3462 pm_else_node_t *else_node = pm_else_node_create(parser, colon, else_statements, &end_keyword);
3469 .flags = PM_NODE_FLAG_NEWLINE,
3475 .if_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
3476 .predicate = predicate,
3477 .then_keyword_loc = PM_LOCATION_TOKEN_VALUE(qmark),
3478 .statements = if_statements,
3480 .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
3529 .location = PM_LOCATION_TOKEN_VALUE(token)
3546 .flags = base | PM_NODE_FLAG_STATIC_LITERAL,
3547 .location = PM_LOCATION_TOKEN_VALUE(token)
3565 .flags = PM_NODE_FLAG_STATIC_LITERAL,
3566 .location = PM_LOCATION_TOKEN_VALUE(token)
3570 .start = token->start,
3571 .end = token->end - 1
3590 .flags = PM_NODE_FLAG_STATIC_LITERAL,
3591 .location = PM_LOCATION_TOKEN_VALUE(token)
3595 .start = token->start,
3596 .end = token->end - 1
3615 .flags = PM_NODE_FLAG_STATIC_LITERAL,
3616 .location = PM_LOCATION_TOKEN_VALUE(token)
3620 .start = token->start,
3621 .end = token->end - 1
3636 if (statements != NULL) {
3639 end = then_keyword->
end;
3648 .start = in_keyword->
start,
3653 .statements = statements,
3654 .in_loc = PM_LOCATION_TOKEN_VALUE(in_keyword),
3655 .then_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword)
3677 .name = target->
name,
3679 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
3701 .name = target->
name,
3703 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
3705 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1)
3727 .name = target->
name,
3729 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
3747 .location = PM_LOCATION_TOKEN_VALUE(token)
3749 .name = pm_parser_constant_id_token(parser, token)
3770 .name = read_node->
name,
3771 .name_loc = PM_LOCATION_NODE_BASE_VALUE(read_node),
3772 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator),
3790 .start = opening->
start,
3794 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
3795 .closing_loc = PM_LOCATION_TOKEN_VALUE(opening),
3810 pm_node_list_append(&node->
parts, part);
3815 node->
closing_loc = PM_LOCATION_TOKEN_VALUE(closing);
3817 pm_node_flag_set((
pm_node_t *)node, pm_regular_expression_flags_create(closing));
3831 .start = opening->
start,
3832 .end = closing->
end,
3835 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
3836 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
3840 if (parts != NULL) {
3841 node->
parts = *parts;
3856 pm_node_list_append(&node->
parts, part);
3865 node->
closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing);
3880 .start = opening->
start,
3881 .end = closing->
end,
3884 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
3885 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
3889 if (parts != NULL) {
3890 node->
parts = *parts;
3902 pm_node_list_append(&node->
parts, part);
3917 .start = opening->
start,
3921 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
3922 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
3931 pm_node_list_append(&node->
parts, part);
3937 node->
closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing);
3951 .location = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
3972 pm_node_list_append(&hash->elements, element);
3973 if (hash->base.location.start == NULL) {
3990 .start = name->start,
3994 .name = pm_parser_constant_id_location(parser, name->start, name->end - 1),
3995 .name_loc = PM_LOCATION_TOKEN_VALUE(name),
4012 .start = name->start,
4016 .name = pm_parser_constant_id_location(parser, name->start, name->end - 1),
4017 .name_loc = PM_LOCATION_TOKEN_VALUE(name),
4035 .start =
operator->start,
4039 .name = pm_parser_optional_constant_id_token(parser, name),
4040 .name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
4041 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
4051pm_lambda_node_create(
4054 uint32_t locals_body_index,
4067 .start =
operator->start,
4072 .locals_body_index = locals_body_index,
4073 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4074 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
4075 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
4076 .parameters = parameters,
4101 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4126 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4129 .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1),
4154 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4171 pm_parser_err_token(parser, name, PM_ERR_PARAMETER_CIRCULAR);
4179 .location = PM_LOCATION_TOKEN_VALUE(name)
4199 .start = name_loc->
start,
4206 .name_loc = *name_loc,
4207 .operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator)
4218pm_token_is_numbered_parameter(
const uint8_t *start,
const uint8_t *end) {
4219 return (end - start == 2) && (start[0] ==
'_') && (start[1] !=
'0') && (pm_char_is_decimal_digit(start[1]));
4227pm_refute_numbered_parameter(
pm_parser_t *parser,
const uint8_t *start,
const uint8_t *end) {
4228 if (pm_token_is_numbered_parameter(start, end)) {
4229 PM_PARSER_ERR_FORMAT(parser, start, end, PM_ERR_PARAMETER_NUMBERED_RESERVED, start);
4244 .location = *location
4258 pm_refute_numbered_parameter(parser, name->start, name->end);
4260 return pm_local_variable_target_node_create_values(
4262 &(
pm_location_t) { .start = name->start, .end = name->end },
4263 pm_parser_constant_id_token(parser, name),
4272pm_local_variable_target_node_create_depth(
pm_parser_t *parser,
const pm_token_t *name, uint32_t depth) {
4273 pm_refute_numbered_parameter(parser, name->start, name->end);
4275 return pm_local_variable_target_node_create_values(
4277 &(
pm_location_t) { .start = name->start, .end = name->end },
4278 pm_parser_constant_id_token(parser, name),
4288 pm_assert_value_expression(parser, value);
4302 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
4313 pm_assert_value_expression(parser, value);
4327 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
4363 .start = module_keyword->
start,
4364 .end = end_keyword->
end
4367 .locals = (locals == NULL ? ((
pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals),
4368 .module_keyword_loc = PM_LOCATION_TOKEN_VALUE(module_keyword),
4369 .constant_path = constant_path,
4371 .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
4372 .name = pm_parser_constant_id_token(parser, name)
4388 .location = { .start = NULL, .end = NULL }
4393 .lparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
4394 .rparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
4406 if (node->
rest == NULL) {
4407 node->
rest = target;
4409 pm_parser_err_node(parser, target, PM_ERR_MULTI_ASSIGN_MULTI_SPLATS);
4410 pm_node_list_append(&node->
rights, target);
4412 }
else if (node->
rest == NULL) {
4413 pm_node_list_append(&node->
lefts, target);
4415 pm_node_list_append(&node->
rights, target);
4433 node->
lparen_loc = PM_LOCATION_TOKEN_VALUE(lparen);
4442 node->
rparen_loc = PM_LOCATION_TOKEN_VALUE(rparen);
4460 .lefts = target->
lefts,
4461 .rest = target->
rest,
4462 .rights = target->
rights,
4465 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4488 .start = keyword->
start,
4492 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
4493 .arguments = arguments
4509 .flags = PM_NODE_FLAG_STATIC_LITERAL,
4510 .location = PM_LOCATION_TOKEN_VALUE(token)
4529 .start =
operator->start,
4533 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4534 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
4550 .location = *location
4569 .location = PM_LOCATION_TOKEN_VALUE(name),
4571 .number = parse_decimal_number(parser, name->start + 1, name->end)
4588 .start = name->start,
4592 .name = pm_parser_constant_id_token(parser, name),
4593 .name_loc = PM_LOCATION_TOKEN_VALUE(name),
4594 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4606 pm_assert_value_expression(parser, left);
4620 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
4636 .location = PM_LOCATION_TOKEN_VALUE(&parser->
current)
4639 .keyword_rest = NULL,
4673 pm_parameters_node_location_set(params, param);
4674 pm_node_list_append(¶ms->
requireds, param);
4682 pm_parameters_node_location_set(params, (
pm_node_t *) param);
4691 pm_parameters_node_location_set(params, param);
4692 pm_node_list_append(¶ms->
posts, param);
4700 pm_parameters_node_location_set(params, param);
4701 params->
rest = param;
4709 pm_parameters_node_location_set(params, param);
4710 pm_node_list_append(¶ms->
keywords, param);
4719 pm_parameters_node_location_set(params, param);
4728 assert(params->
block == NULL);
4729 pm_parameters_node_location_set(params, (
pm_node_t *) param);
4730 params->
block = param;
4749 .statements = statements
4766 .start = opening->
start,
4771 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
4772 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
4789 .start =
operator->start,
4793 .expression = expression,
4794 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
4795 .lparen_loc = PM_LOCATION_TOKEN_VALUE(lparen),
4796 .rparen_loc = PM_LOCATION_TOKEN_VALUE(rparen)
4813 .start =
operator->start,
4817 .variable = variable,
4818 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
4835 .start = keyword->
start,
4839 .statements = statements,
4840 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
4841 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
4842 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
4859 .start = keyword->
start,
4863 .statements = statements,
4864 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
4865 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
4866 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
4877 pm_assert_value_expression(parser, left);
4878 pm_assert_value_expression(parser, right);
4895 flags |= PM_NODE_FLAG_STATIC_LITERAL;
4903 .start = (left == NULL ?
operator->start : left->
location.
start),
4904 .end = (right == NULL ? operator->end : right->
location.
end)
4909 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
4938 .flags = pm_regular_expression_flags_create(closing) | PM_NODE_FLAG_STATIC_LITERAL,
4940 .start = MIN(opening->
start, closing->
start),
4941 .end = MAX(opening->
end, closing->
end)
4944 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
4945 .content_loc = PM_LOCATION_TOKEN_VALUE(content),
4946 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
4947 .unescaped = *unescaped
4958 return pm_regular_expression_node_create_unescaped(parser, opening, content, closing, &
PM_STRING_EMPTY);
4971 .location = PM_LOCATION_TOKEN_VALUE(token)
4973 .name = pm_parser_constant_id_token(parser, token)
4994 .expression = expression,
4995 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
4996 .rescue_expression = rescue_expression
5012 .location = PM_LOCATION_TOKEN_VALUE(keyword)
5014 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5015 .operator_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
5027 node->
operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(
operator);
5045 if (pm_statements_node_body_length(statements) > 0) {
5064 pm_node_list_append(&node->
exceptions, exception);
5079 .start =
operator->start,
5083 .name = pm_parser_optional_constant_id_token(parser, name),
5084 .name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
5085 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator)
5114 .start = keyword->
start,
5118 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5119 .arguments = arguments
5135 .location = PM_LOCATION_TOKEN_VALUE(token)
5152 .start = class_keyword->
start,
5153 .end = end_keyword->
end
5157 .class_keyword_loc = PM_LOCATION_TOKEN_VALUE(class_keyword),
5158 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
5159 .expression = expression,
5161 .end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword)
5177 .flags = PM_NODE_FLAG_STATIC_LITERAL,
5178 .location = PM_LOCATION_TOKEN_VALUE(token)
5195 .flags = PM_NODE_FLAG_STATIC_LITERAL,
5196 .location = PM_LOCATION_TOKEN_VALUE(file_keyword),
5214 .flags = PM_NODE_FLAG_STATIC_LITERAL,
5215 .location = PM_LOCATION_TOKEN_VALUE(token)
5232 .start =
operator->start,
5233 .end = (expression == NULL ?
operator->end : expression->
location.
end)
5236 .operator_loc = PM_LOCATION_TOKEN_VALUE(
operator),
5237 .expression = expression
5253 .location = PM_LOCATION_NULL_VALUE(parser)
5273pm_statements_node_location_set(
pm_statements_node_t *node,
const uint8_t *start,
const uint8_t *end) {
5289 pm_node_list_append(&node->
body, statement);
5292 pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE);
5316 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
5317 .content_loc = PM_LOCATION_TOKEN_VALUE(content),
5318 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
5319 .unescaped = *
string
5330 return pm_string_node_create_unescaped(parser, opening, content, closing, &
PM_STRING_EMPTY);
5352 const uint8_t *end = pm_arguments_end(arguments);
5354 assert(
false &&
"unreachable");
5361 .start = keyword->
start,
5365 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5369 .block = arguments->
block
5386 .flags = PM_NODE_FLAG_STATIC_LITERAL,
5392 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
5393 .value_loc = PM_LOCATION_TOKEN_VALUE(value),
5394 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
5395 .unescaped = *unescaped
5406 return pm_symbol_node_create_unescaped(parser, opening, value, closing, &
PM_STRING_EMPTY);
5426 switch (token->type) {
5432 node = pm_symbol_node_create(parser, &opening, &label, &closing);
5434 assert((label.
end - label.
start) >= 0);
5443 node = pm_symbol_node_create(parser, &opening, &label, &closing);
5447 assert(
false &&
"unreachable");
5459pm_symbol_node_label_p(
pm_node_t *node) {
5460 const uint8_t *end = NULL;
5473 return (end != NULL) && (end[-1] ==
':');
5486 .flags = PM_NODE_FLAG_STATIC_LITERAL,
5488 .start = opening->
start,
5492 .opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
5494 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
5548 .flags = PM_NODE_FLAG_STATIC_LITERAL,
5549 .location = PM_LOCATION_TOKEN_VALUE(token)
5566 .location = PM_LOCATION_TOKEN_VALUE(token),
5568 .keyword_loc = PM_LOCATION_TOKEN_VALUE(token),
5581 pm_node_list_append(&node->
names, name);
5589 pm_conditional_predicate(predicate);
5593 if (statements != NULL) {
5602 .flags = PM_NODE_FLAG_NEWLINE,
5604 .start = keyword->
start,
5608 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5609 .predicate = predicate,
5610 .then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
5611 .statements = statements,
5613 .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
5624 pm_conditional_predicate(predicate);
5628 pm_statements_node_body_append(statements, statement);
5633 .flags = PM_NODE_FLAG_NEWLINE,
5639 .keyword_loc = PM_LOCATION_TOKEN_VALUE(unless_keyword),
5640 .predicate = predicate,
5641 .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
5642 .statements = statements,
5644 .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
5668 .start = keyword->
start,
5669 .end = closing->
end,
5672 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5673 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
5674 .predicate = predicate,
5675 .statements = statements
5697 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5698 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
5699 .predicate = predicate,
5700 .statements = statements
5717 .start = keyword->
start,
5721 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5735 pm_node_list_append(&node->
conditions, condition);
5762 .start = keyword->
start,
5766 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5767 .closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
5768 .predicate = predicate,
5769 .statements = statements
5791 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5792 .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
5793 .predicate = predicate,
5794 .statements = statements
5813 .start = opening->
start,
5817 .opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
5818 .content_loc = PM_LOCATION_TOKEN_VALUE(content),
5819 .closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
5820 .unescaped = *unescaped
5831 return pm_xstring_node_create_unescaped(parser, opening, content, closing, &
PM_STRING_EMPTY);
5842 if (rparen_loc->
start != NULL) {
5843 end = rparen_loc->
end;
5844 }
else if (arguments != NULL) {
5846 }
else if (lparen_loc->
start != NULL) {
5847 end = lparen_loc->
end;
5856 .start = keyword->
start,
5860 .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
5861 .lparen_loc = *lparen_loc,
5862 .arguments = arguments,
5863 .rparen_loc = *rparen_loc
5879pm_parser_scope_push(
pm_parser_t *parser,
bool closed) {
5881 if (scope == NULL)
return false;
5886 .explicit_params =
false,
5887 .numbered_parameters = 0,
5890 pm_constant_id_list_init(&scope->
locals);
5905 while (scope != NULL) {
5906 if (pm_constant_id_list_includes(&scope->
locals, constant_id))
return depth;
5907 if (scope->
closed)
break;
5923 return pm_parser_local_depth_constant_id(parser, pm_parser_constant_id_token(parser, token));
5940pm_parser_numbered_parameters_set(
pm_parser_t *parser, uint8_t numbered_parameters) {
5948pm_parser_local_add_location(
pm_parser_t *parser,
const uint8_t *start,
const uint8_t *end) {
5949 pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, start, end);
5950 if (constant_id != 0) pm_parser_local_add(parser, constant_id);
5959 pm_parser_local_add_location(parser, token->start, token->end);
5966pm_parser_local_add_owned(
pm_parser_t *parser,
const uint8_t *start,
size_t length) {
5967 pm_constant_id_t constant_id = pm_parser_constant_id_owned(parser, start, length);
5968 if (constant_id != 0) pm_parser_local_add(parser, constant_id);
5980 pm_refute_numbered_parameter(parser, name->start, name->end);
5983 if ((name->start < name->end) && (*name->start ==
'_'))
return;
5990 pm_parser_err_token(parser, name, PM_ERR_PARAMETER_NAME_REPEAT);
6017char_is_identifier_start(
pm_parser_t *parser,
const uint8_t *b) {
6022 }
else if (*b ==
'_') {
6024 }
else if (*b >= 0x80) {
6029 }
else if (*b < 0x80) {
6032 return (
size_t) (pm_encoding_utf_8_alpha_char(b, parser->
end - b) || 1u);
6041char_is_identifier_utf8(
const uint8_t *b,
const uint8_t *end) {
6045 return (
size_t) (pm_encoding_utf_8_alnum_char(b, end - b) || 1u);
6055char_is_identifier(
pm_parser_t *parser,
const uint8_t *b) {
6060 }
else if (*b ==
'_') {
6062 }
else if (*b >= 0x80) {
6068 return char_is_identifier_utf8(b, parser->
end);
6074#define BIT(c, idx) (((c) / 32 - 1 == idx) ? (1U << ((c) % 32)) : 0)
6075#define PUNCT(idx) ( \
6076 BIT('~', idx) | BIT('*', idx) | BIT('$', idx) | BIT('?', idx) | \
6077 BIT('!', idx) | BIT('@', idx) | BIT('/', idx) | BIT('\\', idx) | \
6078 BIT(';', idx) | BIT(',', idx) | BIT('.', idx) | BIT('=', idx) | \
6079 BIT(':', idx) | BIT('<', idx) | BIT('>', idx) | BIT('\"', idx) | \
6080 BIT('&', idx) | BIT('`', idx) | BIT('\'', idx) | BIT('+', idx) | \
6083const unsigned int pm_global_name_punctuation_hash[(0x7e - 0x20 + 31) / 32] = { PUNCT(0), PUNCT(1), PUNCT(2) };
6089char_is_global_name_punctuation(const uint8_t b) {
6090 const unsigned int i = (const unsigned int) b;
6091 if (i <= 0x20 || 0x7e < i) return false;
6093 return (pm_global_name_punctuation_hash[(i - 0x20) / 32] >> (i % 32)) & 1;
6097token_is_setter_name(pm_token_t *token) {
6099 (token->type == PM_TOKEN_IDENTIFIER) &&
6100 (token->end - token->start >= 2) &&
6101 (token->end[-1] == '=')
6105/******************************************************************************/
6107/******************************************************************************/
6110pm_accepts_block_stack_push(pm_parser_t *parser, bool value) {
6111 // Use the negation of the value to prevent stack overflow.
6112 pm_state_stack_push(&parser->accepts_block_stack, !value);
6116pm_accepts_block_stack_pop(pm_parser_t *parser) {
6117 pm_state_stack_pop(&parser->accepts_block_stack);
6121pm_accepts_block_stack_p(pm_parser_t *parser) {
6122 return !pm_state_stack_p(&parser->accepts_block_stack);
6126pm_do_loop_stack_push(pm_parser_t *parser, bool value) {
6127 pm_state_stack_push(&parser->do_loop_stack, value);
6131pm_do_loop_stack_pop(pm_parser_t *parser) {
6132 pm_state_stack_pop(&parser->do_loop_stack);
6136pm_do_loop_stack_p(pm_parser_t *parser) {
6137 return pm_state_stack_p(&parser->do_loop_stack);
6140/******************************************************************************/
6141/* Lexer check helpers */
6142/******************************************************************************/
6148static inline uint8_t
6149peek_at(pm_parser_t *parser, const uint8_t *cursor) {
6150 if (cursor < parser->end) {
6162static inline uint8_t
6163peek_offset(pm_parser_t *parser, ptrdiff_t offset) {
6164 return peek_at(parser, parser->current.end + offset);
6171static inline uint8_t
6172peek(pm_parser_t *parser) {
6173 return peek_at(parser, parser->current.end);
6181match(pm_parser_t *parser, uint8_t value) {
6182 if (peek(parser) == value) {
6183 parser->current.end++;
6194match_eol_at(pm_parser_t *parser, const uint8_t *cursor) {
6195 if (peek_at(parser, cursor) == '\n') {
6198 if (peek_at(parser, cursor) == '\r' && peek_at(parser, cursor + 1) == '\n') {
6210match_eol_offset(pm_parser_t *parser, ptrdiff_t offset) {
6211 return match_eol_at(parser, parser->current.end + offset);
6220match_eol(pm_parser_t *parser) {
6221 return match_eol_at(parser, parser->current.end);
6227static inline const uint8_t *
6228next_newline(const uint8_t *cursor, ptrdiff_t length) {
6229 assert(length >= 0);
6231 // Note that it's okay for us to use memchr here to look for \n because none
6232 // of the encodings that we support have \n as a component of a multi-byte
6234 return memchr(cursor, '\n', (size_t) length);
6242parser_lex_magic_comment_encoding_value(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
6243 const pm_encoding_t *encoding = pm_encoding_find(start, end);
6245 if (encoding != NULL) {
6246 if (encoding != PM_ENCODING_UTF_8_ENTRY) {
6247 parser->encoding = encoding;
6248 parser->encoding_changed = true;
6249 if (parser->encoding_changed_callback != NULL) parser->encoding_changed_callback(parser);
6263parser_lex_magic_comment_encoding(pm_parser_t *parser) {
6264 const uint8_t *cursor = parser->current.start + 1;
6265 const uint8_t *end = parser->current.end;
6267 bool separator = false;
6269 if (end - cursor <= 6) return;
6270 switch (cursor[6]) {
6271 case 'C': case 'c': cursor += 6; continue;
6272 case 'O': case 'o': cursor += 5; continue;
6273 case 'D': case 'd': cursor += 4; continue;
6274 case 'I': case 'i': cursor += 3; continue;
6275 case 'N': case 'n': cursor += 2; continue;
6276 case 'G': case 'g': cursor += 1; continue;
6283 if (pm_char_is_whitespace(*cursor)) break;
6286 if (pm_strncasecmp(cursor - 6, (const uint8_t *) "coding", 6) == 0) break;
6292 if (++cursor >= end) return;
6293 } while (pm_char_is_whitespace(*cursor));
6295 if (separator) break;
6296 if (*cursor != '=' && *cursor != ':') return;
6302 const uint8_t *value_start = cursor;
6303 while ((*cursor == '-' || *cursor == '_' || parser->encoding->alnum_char(cursor, 1)) && ++cursor < end);
6305 if (!parser_lex_magic_comment_encoding_value(parser, value_start, cursor)) {
6306 // If we were unable to parse the encoding value, then we've got an
6307 // issue because we didn't understand the encoding that the user was
6308 // trying to use. In this case we'll keep using the default encoding but
6309 // add an error to the parser to indicate an unsuccessful parse.
6310 pm_parser_err(parser, value_start, cursor, PM_ERR_INVALID_ENCODING_MAGIC_COMMENT);
6319parser_lex_magic_comment_frozen_string_literal_value(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
6320 if (start + 4 <= end && pm_strncasecmp(start, (const uint8_t *) "true", 4) == 0) {
6321 parser->frozen_string_literal = true;
6326pm_char_is_magic_comment_key_delimiter(const uint8_t b) {
6327 return b == '\'' || b == '"' || b == ':' || b == ';';
6335static inline const uint8_t *
6336parser_lex_magic_comment_emacs_marker(
pm_parser_t *parser,
const uint8_t *cursor,
const uint8_t *end) {
6337 while ((cursor + 3 <= end) && (cursor = pm_memchr(cursor,
'-', (
size_t) (end - cursor), parser->
encoding_changed, parser->
encoding)) != NULL) {
6338 if (cursor + 3 <= end && cursor[1] ==
'*' && cursor[2] ==
'-') {
6357parser_lex_magic_comment(
pm_parser_t *parser,
bool semantic_token_seen) {
6360 const uint8_t *start = parser->
current.start + 1;
6361 const uint8_t *end = parser->
current.end;
6362 if (end - start <= 7)
return false;
6364 const uint8_t *cursor;
6365 bool indicator =
false;
6367 if ((cursor = parser_lex_magic_comment_emacs_marker(parser, start, end)) != NULL) {
6370 if ((cursor = parser_lex_magic_comment_emacs_marker(parser, start, end)) != NULL) {
6381 while (cursor < end) {
6382 while (cursor < end && (pm_char_is_magic_comment_key_delimiter(*cursor) || pm_char_is_whitespace(*cursor))) cursor++;
6384 const uint8_t *key_start = cursor;
6385 while (cursor < end && (!pm_char_is_magic_comment_key_delimiter(*cursor) && !pm_char_is_whitespace(*cursor))) cursor++;
6387 const uint8_t *key_end = cursor;
6388 while (cursor < end && pm_char_is_whitespace(*cursor)) cursor++;
6389 if (cursor == end)
break;
6391 if (*cursor ==
':') {
6394 if (!indicator)
return false;
6398 while (cursor < end && pm_char_is_whitespace(*cursor)) cursor++;
6399 if (cursor == end)
break;
6401 const uint8_t *value_start;
6402 const uint8_t *value_end;
6404 if (*cursor ==
'"') {
6405 value_start = ++cursor;
6406 for (; cursor < end && *cursor !=
'"'; cursor++) {
6407 if (*cursor ==
'\\' && (cursor + 1 < end)) cursor++;
6411 value_start = cursor;
6412 while (cursor < end && *cursor !=
'"' && *cursor !=
';' && !pm_char_is_whitespace(*cursor)) cursor++;
6417 while (cursor < end && (*cursor ==
';' || pm_char_is_whitespace(*cursor))) cursor++;
6419 while (cursor < end && pm_char_is_whitespace(*cursor)) cursor++;
6420 if (cursor != end)
return false;
6426 const size_t key_length = (size_t) (key_end - key_start);
6430 pm_string_shared_init(&key, key_start, key_end);
6432 size_t width = (size_t) (key_end - key_start);
6433 uint8_t *buffer = malloc(width);
6434 if (buffer == NULL)
break;
6436 memcpy(buffer, key_start, width);
6437 buffer[dash - key_start] =
'_';
6439 while ((dash = pm_memchr(dash + 1,
'-', (
size_t) (key_end - dash - 1), parser->
encoding_changed, parser->
encoding)) != NULL) {
6440 buffer[dash - key_start] =
'_';
6443 pm_string_owned_init(&key, buffer, width);
6448 const uint8_t *key_source = pm_string_source(&key);
6454 (key_length == 8 && pm_strncasecmp(key_source, (
const uint8_t *)
"encoding", 8) == 0) ||
6455 (key_length == 6 && pm_strncasecmp(key_source, (
const uint8_t *)
"coding", 6) == 0)
6457 result = parser_lex_magic_comment_encoding_value(parser, value_start, value_end);
6463 if (!semantic_token_seen) {
6464 if (key_length == 21 && pm_strncasecmp(key_source, (
const uint8_t *)
"frozen_string_literal", 21) == 0) {
6465 parser_lex_magic_comment_frozen_string_literal_value(parser, value_start, value_end);
6471 pm_string_free(&key);
6479 magic_comment->value_length = (uint32_t) (value_end - value_start);
6553 while (context_node != NULL) {
6554 if (context_terminator(context_node->
context, token))
return true;
6555 context_node = context_node->
prev;
6564 if (context_node == NULL)
return false;
6589 while (context_node != NULL) {
6590 if (context_node->
context == context)
return true;
6591 context_node = context_node->
prev;
6601 while (context_node != NULL) {
6602 switch (context_node->
context) {
6614 context_node = context_node->
prev;
6626pm_strspn_number_validate(
pm_parser_t *parser,
const uint8_t *invalid) {
6627 if (invalid != NULL) {
6628 pm_parser_err(parser, invalid, invalid + 1, PM_ERR_INVALID_NUMBER_UNDERSCORE);
6633pm_strspn_binary_number_validate(
pm_parser_t *parser,
const uint8_t *
string) {
6634 const uint8_t *invalid = NULL;
6635 size_t length = pm_strspn_binary_number(
string, parser->
end -
string, &invalid);
6636 pm_strspn_number_validate(parser, invalid);
6641pm_strspn_octal_number_validate(
pm_parser_t *parser,
const uint8_t *
string) {
6642 const uint8_t *invalid = NULL;
6643 size_t length = pm_strspn_octal_number(
string, parser->
end -
string, &invalid);
6644 pm_strspn_number_validate(parser, invalid);
6649pm_strspn_decimal_number_validate(
pm_parser_t *parser,
const uint8_t *
string) {
6650 const uint8_t *invalid = NULL;
6651 size_t length = pm_strspn_decimal_number(
string, parser->
end -
string, &invalid);
6652 pm_strspn_number_validate(parser, invalid);
6657pm_strspn_hexadecimal_number_validate(
pm_parser_t *parser,
const uint8_t *
string) {
6658 const uint8_t *invalid = NULL;
6659 size_t length = pm_strspn_hexadecimal_number(
string, parser->
end -
string, &invalid);
6660 pm_strspn_number_validate(parser, invalid);
6665lex_optional_float_suffix(
pm_parser_t *parser,
bool* seen_e) {
6670 if (peek(parser) ==
'.') {
6671 if (pm_char_is_decimal_digit(peek_offset(parser, 1))) {
6673 parser->
current.end += pm_strspn_decimal_number_validate(parser, parser->
current.end);
6684 if (match(parser,
'e') || match(parser,
'E')) {
6685 (void) (match(parser,
'+') || match(parser,
'-'));
6688 if (pm_char_is_decimal_digit(peek(parser))) {
6690 parser->
current.end += pm_strspn_decimal_number_validate(parser, parser->
current.end);
6693 pm_parser_err_current(parser, PM_ERR_INVALID_FLOAT_EXPONENT);
6702lex_numeric_prefix(
pm_parser_t *parser,
bool* seen_e) {
6706 if (peek_offset(parser, -1) ==
'0') {
6707 switch (*parser->
current.end) {
6712 if (pm_char_is_decimal_digit(peek(parser))) {
6713 parser->
current.end += pm_strspn_decimal_number_validate(parser, parser->
current.end);
6715 pm_parser_err_current(parser, PM_ERR_INVALID_NUMBER_DECIMAL);
6724 if (pm_char_is_binary_digit(peek(parser))) {
6725 parser->
current.end += pm_strspn_binary_number_validate(parser, parser->
current.end);
6727 pm_parser_err_current(parser, PM_ERR_INVALID_NUMBER_BINARY);
6737 if (pm_char_is_octal_digit(peek(parser))) {
6738 parser->
current.end += pm_strspn_octal_number_validate(parser, parser->
current.end);
6740 pm_parser_err_current(parser, PM_ERR_INVALID_NUMBER_OCTAL);
6756 parser->
current.end += pm_strspn_octal_number_validate(parser, parser->
current.end);
6764 if (pm_char_is_hexadecimal_digit(peek(parser))) {
6765 parser->
current.end += pm_strspn_hexadecimal_number_validate(parser, parser->
current.end);
6767 pm_parser_err_current(parser, PM_ERR_INVALID_NUMBER_HEXADECIMAL);
6775 type = lex_optional_float_suffix(parser, seen_e);
6782 type = lex_optional_float_suffix(parser, seen_e);
6789 parser->
current.end += pm_strspn_decimal_number_validate(parser, parser->
current.end);
6792 type = lex_optional_float_suffix(parser, seen_e);
6804 bool seen_e =
false;
6805 type = lex_numeric_prefix(parser, &seen_e);
6807 const uint8_t *end = parser->
current.end;
6811 if (match(parser,
'r')) {
6814 if (match(parser,
'i')) {
6817 }
else if (match(parser,
'i')) {
6821 if (!seen_e && match(parser,
'r')) {
6824 if (match(parser,
'i')) {
6827 }
else if (match(parser,
'i')) {
6832 const uint8_t b = peek(parser);
6833 if (b !=
'\0' && (b >= 0x80 || ((b >=
'a' && b <=
'z') || (b >=
'A' && b <=
'Z')) || b ==
'_')) {
6846 pm_parser_err_current(parser, PM_ERR_INVALID_VARIABLE_GLOBAL);
6850 switch (*parser->
current.end) {
6881 if (parser->
current.end < parser->
end && (width = char_is_identifier(parser, parser->
current.end)) > 0) {
6884 }
while (parser->
current.end < parser->
end && (width = char_is_identifier(parser, parser->
current.end)) > 0);
6887 pm_parser_err_current(parser, PM_ERR_INVALID_VARIABLE_GLOBAL);
6911 if ((width = char_is_identifier(parser, parser->
current.end)) > 0) {
6914 }
while (parser->
current.end < parser->
end && (width = char_is_identifier(parser, parser->
current.end)) > 0);
6918 pm_parser_err_current(parser, PM_ERR_INVALID_VARIABLE_GLOBAL);
6940 if (memcmp(current_start, value, vlen) == 0) {
6943 if (parser->
lex_state & PM_LEX_STATE_FNAME) {
6944 lex_state_set(parser, PM_LEX_STATE_ENDFN);
6946 lex_state_set(parser, state);
6947 if (state == PM_LEX_STATE_BEG) {
6951 if ((modifier_type !=
PM_TOKEN_EOF) && !(last_state & (PM_LEX_STATE_BEG | PM_LEX_STATE_LABELED | PM_LEX_STATE_CLASS))) {
6952 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
6953 return modifier_type;
6964lex_identifier(
pm_parser_t *parser,
bool previous_command_start) {
6967 const uint8_t *end = parser->
end;
6968 const uint8_t *current_start = parser->
current.start;
6969 const uint8_t *current_end = parser->
current.end;
6972 if (encoding_changed) {
6973 while (current_end < end && (width = char_is_identifier(parser, current_end)) > 0) {
6974 current_end += width;
6977 while (current_end < end && (width = char_is_identifier_utf8(current_end, end)) > 0) {
6978 current_end += width;
6981 parser->
current.end = current_end;
6985 width = (size_t) (current_end - current_start);
6987 if (current_end < end) {
6988 if (((current_end + 1 >= end) || (current_end[1] !=
'=')) && (match(parser,
'!') || match(parser,
'?'))) {
6994 ((lex_state_p(parser, PM_LEX_STATE_LABEL | PM_LEX_STATE_ENDFN) && !previous_command_start) || lex_state_arg_p(parser)) &&
6995 (peek(parser) ==
':') && (peek_offset(parser, 1) !=
':')
6999 lex_state_set(parser, PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED);
7000 (void) match(parser,
':');
7004 if (parser->
lex_state != PM_LEX_STATE_DOT) {
7013 if (lex_state_p(parser, PM_LEX_STATE_FNAME) && peek_offset(parser, 1) !=
'~' && peek_offset(parser, 1) !=
'>' && (peek_offset(parser, 1) !=
'=' || peek_offset(parser, 2) ==
'>') && match(parser,
'=')) {
7020 ((lex_state_p(parser, PM_LEX_STATE_LABEL | PM_LEX_STATE_ENDFN) && !previous_command_start) || lex_state_arg_p(parser)) &&
7021 peek(parser) ==
':' && peek_offset(parser, 1) !=
':'
7025 lex_state_set(parser, PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED);
7026 (void) match(parser,
':');
7031 if (parser->
lex_state != PM_LEX_STATE_DOT) {
7036 if (pm_do_loop_stack_p(parser)) {
7097 if (encoding_changed) {
7127lex_interpolation(
pm_parser_t *parser,
const uint8_t *pound) {
7130 if (pound + 1 >= parser->
end) {
7131 parser->
current.end = pound + 1;
7141 if (pound + 2 >= parser->
end) {
7142 parser->
current.end = pound + 1;
7148 const uint8_t *variable = pound + 2;
7149 if (*variable ==
'@' && pound + 3 < parser->
end) variable++;
7151 if (char_is_identifier_start(parser, variable)) {
7155 if (pound > parser->
current.start) {
7162 lex_mode_push(parser, (
pm_lex_mode_t) { .mode = PM_LEX_EMBVAR });
7163 parser->
current.end = pound + 1;
7170 parser->
current.end = pound + 1;
7176 if (pound + 2 >= parser->
end) {
7177 parser->
current.end = pound + 1;
7184 const uint8_t *check = pound + 2;
7186 if (pound[2] ==
'-') {
7187 if (pound + 3 >= parser->
end) {
7188 parser->
current.end = pound + 2;
7200 char_is_identifier_start(parser, check) ||
7201 (pound[2] !=
'-' && (pm_char_is_decimal_digit(pound[2]) || char_is_global_name_punctuation(pound[2])))
7206 if (pound > parser->
current.start) {
7213 lex_mode_push(parser, (
pm_lex_mode_t) { .mode = PM_LEX_EMBVAR });
7214 parser->
current.end = pound + 1;
7220 parser->
current.end = pound + 1;
7226 if (pound > parser->
current.start) {
7235 lex_mode_push(parser, (
pm_lex_mode_t) { .mode = PM_LEX_EMBEXPR });
7236 parser->
current.end = pound + 2;
7238 pm_do_loop_stack_push(parser,
false);
7244 parser->
current.end = pound + 1;
7249static const uint8_t PM_ESCAPE_FLAG_NONE = 0x0;
7250static const uint8_t PM_ESCAPE_FLAG_CONTROL = 0x1;
7251static const uint8_t PM_ESCAPE_FLAG_META = 0x2;
7252static const uint8_t PM_ESCAPE_FLAG_SINGLE = 0x4;
7253static const uint8_t PM_ESCAPE_FLAG_REGEXP = 0x8;
7258static const bool ascii_printable_chars[] = {
7259 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
7260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7261 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7262 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7263 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7264 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
7265 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7266 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
7270char_is_ascii_printable(
const uint8_t b) {
7271 return (b < 0x80) && ascii_printable_chars[b];
7278static inline uint8_t
7279escape_hexadecimal_digit(
const uint8_t value) {
7280 return (uint8_t) ((value <=
'9') ? (value -
'0') : (value & 0x7) + 9);
7288static inline uint32_t
7289escape_unicode(
const uint8_t *
string,
size_t length) {
7291 for (
size_t index = 0; index < length; index++) {
7292 if (index != 0) value <<= 4;
7293 value |= escape_hexadecimal_digit(
string[index]);
7301static inline uint8_t
7302escape_byte(uint8_t value,
const uint8_t flags) {
7303 if (flags & PM_ESCAPE_FLAG_CONTROL) value &= 0x1f;
7304 if (flags & PM_ESCAPE_FLAG_META) value |= 0x80;
7312escape_write_unicode(
pm_parser_t *parser,
pm_buffer_t *buffer,
const uint8_t flags,
const uint8_t *start,
const uint8_t *end, uint32_t value) {
7316 if (value >= 0x80 || flags & PM_ESCAPE_FLAG_SINGLE) {
7324 if (value <= 0x7F) {
7325 pm_buffer_append_byte(buffer, (uint8_t) value);
7326 }
else if (value <= 0x7FF) {
7327 pm_buffer_append_byte(buffer, (uint8_t) (0xC0 | (value >> 6)));
7328 pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F)));
7329 }
else if (value <= 0xFFFF) {
7330 pm_buffer_append_byte(buffer, (uint8_t) (0xE0 | (value >> 12)));
7331 pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F)));
7332 pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F)));
7333 }
else if (value <= 0x10FFFF) {
7334 pm_buffer_append_byte(buffer, (uint8_t) (0xF0 | (value >> 18)));
7335 pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 12) & 0x3F)));
7336 pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F)));
7337 pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F)));
7339 pm_parser_err(parser, start, end, PM_ERR_ESCAPE_INVALID_UNICODE);
7340 pm_buffer_append_byte(buffer, 0xEF);
7341 pm_buffer_append_byte(buffer, 0xBF);
7342 pm_buffer_append_byte(buffer, 0xBD);
7354 PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->
current, PM_ERR_MIXED_ENCODING, parser->
encoding->
name);
7360 pm_buffer_append_byte(buffer,
byte);
7380 if (flags & PM_ESCAPE_FLAG_REGEXP) {
7381 pm_buffer_append_bytes(buffer, (
const uint8_t *)
"\\x", 2);
7383 uint8_t byte1 = (uint8_t) ((
byte >> 4) & 0xF);
7384 uint8_t byte2 = (uint8_t) (
byte & 0xF);
7387 pm_buffer_append_byte(buffer, (uint8_t) ((byte1 - 0xA) +
'A'));
7389 pm_buffer_append_byte(buffer, (uint8_t) (byte1 +
'0'));
7393 pm_buffer_append_byte(buffer, (uint8_t) (byte2 - 0xA +
'A'));
7395 pm_buffer_append_byte(buffer, (uint8_t) (byte2 +
'0'));
7398 escape_write_byte_encoded(parser, buffer,
byte);
7407 switch (peek(parser)) {
7410 escape_write_byte_encoded(parser, buffer, escape_byte(
'\\', flags));
7415 escape_write_byte_encoded(parser, buffer, escape_byte(
'\'', flags));
7420 escape_write_byte_encoded(parser, buffer, escape_byte(
'\a', flags));
7425 escape_write_byte_encoded(parser, buffer, escape_byte(
'\b', flags));
7430 escape_write_byte_encoded(parser, buffer, escape_byte(
'\033', flags));
7435 escape_write_byte_encoded(parser, buffer, escape_byte(
'\f', flags));
7440 escape_write_byte_encoded(parser, buffer, escape_byte(
'\n', flags));
7445 escape_write_byte_encoded(parser, buffer, escape_byte(
'\r', flags));
7450 escape_write_byte_encoded(parser, buffer, escape_byte(
' ', flags));
7455 escape_write_byte_encoded(parser, buffer, escape_byte(
'\t', flags));
7460 escape_write_byte_encoded(parser, buffer, escape_byte(
'\v', flags));
7463 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': {
7464 uint8_t value = (uint8_t) (*parser->
current.end -
'0');
7467 if (pm_char_is_octal_digit(peek(parser))) {
7468 value = ((uint8_t) (value << 3)) | ((uint8_t) (*parser->
current.end -
'0'));
7471 if (pm_char_is_octal_digit(peek(parser))) {
7472 value = ((uint8_t) (value << 3)) | ((uint8_t) (*parser->
current.end -
'0'));
7477 escape_write_byte_encoded(parser, buffer, value);
7481 const uint8_t *start = parser->
current.end - 1;
7484 uint8_t
byte = peek(parser);
7486 if (pm_char_is_hexadecimal_digit(
byte)) {
7487 uint8_t value = escape_hexadecimal_digit(
byte);
7490 byte = peek(parser);
7491 if (pm_char_is_hexadecimal_digit(
byte)) {
7492 value = (uint8_t) ((value << 4) | escape_hexadecimal_digit(
byte));
7496 if (flags & PM_ESCAPE_FLAG_REGEXP) {
7497 pm_buffer_append_bytes(buffer, start, (
size_t) (parser->
current.end - start));
7499 escape_write_byte_encoded(parser, buffer, value);
7502 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_HEXADECIMAL);
7508 const uint8_t *start = parser->
current.end - 1;
7513 pm_char_is_hexadecimal_digit(parser->
current.end[0]) &&
7514 pm_char_is_hexadecimal_digit(parser->
current.end[1]) &&
7515 pm_char_is_hexadecimal_digit(parser->
current.end[2]) &&
7516 pm_char_is_hexadecimal_digit(parser->
current.end[3])
7518 uint32_t value = escape_unicode(parser->
current.end, 4);
7520 if (flags & PM_ESCAPE_FLAG_REGEXP) {
7521 pm_buffer_append_bytes(buffer, start, (
size_t) (parser->
current.end + 4 - start));
7523 escape_write_unicode(parser, buffer, flags, start, parser->
current.end + 4, value);
7527 }
else if (peek(parser) ==
'{') {
7528 const uint8_t *unicode_codepoints_start = parser->
current.end - 2;
7533 const uint8_t *extra_codepoints_start = NULL;
7534 int codepoints_count = 0;
7537 const uint8_t *unicode_start = parser->
current.end;
7538 size_t hexadecimal_length = pm_strspn_hexadecimal_digit(parser->
current.end, parser->
end - parser->
current.end);
7540 if (hexadecimal_length > 6) {
7542 pm_parser_err(parser, unicode_start, unicode_start + hexadecimal_length, PM_ERR_ESCAPE_INVALID_UNICODE_LONG);
7543 }
else if (hexadecimal_length == 0) {
7545 pm_parser_err(parser, unicode_start, unicode_start + hexadecimal_length, PM_ERR_ESCAPE_INVALID_UNICODE);
7549 parser->
current.end += hexadecimal_length;
7551 if (flags & PM_ESCAPE_FLAG_SINGLE && codepoints_count == 2) {
7552 extra_codepoints_start = unicode_start;
7555 if (!(flags & PM_ESCAPE_FLAG_REGEXP)) {
7556 uint32_t value = escape_unicode(unicode_start, hexadecimal_length);
7557 escape_write_unicode(parser, buffer, flags, unicode_start, parser->
current.end, value);
7565 if (flags & PM_ESCAPE_FLAG_SINGLE && codepoints_count > 1) {
7566 pm_parser_err(parser, extra_codepoints_start, parser->
current.end - 1, PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL);
7569 if (peek(parser) ==
'}') {
7572 pm_parser_err(parser, unicode_codepoints_start, parser->
current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM);
7575 if (flags & PM_ESCAPE_FLAG_REGEXP) {
7576 pm_buffer_append_bytes(buffer, unicode_codepoints_start, (
size_t) (parser->
current.end - unicode_codepoints_start));
7579 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_UNICODE);
7587 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL);
7591 uint8_t peeked = peek(parser);
7595 escape_write_byte(parser, buffer, flags, escape_byte(0x7f, flags));
7599 if (flags & PM_ESCAPE_FLAG_CONTROL) {
7600 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
7604 escape_read(parser, buffer, flags | PM_ESCAPE_FLAG_CONTROL);
7607 if (!char_is_ascii_printable(peeked)) {
7608 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL);
7613 escape_write_byte(parser, buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
7620 if (peek(parser) !=
'-') {
7621 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL);
7627 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL);
7631 uint8_t peeked = peek(parser);
7635 escape_write_byte(parser, buffer, flags, escape_byte(0x7f, flags));
7639 if (flags & PM_ESCAPE_FLAG_CONTROL) {
7640 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
7644 escape_read(parser, buffer, flags | PM_ESCAPE_FLAG_CONTROL);
7647 if (!char_is_ascii_printable(peeked)) {
7648 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL);
7653 escape_write_byte(parser, buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_CONTROL));
7660 if (peek(parser) !=
'-') {
7661 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META);
7667 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META);
7671 uint8_t peeked = peek(parser);
7672 if (peeked ==
'\\') {
7673 if (flags & PM_ESCAPE_FLAG_META) {
7674 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META_REPEAT);
7678 escape_read(parser, buffer, flags | PM_ESCAPE_FLAG_META);
7682 if (!char_is_ascii_printable(peeked)) {
7683 pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META);
7688 escape_write_byte(parser, buffer, flags, escape_byte(peeked, flags | PM_ESCAPE_FLAG_META));
7692 if (peek_offset(parser, 1) ==
'\n') {
7694 escape_write_byte_encoded(parser, buffer, escape_byte(
'\n', flags));
7701 escape_write_byte_encoded(parser, buffer, *parser->
current.end++);
7735 if (lex_state_end_p(parser)) {
7736 lex_state_set(parser, PM_LEX_STATE_BEG);
7741 pm_parser_err_current(parser, PM_ERR_INCOMPLETE_QUESTION_MARK);
7746 if (pm_char_is_whitespace(*parser->
current.end)) {
7747 lex_state_set(parser, PM_LEX_STATE_BEG);
7751 lex_state_set(parser, PM_LEX_STATE_BEG);
7753 if (match(parser,
'\\')) {
7754 lex_state_set(parser, PM_LEX_STATE_END);
7757 pm_buffer_init_capacity(&buffer, 3);
7759 escape_read(parser, &buffer, PM_ESCAPE_FLAG_SINGLE);
7771 (parser->
current.end + encoding_width >= parser->
end) ||
7772 !char_is_identifier(parser, parser->
current.end + encoding_width)
7775 lex_state_set(parser, PM_LEX_STATE_END);
7776 parser->
current.end += encoding_width;
7794 if (parser->
current.end < parser->
end && (width = char_is_identifier_start(parser, parser->
current.end)) > 0) {
7797 while (parser->
current.end < parser->
end && (width = char_is_identifier(parser, parser->
current.end)) > 0) {
7801 pm_parser_err_current(parser, PM_ERR_INCOMPLETE_VARIABLE_CLASS);
7803 pm_parser_err_current(parser, PM_ERR_INCOMPLETE_VARIABLE_INSTANCE);
7809 lex_mode_pop(parser);
7831 if (comment == NULL)
return NULL;
7849 const uint8_t *newline = next_newline(parser->
current.end, parser->
end - parser->
current.end);
7851 if (newline == NULL) {
7854 pm_newline_list_append(&parser->
newline_list, newline);
7855 parser->
current.end = newline + 1;
7859 parser_lex_callback(parser);
7862 pm_comment_t *comment = parser_comment(parser, PM_COMMENT_EMBDOC);
7867 while (parser->
current.end + 4 <= parser->
end) {
7872 if (memcmp(parser->
current.end,
"=end", 4) == 0 &&
7873 (parser->
current.end + 4 == parser->
end || pm_char_is_whitespace(parser->
current.end[4]))) {
7874 const uint8_t *newline = next_newline(parser->
current.end, parser->
end - parser->
current.end);
7876 if (newline == NULL) {
7879 pm_newline_list_append(&parser->
newline_list, newline);
7880 parser->
current.end = newline + 1;
7884 parser_lex_callback(parser);
7894 const uint8_t *newline = next_newline(parser->
current.end, parser->
end - parser->
current.end);
7896 if (newline == NULL) {
7899 pm_newline_list_append(&parser->
newline_list, newline);
7900 parser->
current.end = newline + 1;
7904 parser_lex_callback(parser);
7907 pm_parser_err_current(parser, PM_ERR_EMBDOC_TERM);
7923 parser_lex_callback(parser);
7979 pm_buffer_append_byte(&token_buffer->
buffer,
byte);
8006 if (token_buffer->
cursor == NULL) {
8009 pm_buffer_append_bytes(&token_buffer->
buffer, token_buffer->
cursor, (
size_t) (parser->
current.end - token_buffer->
cursor));
8010 pm_token_buffer_copy(parser, token_buffer);
8025 const uint8_t *start;
8026 if (token_buffer->
cursor == NULL) {
8027 pm_buffer_init_capacity(&token_buffer->
buffer, 16);
8028 start = parser->
current.start;
8030 start = token_buffer->
cursor;
8033 const uint8_t *end = parser->
current.end - 1;
8034 pm_buffer_append_bytes(&token_buffer->
buffer, start, (
size_t) (end - start));
8043 size_t whitespace = 0;
8046 case PM_HEREDOC_INDENT_NONE:
8051 case PM_HEREDOC_INDENT_DASH:
8053 *cursor += pm_strspn_inline_whitespace(*cursor, parser->
end - *cursor);
8055 case PM_HEREDOC_INDENT_TILDE:
8058 while (*cursor < parser->end && pm_char_is_inline_whitespace(**cursor)) {
8059 if (**cursor ==
'\t') {
8060 whitespace = (whitespace / PM_TAB_WHITESPACE_SIZE + 1) * PM_TAB_WHITESPACE_SIZE;
8077#define LEX(token_type) parser->current.type = token_type; parser_lex_callback(parser); return
8096 bool lexed_comment =
false;
8104 case PM_LEX_DEFAULT:
8105 case PM_LEX_EMBEXPR:
8122 bool space_seen =
false;
8126 bool chomping =
true;
8127 while (parser->
current.end < parser->
end && chomping) {
8128 switch (*parser->
current.end) {
8137 if (match_eol_offset(parser, 1)) {
8145 size_t eol_length = match_eol_offset(parser, 1);
8151 parser->
current.end += eol_length + 1;
8155 }
else if (pm_char_is_inline_whitespace(*parser->
current.end)) {
8180 switch (*parser->
current.end++) {
8188 const uint8_t *ending = next_newline(parser->
current.end, parser->
end - parser->
current.end);
8189 parser->
current.end = ending == NULL ? parser->
end : ending;
8194 pm_comment_t *comment = parser_comment(parser, PM_COMMENT_INLINE);
8197 if (ending) parser->
current.end++;
8199 parser_lex_callback(parser);
8210 if (length >= 10) parser_lex_magic_comment_encoding(parser);
8213 lexed_comment =
true;
8219 size_t eol_length = match_eol_at(parser, parser->
current.end - 1);
8231 if (!lexed_comment) {
8232 parser->
current.end += eol_length - 1;
8241 parser_flush_heredoc_end(parser);
8246 switch (lex_state_ignored_p(parser)) {
8247 case PM_IGNORED_NEWLINE_NONE:
8249 case PM_IGNORED_NEWLINE_PATTERN:
8251 if (!lexed_comment) parser_lex_ignored_newline(parser);
8252 lex_state_set(parser, PM_LEX_STATE_BEG);
8258 case PM_IGNORED_NEWLINE_ALL:
8259 if (!lexed_comment) parser_lex_ignored_newline(parser);
8260 lexed_comment =
false;
8261 goto lex_next_token;
8269 next_content += pm_strspn_inline_whitespace(next_content, parser->
end - next_content);
8271 if (next_content < parser->end) {
8277 if (next_content[0] ==
'#') {
8279 const uint8_t *following = next_newline(next_content, parser->
end - next_content);
8281 while (following && (following + 1 < parser->
end)) {
8283 following += pm_strspn_inline_whitespace(following, parser->
end - following);
8287 if (peek_at(parser, following) !=
'#')
break;
8291 following = next_newline(following, parser->
end - following);
8297 lex_state_ignored_p(parser) ||
8299 (peek_at(parser, following) ==
'.') ||
8300 (peek_at(parser, following) ==
'&' && peek_at(parser, following + 1) ==
'.')
8303 if (!lexed_comment) parser_lex_ignored_newline(parser);
8304 lexed_comment =
false;
8305 goto lex_next_token;
8311 if (next_content[0] ==
'.') {
8315 if (peek_at(parser, next_content + 1) ==
'.') {
8316 if (!lexed_comment) parser_lex_ignored_newline(parser);
8317 lex_state_set(parser, PM_LEX_STATE_BEG);
8323 if (!lexed_comment) parser_lex_ignored_newline(parser);
8324 lex_state_set(parser, PM_LEX_STATE_DOT);
8325 parser->
current.start = next_content;
8326 parser->
current.end = next_content + 1;
8333 if (peek_at(parser, next_content) ==
'&' && peek_at(parser, next_content + 1) ==
'.') {
8334 if (!lexed_comment) parser_lex_ignored_newline(parser);
8335 lex_state_set(parser, PM_LEX_STATE_DOT);
8336 parser->
current.start = next_content;
8337 parser->
current.end = next_content + 2;
8345 lex_state_set(parser, PM_LEX_STATE_BEG);
8348 if (!lexed_comment) parser_lex_callback(parser);
8354 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
8361 if (space_seen && (lex_state_arg_p(parser) || parser->
lex_state == (PM_LEX_STATE_END | PM_LEX_STATE_LABEL))) {
8366 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
8367 pm_do_loop_stack_push(parser,
false);
8374 lex_state_set(parser, PM_LEX_STATE_ENDFN);
8375 pm_do_loop_stack_pop(parser);
8380 lex_state_set(parser, PM_LEX_STATE_BEG);
8389 if (lex_state_operator_p(parser)) {
8390 if (match(parser,
']')) {
8392 lex_state_set(parser, PM_LEX_STATE_ARG);
8396 lex_state_set(parser, PM_LEX_STATE_ARG | PM_LEX_STATE_LABEL);
8400 if (lex_state_beg_p(parser) || (lex_state_arg_p(parser) && (space_seen || lex_state_p(parser, PM_LEX_STATE_LABELED)))) {
8404 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
8405 pm_do_loop_stack_push(parser,
false);
8411 lex_state_set(parser, PM_LEX_STATE_END);
8412 pm_do_loop_stack_pop(parser);
8422 lex_state_set(parser, PM_LEX_STATE_BEG);
8424 }
else if (lex_state_p(parser, PM_LEX_STATE_LABELED)) {
8426 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
8427 }
else if (lex_state_p(parser, PM_LEX_STATE_ARG_ANY | PM_LEX_STATE_END | PM_LEX_STATE_ENDFN)) {
8430 lex_state_set(parser, PM_LEX_STATE_BEG);
8431 }
else if (lex_state_p(parser, PM_LEX_STATE_ENDARG)) {
8434 lex_state_set(parser, PM_LEX_STATE_BEG);
8437 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
8442 pm_do_loop_stack_push(parser,
false);
8450 pm_do_loop_stack_pop(parser);
8453 lex_mode_pop(parser);
8458 lex_state_set(parser, PM_LEX_STATE_END);
8463 if (match(parser,
'*')) {
8464 if (match(parser,
'=')) {
8465 lex_state_set(parser, PM_LEX_STATE_BEG);
8471 if (lex_state_spcarg_p(parser, space_seen) || lex_state_beg_p(parser)) {
8475 if (lex_state_operator_p(parser)) {
8476 lex_state_set(parser, PM_LEX_STATE_ARG);
8478 lex_state_set(parser, PM_LEX_STATE_BEG);
8484 if (match(parser,
'=')) {
8485 lex_state_set(parser, PM_LEX_STATE_BEG);
8491 if (lex_state_spcarg_p(parser, space_seen)) {
8492 pm_parser_warn_token(parser, &parser->
current, PM_WARN_AMBIGUOUS_PREFIX_STAR);
8494 }
else if (lex_state_beg_p(parser)) {
8498 if (lex_state_operator_p(parser)) {
8499 lex_state_set(parser, PM_LEX_STATE_ARG);
8501 lex_state_set(parser, PM_LEX_STATE_BEG);
8509 if (lex_state_operator_p(parser)) {
8510 lex_state_set(parser, PM_LEX_STATE_ARG);
8511 if (match(parser,
'@')) {
8515 lex_state_set(parser, PM_LEX_STATE_BEG);
8518 if (match(parser,
'=')) {
8522 if (match(parser,
'~')) {
8530 if (current_token_starts_line(parser) && (parser->
current.end + 5 <= parser->
end) && memcmp(parser->
current.end,
"begin", 5) == 0 && pm_char_is_whitespace(peek_offset(parser, 5))) {
8537 goto lex_next_token;
8540 if (lex_state_operator_p(parser)) {
8541 lex_state_set(parser, PM_LEX_STATE_ARG);
8543 lex_state_set(parser, PM_LEX_STATE_BEG);
8546 if (match(parser,
'>')) {
8550 if (match(parser,
'~')) {
8554 if (match(parser,
'=')) {
8562 if (match(parser,
'<')) {
8564 !lex_state_p(parser, PM_LEX_STATE_DOT | PM_LEX_STATE_CLASS) &&
8565 !lex_state_end_p(parser) &&
8566 (!lex_state_p(parser, PM_LEX_STATE_ARG_ANY) || lex_state_p(parser, PM_LEX_STATE_LABELED) || space_seen)
8568 const uint8_t *end = parser->
current.end;
8573 if (match(parser,
'-')) {
8574 indent = PM_HEREDOC_INDENT_DASH;
8576 else if (match(parser,
'~')) {
8577 indent = PM_HEREDOC_INDENT_TILDE;
8580 if (match(parser,
'`')) {
8581 quote = PM_HEREDOC_QUOTE_BACKTICK;
8583 else if (match(parser,
'"')) {
8584 quote = PM_HEREDOC_QUOTE_DOUBLE;
8586 else if (match(parser,
'\'')) {
8587 quote = PM_HEREDOC_QUOTE_SINGLE;
8590 const uint8_t *ident_start = parser->
current.end;
8595 }
else if (quote == PM_HEREDOC_QUOTE_NONE && (width = char_is_identifier(parser, parser->
current.end)) == 0) {
8598 if (quote == PM_HEREDOC_QUOTE_NONE) {
8601 while ((parser->
current.end < parser->
end) && (width = char_is_identifier(parser, parser->
current.end))) {
8612 size_t ident_length = (size_t) (parser->
current.end - ident_start);
8613 if (quote != PM_HEREDOC_QUOTE_NONE && !match(parser, (uint8_t) quote)) {
8619 .mode = PM_LEX_HEREDOC,
8621 .ident_start = ident_start,
8622 .ident_length = ident_length,
8623 .next_start = parser->
current.end,
8626 .common_whitespace = (size_t) -1
8631 const uint8_t *body_start = next_newline(parser->
current.end, parser->
end - parser->
current.end);
8633 if (body_start == NULL) {
8638 pm_parser_err_current(parser, PM_ERR_EMBDOC_TERM);
8639 body_start = parser->
end;
8643 pm_newline_list_append(&parser->
newline_list, body_start);
8656 if (match(parser,
'=')) {
8657 lex_state_set(parser, PM_LEX_STATE_BEG);
8661 if (lex_state_operator_p(parser)) {
8662 lex_state_set(parser, PM_LEX_STATE_ARG);
8664 if (lex_state_p(parser, PM_LEX_STATE_CLASS)) parser->
command_start =
true;
8665 lex_state_set(parser, PM_LEX_STATE_BEG);
8671 if (lex_state_operator_p(parser)) {
8672 lex_state_set(parser, PM_LEX_STATE_ARG);
8674 if (lex_state_p(parser, PM_LEX_STATE_CLASS)) parser->
command_start =
true;
8675 lex_state_set(parser, PM_LEX_STATE_BEG);
8678 if (match(parser,
'=')) {
8679 if (match(parser,
'>')) {
8690 if (match(parser,
'>')) {
8691 if (lex_state_operator_p(parser)) {
8692 lex_state_set(parser, PM_LEX_STATE_ARG);
8694 lex_state_set(parser, PM_LEX_STATE_BEG);
8699 if (lex_state_operator_p(parser)) {
8700 lex_state_set(parser, PM_LEX_STATE_ARG);
8702 lex_state_set(parser, PM_LEX_STATE_BEG);
8709 bool label_allowed = (lex_state_p(parser, PM_LEX_STATE_LABEL | PM_LEX_STATE_ENDFN) && !previous_command_start) || lex_state_arg_p(parser);
8710 lex_mode_push_string(parser,
true, label_allowed,
'\0',
'"');
8716 if (lex_state_p(parser, PM_LEX_STATE_FNAME)) {
8717 lex_state_set(parser, PM_LEX_STATE_ENDFN);
8721 if (lex_state_p(parser, PM_LEX_STATE_DOT)) {
8722 if (previous_command_start) {
8723 lex_state_set(parser, PM_LEX_STATE_CMDARG);
8725 lex_state_set(parser, PM_LEX_STATE_ARG);
8731 lex_mode_push_string(parser,
true,
false,
'\0',
'`');
8737 bool label_allowed = (lex_state_p(parser, PM_LEX_STATE_LABEL | PM_LEX_STATE_ENDFN) && !previous_command_start) || lex_state_arg_p(parser);
8738 lex_mode_push_string(parser,
false, label_allowed,
'\0',
'\'');
8744 LEX(lex_question_mark(parser));
8748 if (match(parser,
'&')) {
8749 lex_state_set(parser, PM_LEX_STATE_BEG);
8751 if (match(parser,
'=')) {
8758 if (match(parser,
'=')) {
8759 lex_state_set(parser, PM_LEX_STATE_BEG);
8763 if (match(parser,
'.')) {
8764 lex_state_set(parser, PM_LEX_STATE_DOT);
8769 if (lex_state_spcarg_p(parser, space_seen) || lex_state_beg_p(parser)) {
8773 if (lex_state_operator_p(parser)) {
8774 lex_state_set(parser, PM_LEX_STATE_ARG);
8776 lex_state_set(parser, PM_LEX_STATE_BEG);
8784 if (match(parser,
'|')) {
8785 if (match(parser,
'=')) {
8786 lex_state_set(parser, PM_LEX_STATE_BEG);
8790 if (lex_state_p(parser, PM_LEX_STATE_BEG)) {
8795 lex_state_set(parser, PM_LEX_STATE_BEG);
8799 if (match(parser,
'=')) {
8800 lex_state_set(parser, PM_LEX_STATE_BEG);
8804 if (lex_state_operator_p(parser)) {
8805 lex_state_set(parser, PM_LEX_STATE_ARG);
8807 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
8814 if (lex_state_operator_p(parser)) {
8815 lex_state_set(parser, PM_LEX_STATE_ARG);
8817 if (match(parser,
'@')) {
8824 if (match(parser,
'=')) {
8825 lex_state_set(parser, PM_LEX_STATE_BEG);
8829 bool spcarg = lex_state_spcarg_p(parser, space_seen);
8831 pm_parser_warn_token(parser, &parser->
current, PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS);
8834 if (lex_state_beg_p(parser) || spcarg) {
8835 lex_state_set(parser, PM_LEX_STATE_BEG);
8837 if (pm_char_is_decimal_digit(peek(parser))) {
8840 lex_state_set(parser, PM_LEX_STATE_END);
8847 lex_state_set(parser, PM_LEX_STATE_BEG);
8853 if (lex_state_operator_p(parser)) {
8854 lex_state_set(parser, PM_LEX_STATE_ARG);
8856 if (match(parser,
'@')) {
8863 if (match(parser,
'=')) {
8864 lex_state_set(parser, PM_LEX_STATE_BEG);
8868 if (match(parser,
'>')) {
8869 lex_state_set(parser, PM_LEX_STATE_ENDFN);
8873 bool spcarg = lex_state_spcarg_p(parser, space_seen);
8875 pm_parser_warn_token(parser, &parser->
current, PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS);
8878 if (lex_state_beg_p(parser) || spcarg) {
8879 lex_state_set(parser, PM_LEX_STATE_BEG);
8883 lex_state_set(parser, PM_LEX_STATE_BEG);
8889 bool beg_p = lex_state_beg_p(parser);
8891 if (match(parser,
'.')) {
8892 if (match(parser,
'.')) {
8898 if (lex_state_p(parser, PM_LEX_STATE_END)) {
8899 lex_state_set(parser, PM_LEX_STATE_BEG);
8901 lex_state_set(parser, PM_LEX_STATE_ENDARG);
8906 lex_state_set(parser, PM_LEX_STATE_BEG);
8910 lex_state_set(parser, PM_LEX_STATE_BEG);
8914 lex_state_set(parser, PM_LEX_STATE_DOT);
8930 lex_state_set(parser, PM_LEX_STATE_END);
8936 if (match(parser,
':')) {
8937 if (lex_state_beg_p(parser) || lex_state_p(parser, PM_LEX_STATE_CLASS) || (lex_state_p(parser, PM_LEX_STATE_ARG_ANY) && space_seen)) {
8938 lex_state_set(parser, PM_LEX_STATE_BEG);
8942 lex_state_set(parser, PM_LEX_STATE_DOT);
8946 if (lex_state_end_p(parser) || pm_char_is_whitespace(peek(parser)) || peek(parser) ==
'#') {
8947 lex_state_set(parser, PM_LEX_STATE_BEG);
8951 if (peek(parser) ==
'"' || peek(parser) ==
'\'') {
8952 lex_mode_push_string(parser, peek(parser) ==
'"',
false,
'\0', *parser->
current.end);
8956 lex_state_set(parser, PM_LEX_STATE_FNAME);
8961 if (lex_state_beg_p(parser)) {
8962 lex_mode_push_regexp(parser,
'\0',
'/');
8966 if (match(parser,
'=')) {
8967 lex_state_set(parser, PM_LEX_STATE_BEG);
8971 if (lex_state_spcarg_p(parser, space_seen)) {
8972 pm_parser_warn_token(parser, &parser->
current, PM_WARN_AMBIGUOUS_SLASH);
8973 lex_mode_push_regexp(parser,
'\0',
'/');
8977 if (lex_state_operator_p(parser)) {
8978 lex_state_set(parser, PM_LEX_STATE_ARG);
8980 lex_state_set(parser, PM_LEX_STATE_BEG);
8987 if (lex_state_operator_p(parser)) {
8988 lex_state_set(parser, PM_LEX_STATE_ARG);
8990 lex_state_set(parser, PM_LEX_STATE_BEG);
8996 if (lex_state_operator_p(parser)) {
8997 (void) match(parser,
'@');
8998 lex_state_set(parser, PM_LEX_STATE_ARG);
9000 lex_state_set(parser, PM_LEX_STATE_BEG);
9011 if ((lex_state_beg_p(parser) || lex_state_arg_p(parser)) && (parser->
current.end >= parser->
end)) {
9012 pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT);
9016 if (!lex_state_beg_p(parser) && match(parser,
'=')) {
9017 lex_state_set(parser, PM_LEX_STATE_BEG);
9020 lex_state_beg_p(parser) ||
9021 (lex_state_p(parser, PM_LEX_STATE_FITEM) && (peek(parser) ==
's')) ||
9022 lex_state_spcarg_p(parser, space_seen)
9025 if (*parser->
current.end >= 0x80) {
9026 pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT);
9029 lex_mode_push_string(parser,
true,
false, lex_mode_incrementor(*parser->
current.end), lex_mode_terminator(*parser->
current.end));
9031 size_t eol_length = match_eol(parser);
9033 parser->
current.end += eol_length;
9046 uint8_t delimiter = peek_offset(parser, 1);
9048 pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT);
9049 goto lex_next_token;
9052 switch (peek(parser)) {
9057 lex_mode_push_list(parser,
false, *parser->
current.end++);
9059 lex_mode_push_list_eof(parser);
9068 lex_mode_push_list(parser,
true, *parser->
current.end++);
9070 lex_mode_push_list_eof(parser);
9079 lex_mode_push_regexp(parser, lex_mode_incrementor(*parser->
current.end), lex_mode_terminator(*parser->
current.end));
9083 lex_mode_push_regexp(parser,
'\0',
'\0');
9092 lex_mode_push_string(parser,
false,
false, lex_mode_incrementor(*parser->
current.end), lex_mode_terminator(*parser->
current.end));
9096 lex_mode_push_string_eof(parser);
9105 lex_mode_push_string(parser,
true,
false, lex_mode_incrementor(*parser->
current.end), lex_mode_terminator(*parser->
current.end));
9109 lex_mode_push_string_eof(parser);
9118 lex_mode_push_string(parser,
false,
false, lex_mode_incrementor(*parser->
current.end), lex_mode_terminator(*parser->
current.end));
9119 lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM);
9122 lex_mode_push_string_eof(parser);
9131 lex_mode_push_list(parser,
false, *parser->
current.end++);
9133 lex_mode_push_list_eof(parser);
9142 lex_mode_push_list(parser,
true, *parser->
current.end++);
9144 lex_mode_push_list_eof(parser);
9153 lex_mode_push_string(parser,
true,
false, lex_mode_incrementor(*parser->
current.end), lex_mode_terminator(*parser->
current.end));
9156 lex_mode_push_string_eof(parser);
9166 pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT);
9167 goto lex_next_token;
9171 lex_state_set(parser, lex_state_operator_p(parser) ? PM_LEX_STATE_ARG : PM_LEX_STATE_BEG);
9182 lex_mode_pop(parser);
9185 lex_state_set(parser, PM_LEX_STATE_END);
9191 lex_state_set(parser, parser->
lex_state & PM_LEX_STATE_FNAME ? PM_LEX_STATE_ENDFN : PM_LEX_STATE_END);
9192 LEX(lex_at_variable(parser));
9195 if (*parser->
current.start !=
'_') {
9196 size_t width = char_is_identifier_start(parser, parser->
current.start);
9202 pm_parser_err_current(parser, PM_ERR_INVALID_TOKEN);
9203 goto lex_next_token;
9216 current_token_starts_line(parser) &&
9217 (memcmp(parser->
current.start,
"__END__", 7) == 0) &&
9218 (parser->
current.end == parser->
end || match_eol(parser))
9224 const uint8_t *cursor = parser->
current.end;
9225 while ((cursor = next_newline(cursor, parser->
end - cursor)) != NULL) {
9226 pm_newline_list_append(&parser->
newline_list, cursor++);
9231 parser_lex_callback(parser);
9242 if (lex_state_p(parser, PM_LEX_STATE_BEG_ANY | PM_LEX_STATE_ARG_ANY | PM_LEX_STATE_DOT)) {
9243 if (previous_command_start) {
9244 lex_state_set(parser, PM_LEX_STATE_CMDARG);
9246 lex_state_set(parser, PM_LEX_STATE_ARG);
9248 }
else if (parser->
lex_state == PM_LEX_STATE_FNAME) {
9249 lex_state_set(parser, PM_LEX_STATE_ENDFN);
9251 lex_state_set(parser, PM_LEX_STATE_END);
9256 !(last_state & (PM_LEX_STATE_DOT | PM_LEX_STATE_FNAME)) &&
9258 ((pm_parser_local_depth(parser, &parser->
current) != -1) ||
9259 pm_token_is_numbered_parameter(parser->
current.start, parser->
current.end))
9261 lex_state_set(parser, PM_LEX_STATE_END | PM_LEX_STATE_LABEL);
9282 whitespace = pm_strspn_inline_whitespace(parser->
current.end, parser->
end - parser->
current.end);
9283 if (peek_offset(parser, (ptrdiff_t)whitespace) ==
'\n') {
9290 if (whitespace > 0) {
9291 parser->
current.end += whitespace;
9292 if (peek_offset(parser, -1) ==
'\n') {
9294 parser_flush_heredoc_end(parser);
9309 const uint8_t *breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9315 while (breakpoint != NULL) {
9317 if (*breakpoint ==
'\0') {
9318 breakpoint = pm_strpbrk(parser, breakpoint + 1, breakpoints, parser->
end - (breakpoint + 1));
9324 if (pm_char_is_whitespace(*breakpoint)) {
9325 parser->
current.end = breakpoint;
9326 pm_token_buffer_flush(parser, &token_buffer);
9336 parser->
current.end = breakpoint + 1;
9337 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9344 if (breakpoint > parser->
current.start) {
9345 parser->
current.end = breakpoint;
9346 pm_token_buffer_flush(parser, &token_buffer);
9352 parser->
current.end = breakpoint + 1;
9353 lex_mode_pop(parser);
9354 lex_state_set(parser, PM_LEX_STATE_END);
9361 if (*breakpoint ==
'\\') {
9362 parser->
current.end = breakpoint + 1;
9371 pm_token_buffer_escape(parser, &token_buffer);
9372 uint8_t peeked = peek(parser);
9380 pm_token_buffer_push(&token_buffer, peeked);
9385 if (peek(parser) !=
'\n') {
9386 pm_token_buffer_push(&token_buffer,
'\r');
9391 pm_token_buffer_push(&token_buffer,
'\n');
9397 parser_flush_heredoc_end(parser);
9398 pm_token_buffer_copy(parser, &token_buffer);
9409 pm_token_buffer_push(&token_buffer, peeked);
9412 escape_read(parser, &token_buffer.
buffer, PM_ESCAPE_FLAG_NONE);
9414 pm_token_buffer_push(&token_buffer,
'\\');
9415 pm_token_buffer_push(&token_buffer, peeked);
9423 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9428 if (*breakpoint ==
'#') {
9436 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9441 pm_token_buffer_flush(parser, &token_buffer);
9450 parser->
current.end = breakpoint + 1;
9451 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9457 pm_token_buffer_flush(parser, &token_buffer);
9464 pm_token_buffer_flush(parser, &token_buffer);
9467 case PM_LEX_REGEXP: {
9489 const uint8_t *breakpoints = lex_mode->
as.regexp.
breakpoints;
9490 const uint8_t *breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9493 while (breakpoint != NULL) {
9495 if (*breakpoint ==
'\0') {
9496 parser->
current.end = breakpoint + 1;
9497 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9503 if (*breakpoint ==
'\n') {
9512 pm_newline_list_append(&parser->
newline_list, breakpoint);
9518 parser->
current.end = breakpoint + 1;
9519 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9528 parser->
current.end = breakpoint + 1;
9529 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9537 if (breakpoint > parser->
current.start) {
9538 parser->
current.end = breakpoint;
9539 pm_token_buffer_flush(parser, &token_buffer);
9545 parser->
current.end = breakpoint + 1;
9548 lex_mode_pop(parser);
9549 lex_state_set(parser, PM_LEX_STATE_END);
9556 if (*breakpoint ==
'\\') {
9557 parser->
current.end = breakpoint + 1;
9566 pm_token_buffer_escape(parser, &token_buffer);
9567 uint8_t peeked = peek(parser);
9572 if (peek(parser) !=
'\n') {
9574 pm_token_buffer_push(&token_buffer,
'\\');
9576 pm_token_buffer_push(&token_buffer,
'\r');
9585 parser_flush_heredoc_end(parser);
9586 pm_token_buffer_copy(parser, &token_buffer);
9600 escape_read(parser, &token_buffer.
buffer, PM_ESCAPE_FLAG_REGEXP);
9608 case '$':
case ')':
case '*':
case '+':
9609 case '.':
case '>':
case '?':
case ']':
9610 case '^':
case '|':
case '}':
9611 pm_token_buffer_push(&token_buffer,
'\\');
9617 pm_token_buffer_push(&token_buffer, peeked);
9622 if (peeked < 0x80) pm_token_buffer_push(&token_buffer,
'\\');
9623 pm_token_buffer_push(&token_buffer, peeked);
9629 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9634 if (*breakpoint ==
'#') {
9642 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9647 pm_token_buffer_flush(parser, &token_buffer);
9656 parser->
current.end = breakpoint + 1;
9657 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9663 pm_token_buffer_flush(parser, &token_buffer);
9670 pm_token_buffer_flush(parser, &token_buffer);
9673 case PM_LEX_STRING: {
9692 const uint8_t *breakpoints = lex_mode->
as.string.
breakpoints;
9693 const uint8_t *breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9699 while (breakpoint != NULL) {
9704 parser->
current.end = breakpoint + 1;
9705 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9716 parser->
current.end = breakpoint + 1;
9717 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9724 if (breakpoint > parser->
current.start) {
9725 parser->
current.end = breakpoint;
9726 pm_token_buffer_flush(parser, &token_buffer);
9732 size_t eol_length = match_eol_at(parser, breakpoint);
9734 parser->
current.end = breakpoint + eol_length;
9737 parser->
current.end = breakpoint + 1;
9740 if (lex_mode->
as.string.
label_allowed && (peek(parser) ==
':') && (peek_offset(parser, 1) !=
':')) {
9742 lex_state_set(parser, PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED);
9743 lex_mode_pop(parser);
9747 lex_state_set(parser, PM_LEX_STATE_END);
9748 lex_mode_pop(parser);
9755 if (*breakpoint ==
'\n') {
9757 pm_newline_list_append(&parser->
newline_list, breakpoint);
9758 parser->
current.end = breakpoint + 1;
9759 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9762 parser->
current.end = breakpoint + 1;
9763 parser_flush_heredoc_end(parser);
9764 pm_token_buffer_flush(parser, &token_buffer);
9769 switch (*breakpoint) {
9772 parser->
current.end = breakpoint + 1;
9773 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9777 parser->
current.end = breakpoint + 1;
9786 pm_token_buffer_escape(parser, &token_buffer);
9787 uint8_t peeked = peek(parser);
9791 pm_token_buffer_push(&token_buffer,
'\\');
9796 if (peek(parser) !=
'\n') {
9798 pm_token_buffer_push(&token_buffer,
'\\');
9800 pm_token_buffer_push(&token_buffer,
'\r');
9806 pm_token_buffer_push(&token_buffer,
'\\');
9807 pm_token_buffer_push(&token_buffer,
'\n');
9814 parser_flush_heredoc_end(parser);
9815 pm_token_buffer_copy(parser, &token_buffer);
9826 pm_token_buffer_push(&token_buffer, peeked);
9829 pm_token_buffer_push(&token_buffer, peeked);
9832 escape_read(parser, &token_buffer.
buffer, PM_ESCAPE_FLAG_NONE);
9834 pm_token_buffer_push(&token_buffer,
'\\');
9835 pm_token_buffer_push(&token_buffer, peeked);
9843 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9854 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9859 pm_token_buffer_flush(parser, &token_buffer);
9865 assert(
false &&
"unreachable");
9870 pm_token_buffer_flush(parser, &token_buffer);
9877 pm_token_buffer_flush(parser, &token_buffer);
9880 case PM_LEX_HEREDOC: {
9900 const uint8_t *ident_start = lex_mode->
as.heredoc.
ident_start;
9905 if (current_token_starts_line(parser)) {
9906 const uint8_t *start = parser->
current.start;
9907 if (start + ident_length <= parser->end) {
9908 const uint8_t *newline = next_newline(start, parser->
end - start);
9909 const uint8_t *ident_end = newline;
9910 const uint8_t *terminator_end = newline;
9912 if (newline == NULL) {
9913 terminator_end = parser->
end;
9914 ident_end = parser->
end;
9917 if (newline[-1] ==
'\r') {
9922 const uint8_t *terminator_start = ident_end - ident_length;
9923 const uint8_t *cursor = start;
9926 lex_mode->
as.heredoc.
indent == PM_HEREDOC_INDENT_DASH ||
9927 lex_mode->
as.heredoc.
indent == PM_HEREDOC_INDENT_TILDE
9929 while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) {
9935 (cursor == terminator_start) &&
9936 (memcmp(terminator_start, ident_start, ident_length) == 0)
9938 if (newline != NULL) {
9939 pm_newline_list_append(&parser->
newline_list, newline);
9942 parser->
current.end = terminator_end;
9950 lex_state_set(parser, PM_LEX_STATE_END);
9955 size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->
as.heredoc.
indent);
9957 lex_mode->
as.heredoc.
indent == PM_HEREDOC_INDENT_TILDE &&
9959 peek_at(parser, start) !=
'\n'
9968 uint8_t breakpoints[] =
"\n\\#";
9971 if (quote == PM_HEREDOC_QUOTE_SINGLE) {
9972 breakpoints[2] =
'\0';
9975 const uint8_t *breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9977 bool was_escaped_newline =
false;
9979 while (breakpoint != NULL) {
9980 switch (*breakpoint) {
9983 parser->
current.end = breakpoint + 1;
9984 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
9988 parser_flush_heredoc_end(parser);
9989 parser->
current.end = breakpoint + 1;
9990 pm_token_buffer_flush(parser, &token_buffer);
9994 pm_newline_list_append(&parser->
newline_list, breakpoint);
9998 const uint8_t *start = breakpoint + 1;
10000 if (!was_escaped_newline && (start + ident_length <= parser->end)) {
10003 const uint8_t *newline = next_newline(start, parser->
end - start);
10005 if (newline == NULL) {
10006 newline = parser->
end;
10007 }
else if (newline[-1] ==
'\r') {
10012 const uint8_t *terminator_start = newline - ident_length;
10016 const uint8_t *cursor = start;
10018 if (lex_mode->
as.heredoc.
indent == PM_HEREDOC_INDENT_DASH ||
10019 lex_mode->
as.heredoc.
indent == PM_HEREDOC_INDENT_TILDE) {
10020 while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) {
10026 cursor == terminator_start &&
10027 (memcmp(terminator_start, ident_start, ident_length) == 0)
10029 parser->
current.end = breakpoint + 1;
10030 pm_token_buffer_flush(parser, &token_buffer);
10035 size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->
as.heredoc.
indent);
10043 if (lex_mode->
as.heredoc.
indent == PM_HEREDOC_INDENT_TILDE) {
10044 if ((lex_mode->
as.heredoc.
common_whitespace > whitespace) && peek_at(parser, start) !=
'\n') {
10048 parser->
current.end = breakpoint + 1;
10050 if (!was_escaped_newline) {
10051 pm_token_buffer_flush(parser, &token_buffer);
10058 parser->
current.end = breakpoint + 1;
10059 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
10069 parser->
current.end = breakpoint + 1;
10078 pm_token_buffer_escape(parser, &token_buffer);
10079 uint8_t peeked = peek(parser);
10081 if (quote == PM_HEREDOC_QUOTE_SINGLE) {
10085 if (peek(parser) !=
'\n') {
10086 pm_token_buffer_push(&token_buffer,
'\\');
10087 pm_token_buffer_push(&token_buffer,
'\r');
10092 pm_token_buffer_push(&token_buffer,
'\\');
10093 pm_token_buffer_push(&token_buffer,
'\n');
10095 breakpoint = parser->
current.end;
10099 pm_token_buffer_push(&token_buffer,
'\\');
10100 pm_token_buffer_push(&token_buffer, peeked);
10107 if (peek(parser) !=
'\n') {
10108 pm_token_buffer_push(&token_buffer,
'\r');
10113 was_escaped_newline =
true;
10115 breakpoint = parser->
current.end;
10118 escape_read(parser, &token_buffer.
buffer, PM_ESCAPE_FLAG_NONE);
10124 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
10136 breakpoint = pm_strpbrk(parser, parser->
current.end, breakpoints, parser->
end - parser->
current.end);
10141 pm_token_buffer_flush(parser, &token_buffer);
10147 assert(
false &&
"unreachable");
10150 was_escaped_newline =
false;
10155 pm_token_buffer_flush(parser, &token_buffer);
10162 pm_token_buffer_flush(parser, &token_buffer);
10167 assert(
false &&
"unreachable");
10185 PM_BINDING_POWER_UNSET = 0,
10186 PM_BINDING_POWER_STATEMENT = 2,
10187 PM_BINDING_POWER_MODIFIER = 4,
10188 PM_BINDING_POWER_MODIFIER_RESCUE = 6,
10189 PM_BINDING_POWER_COMPOSITION = 8,
10190 PM_BINDING_POWER_NOT = 10,
10191 PM_BINDING_POWER_MATCH = 12,
10192 PM_BINDING_POWER_DEFINED = 14,
10193 PM_BINDING_POWER_MULTI_ASSIGNMENT = 16,
10194 PM_BINDING_POWER_ASSIGNMENT = 18,
10195 PM_BINDING_POWER_TERNARY = 20,
10196 PM_BINDING_POWER_RANGE = 22,
10197 PM_BINDING_POWER_LOGICAL_OR = 24,
10198 PM_BINDING_POWER_LOGICAL_AND = 26,
10199 PM_BINDING_POWER_EQUALITY = 28,
10200 PM_BINDING_POWER_COMPARISON = 30,
10201 PM_BINDING_POWER_BITWISE_OR = 32,
10202 PM_BINDING_POWER_BITWISE_AND = 34,
10203 PM_BINDING_POWER_SHIFT = 36,
10204 PM_BINDING_POWER_TERM = 38,
10205 PM_BINDING_POWER_FACTOR = 40,
10206 PM_BINDING_POWER_UMINUS = 42,
10207 PM_BINDING_POWER_EXPONENT = 44,
10208 PM_BINDING_POWER_UNARY = 46,
10209 PM_BINDING_POWER_INDEX = 48,
10210 PM_BINDING_POWER_CALL = 50,
10211 PM_BINDING_POWER_MAX = 52
10212} pm_binding_power_t;
10235#define BINDING_POWER_ASSIGNMENT { PM_BINDING_POWER_UNARY, PM_BINDING_POWER_ASSIGNMENT, true, false }
10236#define LEFT_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, false }
10237#define RIGHT_ASSOCIATIVE(precedence) { precedence, precedence, true, false }
10238#define NON_ASSOCIATIVE(precedence) { precedence, precedence + 1, true, true }
10239#define RIGHT_ASSOCIATIVE_UNARY(precedence) { precedence, precedence, false, false }
10301 [
PM_TOKEN_LESS] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPARISON),
10305 [
PM_TOKEN_CARET] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_BITWISE_OR),
10306 [
PM_TOKEN_PIPE] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_BITWISE_OR),
10322 [
PM_TOKEN_STAR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR),
10326 [
PM_TOKEN_UMINUS] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UMINUS),
10334 [
PM_TOKEN_BANG] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UNARY),
10335 [
PM_TOKEN_TILDE] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UNARY),
10336 [
PM_TOKEN_UPLUS] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UNARY),
10343 [
PM_TOKEN_DOT] = RIGHT_ASSOCIATIVE(PM_BINDING_POWER_CALL),
10347#undef BINDING_POWER_ASSIGNMENT
10348#undef LEFT_ASSOCIATIVE
10349#undef RIGHT_ASSOCIATIVE
10350#undef RIGHT_ASSOCIATIVE_UNARY
10365 return match1(parser, type1) || match1(parser, type2);
10373 return match1(parser, type1) || match1(parser, type2) || match1(parser, type3);
10381 return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4);
10389 return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5);
10397 return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6);
10405 return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6) || match1(parser, type7);
10413 return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6) || match1(parser, type7) || match1(parser, type8);
10424 if (match1(parser, type)) {
10425 parser_lex(parser);
10437 if (match2(parser, type1, type2)) {
10438 parser_lex(parser);
10450 if (match3(parser, type1, type2, type3)) {
10451 parser_lex(parser);
10470 if (accept1(parser, type))
return;
10473 pm_parser_err(parser, location, location, diag_id);
10485 if (accept2(parser, type1, type2))
return;
10488 pm_parser_err(parser, location, location, diag_id);
10499 if (accept3(parser, type1, type2, type3))
return;
10502 pm_parser_err(parser, location, location, diag_id);
10516 pm_node_t *node = parse_expression(parser, binding_power, accepts_command_call, diag_id);
10517 pm_assert_value_expression(parser, node);
10572 assert(pm_binding_powers[type].left == PM_BINDING_POWER_UNSET);
10592 return pm_binding_powers[
type].left == PM_BINDING_POWER_UNSET;
10604 pm_node_t *expression = parse_value_expression(parser, binding_power,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
10605 return (
pm_node_t *) pm_splat_node_create(parser, &
operator, expression);
10608 return parse_value_expression(parser, binding_power, accepts_command_call, diag_id);
10622 size_t length = constant->
length;
10623 uint8_t *name = calloc(length + 1,
sizeof(uint8_t));
10624 if (name == NULL)
return;
10626 memcpy(name, constant->
start, length);
10627 name[length] =
'=';
10632 *name_field = pm_constant_pool_insert_owned(&parser->
constant_pool, name, length + 1);
10657 pm_parser_err_node(parser, target, PM_ERR_WRITE_TARGET_READONLY);
10665 PM_PARSER_ERR_NODE_FORMAT(parser, target, PM_ERR_PARAMETER_NUMBERED_RESERVED, target->
location.
start);
10698 (call->
block == NULL)
10712 pm_parser_local_add_location(parser, message.
start, message.
end);
10713 pm_node_destroy(parser, target);
10715 uint32_t depth = 0;
10717 target = (
pm_node_t *) pm_local_variable_read_node_create(parser, &name, depth);
10722 pm_refute_numbered_parameter(parser, message.
start, message.
end);
10727 parse_write_name(parser, &call->
name);
10728 return (
pm_node_t *) pm_call_target_node_create(parser, call);
10735 if (pm_call_node_index_p(call)) {
10736 return (
pm_node_t *) pm_index_target_node_create(parser, call);
10744 pm_parser_err_node(parser, target, PM_ERR_WRITE_TARGET_UNEXPECTED);
10755 pm_node_t *result = parse_target(parser, target);
10763 pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED);
10776 pm_node_destroy(parser, value);
10780 pm_node_destroy(parser, target);
10787 if (context_def_p(parser)) {
10788 pm_parser_err_node(parser, (
pm_node_t *) node, PM_ERR_WRITE_TARGET_IN_METHOD);
10790 pm_node_destroy(parser, target);
10795 pm_parser_err_node(parser, target, PM_ERR_WRITE_TARGET_READONLY);
10799 pm_node_destroy(parser, target);
10807 uint32_t depth = local_read->
depth;
10810 pm_node_destroy(parser, target);
10812 return (
pm_node_t *) pm_local_variable_write_node_create(parser, constant_id, depth, value, &name_loc,
operator);
10816 pm_node_destroy(parser, target);
10829 pm_multi_target_node_targets_append(parser, multi_target, (
pm_node_t *) splat);
10831 return (
pm_node_t *) pm_multi_write_node_create(parser, multi_target,
operator, value);
10845 (call->
block == NULL)
10859 pm_parser_local_add_location(parser, message.
start, message.
end);
10860 pm_node_destroy(parser, target);
10863 target = (
pm_node_t *) pm_local_variable_write_node_create(parser, constant_id, 0, value, &message,
operator);
10865 pm_refute_numbered_parameter(parser, message.
start, message.
end);
10883 pm_arguments_node_arguments_append(arguments, value);
10886 parse_write_name(parser, &call->
name);
10895 if (pm_call_node_index_p(call)) {
10897 call->
arguments = pm_arguments_node_create(parser);
10900 pm_arguments_node_arguments_append(call->
arguments, value);
10904 call->
name = pm_parser_constant_id_constant(parser,
"[]=", 3);
10914 pm_node_destroy(parser, value);
10921 pm_parser_err_token(parser,
operator, PM_ERR_WRITE_TARGET_UNEXPECTED);
10937parse_targets(
pm_parser_t *parser,
pm_node_t *first_target, pm_binding_power_t binding_power) {
10941 pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target));
10949 pm_parser_err_previous(parser, PM_ERR_MULTI_ASSIGN_MULTI_SPLATS);
10955 if (token_begins_expression_p(parser->
current.type)) {
10956 name = parse_expression(parser, binding_power,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
10957 name = parse_target(parser, name);
10960 pm_node_t *splat = (
pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
10961 pm_multi_target_node_targets_append(parser, result, splat);
10963 }
else if (token_begins_expression_p(parser->
current.type)) {
10964 pm_node_t *target = parse_expression(parser, binding_power,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
10965 target = parse_target(parser, target);
10967 pm_multi_target_node_targets_append(parser, result, target);
10972 pm_multi_target_node_targets_append(parser, result, rest);
10985parse_targets_validate(
pm_parser_t *parser,
pm_node_t *first_target, pm_binding_power_t binding_power) {
10986 pm_node_t *result = parse_targets(parser, first_target, binding_power);
10990 pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED);
11006 if (context_terminator(context, &parser->
current))
return NULL;
11012 context_push(parser, context);
11015 pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT,
true, PM_ERR_CANNOT_PARSE_EXPRESSION);
11016 pm_statements_node_body_append(statements, node);
11033 if (context_terminator(context, &parser->
current))
break;
11042 if (context_terminator(context, &parser->
current))
break;
11055 parser_lex(parser);
11058 if (context_terminator(context, &parser->
current))
break;
11064 context_pop(parser);
11074 bool contains_keyword_splat =
false;
11079 switch (parser->
current.type) {
11081 parser_lex(parser);
11085 if (token_begins_expression_p(parser->
current.type)) {
11086 value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
11087 }
else if (pm_parser_local_depth(parser, &
operator) == -1) {
11088 pm_parser_err_token(parser, &
operator, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
11091 element = (
pm_node_t *) pm_assoc_splat_node_create(parser, value, &
operator);
11092 contains_keyword_splat =
true;
11097 parser_lex(parser);
11103 if (token_begins_expression_p(parser->
current.type)) {
11104 value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL);
11108 value = (
pm_node_t *) pm_constant_read_node_create(parser, &constant);
11114 value = (
pm_node_t *) pm_call_node_variable_call_create(parser, &identifier);
11116 value = (
pm_node_t *) pm_local_variable_read_node_create(parser, &identifier, (uint32_t) depth);
11121 value = (
pm_node_t *) pm_implicit_node_create(parser, value);
11124 element = (
pm_node_t *) pm_assoc_node_create(parser, key, &
operator, value);
11128 pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_HASH_KEY);
11131 if (pm_symbol_node_label_p(key)) {
11132 operator = not_provided(parser);
11138 pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_HASH_VALUE);
11139 element = (
pm_node_t *) pm_assoc_node_create(parser, key, &
operator, value);
11159 if (token_begins_expression_p(parser->
current.type))
continue;
11164 return contains_keyword_splat;
11173 arguments->
arguments = pm_arguments_node_create(parser);
11176 pm_arguments_node_arguments_append(arguments->
arguments, argument);
11184 pm_binding_power_t binding_power = pm_binding_powers[parser->
current.type].left;
11190 (binding_power != PM_BINDING_POWER_UNSET && binding_power < PM_BINDING_POWER_RANGE) ||
11196 bool parsed_first_argument =
false;
11197 bool parsed_bare_hash =
false;
11198 bool parsed_block_argument =
false;
11199 bool parsed_forwarding_arguments =
false;
11202 if (parsed_block_argument) {
11203 pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK);
11205 if (parsed_forwarding_arguments) {
11206 pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES);
11211 switch (parser->
current.type) {
11214 if (parsed_bare_hash) {
11215 pm_parser_err_current(parser, PM_ERR_ARGUMENT_BARE_HASH);
11221 bool contains_keyword_splat = parse_assocs(parser, (
pm_node_t *) hash);
11222 parsed_bare_hash =
true;
11223 parse_arguments_append(parser, arguments, argument);
11224 if (contains_keyword_splat) {
11230 parser_lex(parser);
11234 if (token_begins_expression_p(parser->
current.type)) {
11235 expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_EXPECT_ARGUMENT);
11237 if (pm_parser_local_depth(parser, &
operator) == -1) {
11239 pm_constant_id_t ellipsis_id = pm_parser_constant_id_constant(parser,
"...", 3);
11240 if (pm_parser_local_depth_constant_id(parser, ellipsis_id) == -1) {
11241 pm_parser_err_token(parser, &
operator, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
11246 argument = (
pm_node_t *) pm_block_argument_node_create(parser, &
operator, expression);
11247 if (parsed_block_argument) {
11248 parse_arguments_append(parser, arguments, argument);
11250 arguments->
block = argument;
11253 parsed_block_argument =
true;
11257 parser_lex(parser);
11261 if (pm_parser_local_depth(parser, &parser->
previous) == -1) {
11262 pm_parser_err_token(parser, &
operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
11265 argument = (
pm_node_t *) pm_splat_node_create(parser, &
operator, NULL);
11267 pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT);
11269 if (parsed_bare_hash) {
11270 pm_parser_err(parser,
operator.start, expression->
location.
end, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT);
11273 argument = (
pm_node_t *) pm_splat_node_create(parser, &
operator, expression);
11276 parse_arguments_append(parser, arguments, argument);
11280 if (accepts_forwarding) {
11281 parser_lex(parser);
11283 if (token_begins_expression_p(parser->
current.type)) {
11287 pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
11288 argument = (
pm_node_t *) pm_range_node_create(parser, NULL, &
operator, right);
11290 if (pm_parser_local_depth(parser, &parser->
previous) == -1) {
11291 pm_parser_err_previous(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
11293 if (parsed_first_argument && terminator ==
PM_TOKEN_EOF) {
11294 pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORWARDING_UNBOUND);
11297 argument = (
pm_node_t *) pm_forwarding_arguments_node_create(parser, &parser->
previous);
11298 parse_arguments_append(parser, arguments, argument);
11299 parsed_forwarding_arguments =
true;
11306 if (argument == NULL) {
11307 argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, PM_ERR_EXPECT_ARGUMENT);
11310 bool contains_keyword_splat =
false;
11312 if (parsed_bare_hash) {
11313 pm_parser_err_previous(parser, PM_ERR_ARGUMENT_BARE_HASH);
11320 operator = not_provided(parser);
11326 pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_HASH_VALUE);
11328 argument = (
pm_node_t *) pm_assoc_node_create(parser, argument, &
operator, value);
11329 pm_keyword_hash_node_elements_append(bare_hash, argument);
11334 token_begins_expression_p(parser->
current.type) ||
11337 contains_keyword_splat = parse_assocs(parser, (
pm_node_t *) bare_hash);
11340 parsed_bare_hash =
true;
11343 parse_arguments_append(parser, arguments, argument);
11344 if (contains_keyword_splat) {
11351 parsed_first_argument =
true;
11373 if (match1(parser, terminator))
break;
11388parse_required_destructured_parameter(
pm_parser_t *parser) {
11392 pm_multi_target_node_opening_set(node, &parser->
previous);
11403 pm_multi_target_node_targets_append(parser, node, param);
11404 pm_parser_err_current(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
11409 param = (
pm_node_t *) parse_required_destructured_parameter(parser);
11416 value = (
pm_node_t *) pm_required_parameter_node_create(parser, &name);
11417 pm_parser_parameter_name_check(parser, &name);
11418 pm_parser_local_add_token(parser, &name);
11421 param = (
pm_node_t *) pm_splat_node_create(parser, &star, value);
11426 param = (
pm_node_t *) pm_required_parameter_node_create(parser, &name);
11427 pm_parser_parameter_name_check(parser, &name);
11428 pm_parser_local_add_token(parser, &name);
11431 pm_multi_target_node_targets_append(parser, node, param);
11435 pm_multi_target_node_closing_set(node, &parser->
previous);
11445 PM_PARAMETERS_NO_CHANGE = 0,
11446 PM_PARAMETERS_ORDER_NOTHING_AFTER = 1,
11447 PM_PARAMETERS_ORDER_KEYWORDS_REST,
11448 PM_PARAMETERS_ORDER_KEYWORDS,
11449 PM_PARAMETERS_ORDER_REST,
11450 PM_PARAMETERS_ORDER_AFTER_OPTIONAL,
11451 PM_PARAMETERS_ORDER_OPTIONAL,
11452 PM_PARAMETERS_ORDER_NAMED,
11453 PM_PARAMETERS_ORDER_NONE,
11455} pm_parameters_order_t;
11461 [0] = PM_PARAMETERS_NO_CHANGE,
11482 pm_parameters_order_t state = parameters_ordering[token->type];
11483 if (state == PM_PARAMETERS_NO_CHANGE)
return;
11487 if (*current == PM_PARAMETERS_ORDER_OPTIONAL && state == PM_PARAMETERS_ORDER_NAMED) {
11488 *current = PM_PARAMETERS_ORDER_AFTER_OPTIONAL;
11490 }
else if (*current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL && state == PM_PARAMETERS_ORDER_NAMED) {
11494 if (token->type ==
PM_TOKEN_USTAR && *current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
11495 pm_parser_err_token(parser, token, PM_ERR_PARAMETER_STAR);
11498 if (*current == PM_PARAMETERS_ORDER_NOTHING_AFTER || state > *current) {
11500 pm_parser_err_token(parser, token, PM_ERR_PARAMETER_ORDER);
11501 }
else if (state < *current) {
11512 pm_binding_power_t binding_power,
11513 bool uses_parentheses,
11514 bool allows_trailing_comma,
11515 bool allows_forwarding_parameters
11518 bool looping =
true;
11520 pm_do_loop_stack_push(parser,
false);
11521 pm_parameters_order_t order = PM_PARAMETERS_ORDER_NONE;
11524 switch (parser->
current.type) {
11526 update_parameter_state(parser, &parser->
current, &order);
11529 if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
11530 pm_parameters_node_requireds_append(params, param);
11532 pm_parameters_node_posts_append(params, param);
11538 update_parameter_state(parser, &parser->
current, &order);
11539 parser_lex(parser);
11546 pm_parser_parameter_name_check(parser, &name);
11547 pm_parser_local_add_token(parser, &name);
11549 name = not_provided(parser);
11551 if (allows_forwarding_parameters) {
11552 pm_parser_local_add_token(parser, &
operator);
11557 if (params->
block == NULL) {
11558 pm_parameters_node_block_set(params, param);
11560 pm_parser_err_node(parser, (
pm_node_t *) param, PM_ERR_PARAMETER_BLOCK_MULTI);
11561 pm_parameters_node_posts_append(params, (
pm_node_t *) param);
11567 if (!allows_forwarding_parameters) {
11568 pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
11571 if (order > PM_PARAMETERS_ORDER_NOTHING_AFTER) {
11572 update_parameter_state(parser, &parser->
current, &order);
11573 parser_lex(parser);
11575 if (allows_forwarding_parameters) {
11576 pm_parser_local_add_token(parser, &parser->
previous);
11584 pm_parameters_node_posts_append(params, keyword_rest);
11585 pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_FWD);
11588 pm_parameters_node_keyword_rest_set(params, (
pm_node_t *)param);
11590 update_parameter_state(parser, &parser->
current, &order);
11591 parser_lex(parser);
11602 parser_lex(parser);
11605 pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORMAL_CONSTANT);
11608 pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORMAL_IVAR);
11611 pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORMAL_GLOBAL);
11614 pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORMAL_CLASS);
11617 pm_parser_err_previous(parser, PM_ERR_PARAMETER_METHOD_NAME);
11623 update_parameter_state(parser, &parser->
current, &order);
11625 update_parameter_state(parser, &parser->
previous, &order);
11629 pm_parser_parameter_name_check(parser, &name);
11630 pm_parser_local_add_token(parser, &name);
11637 pm_node_t *value = parse_value_expression(parser, binding_power,
false, PM_ERR_PARAMETER_NO_DEFAULT);
11640 pm_parameters_node_optionals_append(params, param);
11643 context_pop(parser);
11652 }
else if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
11654 pm_parameters_node_requireds_append(params, (
pm_node_t *) param);
11657 pm_parameters_node_posts_append(params, (
pm_node_t *) param);
11664 update_parameter_state(parser, &parser->
current, &order);
11665 parser_lex(parser);
11671 pm_parser_parameter_name_check(parser, &local);
11672 pm_parser_local_add_token(parser, &local);
11674 switch (parser->
current.type) {
11678 pm_node_t *param = (
pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
11679 pm_parameters_node_keywords_append(params, param);
11684 if (uses_parentheses) {
11689 pm_node_t *param = (
pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
11690 pm_parameters_node_keywords_append(params, param);
11696 if (token_begins_expression_p(parser->
current.type)) {
11700 pm_node_t *value = parse_value_expression(parser, binding_power,
false, PM_ERR_PARAMETER_NO_DEFAULT_KW);
11702 context_pop(parser);
11703 param = (
pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value);
11706 param = (
pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
11709 pm_parameters_node_keywords_append(params, param);
11726 update_parameter_state(parser, &parser->
current, &order);
11727 parser_lex(parser);
11734 pm_parser_parameter_name_check(parser, &name);
11735 pm_parser_local_add_token(parser, &name);
11737 name = not_provided(parser);
11739 if (allows_forwarding_parameters) {
11740 pm_parser_local_add_token(parser, &
operator);
11744 pm_node_t *param = (
pm_node_t *) pm_rest_parameter_node_create(parser, &
operator, &name);
11745 if (params->
rest == NULL) {
11746 pm_parameters_node_rest_set(params, param);
11748 pm_parser_err_node(parser, param, PM_ERR_PARAMETER_SPLAT_MULTI);
11749 pm_parameters_node_posts_append(params, param);
11756 update_parameter_state(parser, &parser->
current, &order);
11757 parser_lex(parser);
11763 param = (
pm_node_t *) pm_no_keywords_parameter_node_create(parser, &
operator, &parser->
previous);
11769 pm_parser_parameter_name_check(parser, &name);
11770 pm_parser_local_add_token(parser, &name);
11772 name = not_provided(parser);
11774 if (allows_forwarding_parameters) {
11775 pm_parser_local_add_token(parser, &
operator);
11779 param = (
pm_node_t *) pm_keyword_rest_parameter_node_create(parser, &
operator, &name);
11783 pm_parameters_node_keyword_rest_set(params, param);
11785 pm_parser_err_node(parser, param, PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI);
11786 pm_parameters_node_posts_append(params, param);
11793 if (allows_trailing_comma) {
11798 if (params->
rest == NULL) {
11799 pm_parameters_node_rest_set(params, param);
11801 pm_parser_err_node(parser, (
pm_node_t *) param, PM_ERR_PARAMETER_SPLAT_MULTI);
11802 pm_parameters_node_posts_append(params, (
pm_node_t *) param);
11805 pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
11813 if (looping && uses_parentheses) {
11818 pm_do_loop_stack_pop(parser);
11822 pm_node_destroy(parser, (
pm_node_t *) params);
11840 switch (parser->
current.type) {
11845 parser_lex(parser);
11846 pm_rescue_node_operator_set(rescue, &parser->
previous);
11848 pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX,
false, PM_ERR_RESCUE_VARIABLE);
11849 reference = parse_target(parser, reference);
11851 pm_rescue_node_reference_set(rescue, reference);
11866 pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_RESCUE_EXPRESSION);
11867 pm_rescue_node_exceptions_append(rescue, expression);
11876 pm_rescue_node_operator_set(rescue, &parser->
previous);
11878 pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX,
false, PM_ERR_RESCUE_VARIABLE);
11879 reference = parse_target(parser, reference);
11881 pm_rescue_node_reference_set(rescue, reference);
11896 pm_accepts_block_stack_push(parser,
true);
11899 pm_rescue_node_statements_set(rescue, statements);
11901 pm_accepts_block_stack_pop(parser);
11905 if (current == NULL) {
11906 pm_begin_node_rescue_clause_set(parent_node, rescue);
11908 pm_rescue_node_consequent_set(current, rescue);
11932 pm_accepts_block_stack_push(parser,
true);
11934 pm_accepts_block_stack_pop(parser);
11938 pm_else_node_t *else_clause = pm_else_node_create(parser, &else_keyword, else_statements, &parser->
current);
11939 pm_begin_node_else_clause_set(parent_node, else_clause);
11948 pm_accepts_block_stack_push(parser,
true);
11950 pm_accepts_block_stack_pop(parser);
11954 pm_ensure_node_t *ensure_clause = pm_ensure_node_create(parser, &ensure_keyword, ensure_statements, &parser->
current);
11955 pm_begin_node_ensure_clause_set(parent_node, ensure_clause);
11959 pm_begin_node_end_keyword_set(parent_node, &parser->
current);
11962 pm_begin_node_end_keyword_set(parent_node, &end_keyword);
11968 pm_token_t no_begin_token = not_provided(parser);
11969 pm_begin_node_t *begin_node = pm_begin_node_create(parser, &no_begin_token, statements);
11970 parse_rescues(parser, begin_node, def_p);
11994parse_block_parameters(
11996 bool allows_trailing_comma,
11998 bool is_lambda_literal
12002 parameters = parse_parameters(
12004 is_lambda_literal ? PM_BINDING_POWER_DEFINED : PM_BINDING_POWER_INDEX,
12006 allows_trailing_comma,
12015 pm_parser_parameter_name_check(parser, &parser->
previous);
12016 pm_parser_local_add_token(parser, &parser->
previous);
12019 pm_block_parameters_node_append_local(block_parameters, local);
12023 return block_parameters;
12034 pm_accepts_block_stack_push(parser,
true);
12035 pm_parser_scope_push(parser,
false);
12043 block_parameters = pm_block_parameters_node_create(parser, NULL, &block_parameters_opening);
12045 parser_lex(parser);
12047 block_parameters = parse_block_parameters(parser,
true, &block_parameters_opening,
false);
12050 expect1(parser,
PM_TOKEN_PIPE, PM_ERR_BLOCK_PARAM_PIPE_TERM);
12053 pm_block_parameters_node_closing_set(block_parameters, &parser->
previous);
12056 uint32_t locals_body_index = 0;
12058 if (block_parameters) {
12074 pm_accepts_block_stack_push(parser,
true);
12076 pm_accepts_block_stack_pop(parser);
12091 if (parameters == NULL && (maximum > 0)) {
12093 locals_body_index = maximum;
12097 pm_parser_scope_pop(parser);
12098 pm_accepts_block_stack_pop(parser);
12099 return pm_block_node_create(parser, &locals, locals_body_index, &opening, parameters, statements, &parser->
previous);
12109 bool found =
false;
12118 pm_accepts_block_stack_push(parser,
true);
12121 pm_accepts_block_stack_pop(parser);
12127 pm_accepts_block_stack_push(parser,
false);
12132 parse_arguments(parser, arguments,
true,
PM_TOKEN_EOF);
12138 pm_parser_err_previous(parser, PM_ERR_EXPECT_ARGUMENT);
12141 pm_accepts_block_stack_pop(parser);
12147 if (accepts_block) {
12152 block = parse_block(parser);
12153 pm_arguments_validate_block(parser, arguments, block);
12156 block = parse_block(parser);
12159 if (block != NULL) {
12160 if (arguments->
block == NULL) {
12163 pm_parser_err_node(parser, (
pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI);
12165 arguments->
arguments = pm_arguments_node_create(parser);
12167 pm_arguments_node_arguments_append(arguments->
arguments, arguments->
block);
12180 pm_node_t *predicate = parse_value_expression(parser, binding_power,
true, error_id);
12186 predicate_closed =
true;
12190 if (!predicate_closed) {
12191 pm_parser_err_current(parser, PM_ERR_CONDITIONAL_PREDICATE_TERM);
12194 context_pop(parser);
12201 pm_token_t then_keyword = not_provided(parser);
12203 pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context, &then_keyword);
12207 pm_accepts_block_stack_push(parser,
true);
12208 statements = parse_statements(parser, context);
12209 pm_accepts_block_stack_pop(parser);
12213 pm_token_t end_keyword = not_provided(parser);
12218 parent = (
pm_node_t *) pm_if_node_create(parser, &keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
12221 parent = (
pm_node_t *) pm_unless_node_create(parser, &keyword, predicate, &then_keyword, statements);
12224 assert(
false &&
"unreachable");
12236 pm_accepts_block_stack_push(parser,
true);
12238 pm_accepts_block_stack_pop(parser);
12242 pm_node_t *elsif = (
pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
12249 parser_lex(parser);
12252 pm_accepts_block_stack_push(parser,
true);
12254 pm_accepts_block_stack_pop(parser);
12259 pm_else_node_t *else_node = pm_else_node_create(parser, &else_keyword, else_statements, &parser->
previous);
12269 assert(
false &&
"unreachable");
12281 bool recursing =
true;
12283 while (recursing) {
12288 recursing = current != NULL;
12306 assert(
false &&
"unreachable");
12317#define PM_CASE_KEYWORD PM_TOKEN_KEYWORD___ENCODING__: case PM_TOKEN_KEYWORD___FILE__: case PM_TOKEN_KEYWORD___LINE__: \
12318 case PM_TOKEN_KEYWORD_ALIAS: case PM_TOKEN_KEYWORD_AND: case PM_TOKEN_KEYWORD_BEGIN: case PM_TOKEN_KEYWORD_BEGIN_UPCASE: \
12319 case PM_TOKEN_KEYWORD_BREAK: case PM_TOKEN_KEYWORD_CASE: case PM_TOKEN_KEYWORD_CLASS: case PM_TOKEN_KEYWORD_DEF: \
12320 case PM_TOKEN_KEYWORD_DEFINED: case PM_TOKEN_KEYWORD_DO: case PM_TOKEN_KEYWORD_DO_LOOP: case PM_TOKEN_KEYWORD_ELSE: \
12321 case PM_TOKEN_KEYWORD_ELSIF: case PM_TOKEN_KEYWORD_END: case PM_TOKEN_KEYWORD_END_UPCASE: case PM_TOKEN_KEYWORD_ENSURE: \
12322 case PM_TOKEN_KEYWORD_FALSE: case PM_TOKEN_KEYWORD_FOR: case PM_TOKEN_KEYWORD_IF: case PM_TOKEN_KEYWORD_IN: \
12323 case PM_TOKEN_KEYWORD_MODULE: case PM_TOKEN_KEYWORD_NEXT: case PM_TOKEN_KEYWORD_NIL: case PM_TOKEN_KEYWORD_NOT: \
12324 case PM_TOKEN_KEYWORD_OR: case PM_TOKEN_KEYWORD_REDO: case PM_TOKEN_KEYWORD_RESCUE: case PM_TOKEN_KEYWORD_RETRY: \
12325 case PM_TOKEN_KEYWORD_RETURN: case PM_TOKEN_KEYWORD_SELF: case PM_TOKEN_KEYWORD_SUPER: case PM_TOKEN_KEYWORD_THEN: \
12326 case PM_TOKEN_KEYWORD_TRUE: case PM_TOKEN_KEYWORD_UNDEF: case PM_TOKEN_KEYWORD_UNLESS: case PM_TOKEN_KEYWORD_UNTIL: \
12327 case PM_TOKEN_KEYWORD_WHEN: case PM_TOKEN_KEYWORD_WHILE: case PM_TOKEN_KEYWORD_YIELD
12333#define PM_CASE_OPERATOR PM_TOKEN_AMPERSAND: case PM_TOKEN_BACKTICK: case PM_TOKEN_BANG_EQUAL: \
12334 case PM_TOKEN_BANG_TILDE: case PM_TOKEN_BANG: case PM_TOKEN_BRACKET_LEFT_RIGHT_EQUAL: \
12335 case PM_TOKEN_BRACKET_LEFT_RIGHT: case PM_TOKEN_CARET: case PM_TOKEN_EQUAL_EQUAL_EQUAL: case PM_TOKEN_EQUAL_EQUAL: \
12336 case PM_TOKEN_EQUAL_TILDE: case PM_TOKEN_GREATER_EQUAL: case PM_TOKEN_GREATER_GREATER: case PM_TOKEN_GREATER: \
12337 case PM_TOKEN_LESS_EQUAL_GREATER: case PM_TOKEN_LESS_EQUAL: case PM_TOKEN_LESS_LESS: case PM_TOKEN_LESS: \
12338 case PM_TOKEN_MINUS: case PM_TOKEN_PERCENT: case PM_TOKEN_PIPE: case PM_TOKEN_PLUS: case PM_TOKEN_SLASH: \
12339 case PM_TOKEN_STAR_STAR: case PM_TOKEN_STAR: case PM_TOKEN_TILDE: case PM_TOKEN_UAMPERSAND: case PM_TOKEN_UMINUS: \
12340 case PM_TOKEN_UMINUS_NUM: case PM_TOKEN_UPLUS: case PM_TOKEN_USTAR: case PM_TOKEN_USTAR_STAR
12347#define PM_CASE_PRIMITIVE PM_TOKEN_INTEGER: case PM_TOKEN_INTEGER_IMAGINARY: case PM_TOKEN_INTEGER_RATIONAL: \
12348 case PM_TOKEN_INTEGER_RATIONAL_IMAGINARY: case PM_TOKEN_FLOAT: case PM_TOKEN_FLOAT_IMAGINARY: \
12349 case PM_TOKEN_FLOAT_RATIONAL: case PM_TOKEN_FLOAT_RATIONAL_IMAGINARY: case PM_TOKEN_SYMBOL_BEGIN: \
12350 case PM_TOKEN_REGEXP_BEGIN: case PM_TOKEN_BACKTICK: case PM_TOKEN_PERCENT_LOWER_X: case PM_TOKEN_PERCENT_LOWER_I: \
12351 case PM_TOKEN_PERCENT_LOWER_W: case PM_TOKEN_PERCENT_UPPER_I: case PM_TOKEN_PERCENT_UPPER_W: \
12352 case PM_TOKEN_STRING_BEGIN: case PM_TOKEN_KEYWORD_NIL: case PM_TOKEN_KEYWORD_SELF: case PM_TOKEN_KEYWORD_TRUE: \
12353 case PM_TOKEN_KEYWORD_FALSE: case PM_TOKEN_KEYWORD___FILE__: case PM_TOKEN_KEYWORD___LINE__: \
12354 case PM_TOKEN_KEYWORD___ENCODING__: case PM_TOKEN_MINUS_GREATER: case PM_TOKEN_HEREDOC_START: \
12355 case PM_TOKEN_UMINUS_NUM: case PM_TOKEN_CHARACTER_LITERAL
12361#define PM_CASE_PARAMETER PM_TOKEN_UAMPERSAND: case PM_TOKEN_AMPERSAND: case PM_TOKEN_UDOT_DOT_DOT: \
12362 case PM_TOKEN_IDENTIFIER: case PM_TOKEN_LABEL: case PM_TOKEN_USTAR: case PM_TOKEN_STAR: case PM_TOKEN_STAR_STAR: \
12363 case PM_TOKEN_USTAR_STAR: case PM_TOKEN_CONSTANT: case PM_TOKEN_INSTANCE_VARIABLE: case PM_TOKEN_GLOBAL_VARIABLE: \
12364 case PM_TOKEN_CLASS_VARIABLE
12370#define PM_CASE_WRITABLE PM_CLASS_VARIABLE_READ_NODE: case PM_CONSTANT_PATH_NODE: \
12371 case PM_CONSTANT_READ_NODE: case PM_GLOBAL_VARIABLE_READ_NODE: case PM_LOCAL_VARIABLE_READ_NODE: \
12372 case PM_INSTANCE_VARIABLE_READ_NODE: case PM_MULTI_TARGET_NODE: case PM_BACK_REFERENCE_READ_NODE: \
12373 case PM_NUMBERED_REFERENCE_READ_NODE
12384parse_unescaped_encoding(
const pm_parser_t *parser) {
12401 switch (parser->
current.type) {
12413 pm_node_flag_set(node, parse_unescaped_encoding(parser));
12415 parser_lex(parser);
12429 lex_state_set(parser, PM_LEX_STATE_BEG);
12430 parser_lex(parser);
12436 pm_accepts_block_stack_push(parser,
true);
12438 pm_accepts_block_stack_pop(parser);
12442 lex_state_set(parser, state);
12447 return (
pm_node_t *) pm_embedded_statements_node_create(parser, &opening, statements, &closing);
12457 lex_state_set(parser, PM_LEX_STATE_BEG);
12458 parser_lex(parser);
12463 switch (parser->
current.type) {
12467 parser_lex(parser);
12468 variable = (
pm_node_t *) pm_back_reference_read_node_create(parser, &parser->
previous);
12473 parser_lex(parser);
12474 variable = (
pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->
previous);
12479 parser_lex(parser);
12480 variable = (
pm_node_t *) pm_global_variable_read_node_create(parser, &parser->
previous);
12485 parser_lex(parser);
12486 variable = (
pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->
previous);
12491 parser_lex(parser);
12492 variable = (
pm_node_t *) pm_class_variable_read_node_create(parser, &parser->
previous);
12503 return (
pm_node_t *) pm_embedded_variable_node_create(parser, &
operator, variable);
12506 parser_lex(parser);
12507 pm_parser_err_previous(parser, PM_ERR_CANNOT_PARSE_STRING_PART);
12516 if (lex_mode->
mode != PM_LEX_STRING) {
12517 if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
12519 switch (parser->
current.type) {
12528 case PM_CASE_KEYWORD:
12529 parser_lex(parser);
12531 case PM_CASE_OPERATOR:
12532 lex_state_set(parser, next_state == PM_LEX_STATE_NONE ? PM_LEX_STATE_ENDFN : next_state);
12533 parser_lex(parser);
12550 if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
12551 parser_lex(parser);
12555 return (
pm_node_t *) pm_symbol_node_create(parser, &opening, &content, &closing);
12559 pm_node_t *part = parse_string_part(parser);
12564 if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
12573 if (part) pm_node_list_append(&node_list, part);
12576 if ((part = parse_string_part(parser)) != NULL) {
12577 pm_node_list_append(&node_list, part);
12581 if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
12583 pm_parser_err_token(parser, &opening, PM_ERR_SYMBOL_TERM_INTERPOLATED);
12588 return (
pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &node_list, &parser->
previous);
12597 parser_lex(parser);
12612 pm_node_t *part = (
pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &unescaped);
12613 pm_node_list_append(&parts, part);
12616 pm_node_list_append(&parts, part);
12618 if (next_state != PM_LEX_STATE_NONE) {
12619 lex_state_set(parser, next_state);
12622 parser_lex(parser);
12624 return (
pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->
previous);
12628 pm_string_shared_init(&unescaped, content.
start, content.
end);
12631 if (next_state != PM_LEX_STATE_NONE) {
12632 lex_state_set(parser, next_state);
12636 pm_parser_err_token(parser, &opening, PM_ERR_SYMBOL_TERM_DYNAMIC);
12640 return (
pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->
previous, &unescaped);
12649 switch (parser->
current.type) {
12650 case PM_CASE_KEYWORD:
12651 case PM_CASE_OPERATOR:
12655 parser_lex(parser);
12666 parser_lex(parser);
12668 return parse_symbol(parser, &lex_mode, PM_LEX_STATE_NONE);
12671 pm_parser_err_current(parser, PM_ERR_UNDEF_ARGUMENT);
12683parse_alias_argument(
pm_parser_t *parser,
bool first) {
12684 switch (parser->
current.type) {
12685 case PM_CASE_OPERATOR:
12686 case PM_CASE_KEYWORD:
12691 lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM);
12694 parser_lex(parser);
12704 parser_lex(parser);
12706 return parse_symbol(parser, &lex_mode, first ? PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM : PM_LEX_STATE_NONE);
12709 parser_lex(parser);
12710 return (
pm_node_t *) pm_back_reference_read_node_create(parser, &parser->
previous);
12712 parser_lex(parser);
12713 return (
pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->
previous);
12715 parser_lex(parser);
12716 return (
pm_node_t *) pm_global_variable_read_node_create(parser, &parser->
previous);
12718 pm_parser_err_current(parser, PM_ERR_ALIAS_ARGUMENT);
12728outer_scope_using_numbered_parameters_p(
pm_parser_t *parser) {
12745 if ((depth = pm_parser_local_depth(parser, &parser->
previous)) != -1) {
12746 return (
pm_node_t *) pm_local_variable_read_node_create(parser, &parser->
previous, (uint32_t) depth);
12755 pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED);
12756 }
else if (outer_scope_using_numbered_parameters_p(parser)) {
12757 pm_parser_err_previous(parser, PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE);
12765 uint8_t numbered_parameters = (uint8_t) (number -
'0');
12768 pm_parser_numbered_parameters_set(parser, numbered_parameters);
12776 uint8_t current =
'1';
12779 while (current < number) {
12782 value[1] = current++;
12783 pm_parser_local_add_owned(parser, value, 2);
12789 pm_parser_local_add_token(parser, &parser->
previous);
12790 return (
pm_node_t *) pm_local_variable_read_node_create(parser, &parser->
previous, 0);
12798 pm_node_flag_set((
pm_node_t *)node, flags);
12809parse_method_definition_name(
pm_parser_t *parser) {
12810 switch (parser->
current.type) {
12811 case PM_CASE_KEYWORD:
12814 parser_lex(parser);
12817 pm_refute_numbered_parameter(parser, parser->
current.start, parser->
current.end);
12818 parser_lex(parser);
12820 case PM_CASE_OPERATOR:
12821 lex_state_set(parser, PM_LEX_STATE_ENDFN);
12822 parser_lex(parser);
12830parse_heredoc_dedent_string(
pm_string_t *
string,
size_t common_whitespace) {
12833 pm_string_ensure_owned(
string);
12838 size_t dest_length = pm_string_length(
string);
12839 const uint8_t *source_cursor = (uint8_t *) string->
source;
12840 const uint8_t *source_end = source_cursor + dest_length;
12845 size_t trimmed_whitespace = 0;
12851 while ((source_cursor < source_end) && pm_char_is_inline_whitespace(*source_cursor) && trimmed_whitespace < common_whitespace) {
12852 if (*source_cursor ==
'\t') {
12853 trimmed_whitespace = (trimmed_whitespace / PM_TAB_WHITESPACE_SIZE + 1) * PM_TAB_WHITESPACE_SIZE;
12854 if (trimmed_whitespace > common_whitespace)
break;
12856 trimmed_whitespace++;
12863 memmove((uint8_t *) string->source, source_cursor, (
size_t) (source_end - source_cursor));
12864 string->length = dest_length;
12874 bool dedent_next =
true;
12879 size_t write_index = 0;
12881 for (
size_t read_index = 0; read_index < nodes->
size; read_index++) {
12888 nodes->
nodes[write_index++] = node;
12889 dedent_next =
false;
12895 parse_heredoc_dedent_string(&string_node->
unescaped, common_whitespace);
12899 pm_node_destroy(parser, node);
12901 nodes->
nodes[write_index++] = node;
12905 dedent_next =
true;
12908 nodes->
size = write_index;
12926 node = (
pm_node_t *)pm_constant_path_node_create(parser, node, &delimiter, child);
12945 inner = parse_pattern(parser,
true, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET);
12952 parser_lex(parser);
12956 inner = parse_pattern(parser,
true, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN);
12966 return (
pm_node_t *) pm_array_pattern_node_constant_create(parser, node, &opening, &closing);
12982 pattern_node->
opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
12983 pattern_node->
closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
12998 pattern_node->
opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
12999 pattern_node->
closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
13014 pattern_node->
opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
13015 pattern_node->
closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
13029 pm_array_pattern_node_t *pattern_node = pm_array_pattern_node_constant_create(parser, node, &opening, &closing);
13030 pm_array_pattern_node_requireds_append(pattern_node, inner);
13048 pm_parser_local_add_token(parser, &identifier);
13049 name = (
pm_node_t *) pm_local_variable_target_node_create(parser, &identifier);
13053 return pm_splat_node_create(parser, &
operator, name);
13062 parser_lex(parser);
13068 return (
pm_node_t *) pm_no_keywords_parameter_node_create(parser, &
operator, &parser->
previous);
13072 pm_parser_local_add_token(parser, &parser->
previous);
13073 value = (
pm_node_t *) pm_local_variable_target_node_create(parser, &parser->
previous);
13076 return (
pm_node_t *) pm_assoc_splat_node_create(parser, value, &
operator);
13092 pm_node_t *value = parse_pattern(parser,
false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY);
13096 assoc->
value = value;
13102 pm_parser_local_add_location(parser, value_loc->
start, value_loc->
end);
13106 pm_node_list_append(&assocs, first_assoc);
13111 rest = first_assoc;
13126 pm_node_t *assoc = parse_pattern_keyword_rest(parser);
13128 if (rest == NULL) {
13131 pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST);
13132 pm_node_list_append(&assocs, assoc);
13135 expect1(parser,
PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA);
13140 value = parse_pattern(parser,
false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY);
13143 pm_parser_local_add_location(parser, value_loc->
start, value_loc->
end);
13147 pm_node_t *assoc = (
pm_node_t *) pm_assoc_node_create(parser, key, &
operator, value);
13149 if (rest != NULL) {
13150 pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST);
13153 pm_node_list_append(&assocs, assoc);
13158 free(assocs.
nodes);
13168 switch (parser->
current.type) {
13171 parser_lex(parser);
13173 int depth = pm_parser_local_depth(parser, &name);
13176 pm_parser_local_add_token(parser, &name);
13178 return (
pm_node_t *) pm_local_variable_target_node_create_depth(parser, &name, (uint32_t) depth);
13182 parser_lex(parser);
13187 return (
pm_node_t *)pm_array_pattern_node_empty_create(parser, &opening, &parser->
previous);
13192 pm_node_t *inner = parse_pattern(parser,
true, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET);
13206 pattern_node->
opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
13207 pattern_node->
closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
13220 pattern_node->
opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
13221 pattern_node->
closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
13233 pm_array_pattern_node_requireds_append(node, inner);
13242 parser_lex(parser);
13247 node = pm_hash_pattern_node_empty_create(parser, &opening, &parser->
previous);
13251 switch (parser->
current.type) {
13253 parser_lex(parser);
13258 first_assoc = (
pm_node_t *) pm_assoc_node_create(parser, (
pm_node_t *) key, &
operator, NULL);
13262 first_assoc = parse_pattern_keyword_rest(parser);
13265 pm_node_t *key = parse_expression(parser, PM_BINDING_POWER_MAX,
false, PM_ERR_PATTERN_HASH_KEY);
13268 if (!pm_symbol_node_label_p(key)) {
13269 pm_parser_err_node(parser, key, PM_ERR_PATTERN_HASH_KEY_LABEL);
13272 first_assoc = (
pm_node_t *) pm_assoc_node_create(parser, key, &
operator, NULL);
13276 parser_lex(parser);
13277 pm_parser_err_previous(parser, PM_ERR_PATTERN_HASH_KEY);
13282 first_assoc = (
pm_node_t *) pm_assoc_node_create(parser, (
pm_node_t *) key, &
operator, NULL);
13287 node = parse_pattern_hash(parser, first_assoc);
13296 node->
opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
13297 node->
closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
13306 parser_lex(parser);
13310 switch (parser->
current.type) {
13311 case PM_CASE_PRIMITIVE: {
13312 pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX,
false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
13313 return (
pm_node_t *) pm_range_node_create(parser, NULL, &
operator, right);
13316 pm_parser_err_token(parser, &
operator, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
13317 pm_node_t *right = (
pm_node_t *) pm_missing_node_create(parser,
operator.start,
operator.end);
13318 return (
pm_node_t *) pm_range_node_create(parser, NULL, &
operator, right);
13322 case PM_CASE_PRIMITIVE: {
13323 pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX,
false, diag_id);
13332 switch (parser->
current.type) {
13333 case PM_CASE_PRIMITIVE: {
13334 pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX,
false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
13335 return (
pm_node_t *) pm_range_node_create(parser, node, &
operator, right);
13338 return (
pm_node_t *) pm_range_node_create(parser, node, &
operator, NULL);
13345 parser_lex(parser);
13350 switch (parser->
current.type) {
13352 parser_lex(parser);
13355 return (
pm_node_t *) pm_pinned_variable_node_create(parser, &
operator, variable);
13358 parser_lex(parser);
13361 return (
pm_node_t *) pm_pinned_variable_node_create(parser, &
operator, variable);
13364 parser_lex(parser);
13367 return (
pm_node_t *) pm_pinned_variable_node_create(parser, &
operator, variable);
13370 parser_lex(parser);
13373 return (
pm_node_t *) pm_pinned_variable_node_create(parser, &
operator, variable);
13376 parser_lex(parser);
13379 return (
pm_node_t *) pm_pinned_variable_node_create(parser, &
operator, variable);
13382 parser_lex(parser);
13385 return (
pm_node_t *) pm_pinned_variable_node_create(parser, &
operator, variable);
13392 parser_lex(parser);
13394 pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT,
true, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
13399 return (
pm_node_t *) pm_pinned_expression_node_create(parser, expression, &
operator, &lparen, &parser->
previous);
13404 pm_parser_err_token(parser, &
operator, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
13405 pm_node_t *variable = (
pm_node_t *) pm_missing_node_create(parser,
operator.start,
operator.end);
13406 return (
pm_node_t *) pm_pinned_variable_node_create(parser, &
operator, variable);
13412 parser_lex(parser);
13418 return parse_pattern_constant_path(parser, (
pm_node_t *)node);
13422 parser_lex(parser);
13425 return parse_pattern_constant_path(parser, node);
13428 pm_parser_err_current(parser, diag_id);
13444 switch (parser->
current.type) {
13453 case PM_CASE_PRIMITIVE: {
13454 if (node == NULL) {
13455 node = parse_pattern_primitive(parser, diag_id);
13457 pm_node_t *right = parse_pattern_primitive(parser, PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE);
13458 node = (
pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &
operator);
13464 parser_lex(parser);
13465 if (node != NULL) {
13466 pm_node_destroy(parser, node);
13468 node = parse_pattern(parser,
false, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN);
13474 pm_parser_err_current(parser, diag_id);
13477 if (node == NULL) {
13480 node = (
pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &
operator);
13495 int depth = pm_parser_local_depth(parser, &identifier);
13498 pm_parser_local_add_token(parser, &identifier);
13501 pm_node_t *target = (
pm_node_t *) pm_local_variable_target_node_create_depth(parser, &identifier, (uint32_t) depth);
13502 node = (
pm_node_t *) pm_capture_pattern_node_create(parser, node, target, &
operator);
13515 bool leading_rest =
false;
13516 bool trailing_rest =
false;
13518 switch (parser->
current.type) {
13520 parser_lex(parser);
13524 return (
pm_node_t *) parse_pattern_hash(parser, (
pm_node_t *) pm_assoc_node_create(parser, key, &
operator, NULL));
13527 node = parse_pattern_keyword_rest(parser);
13528 return (
pm_node_t *) parse_pattern_hash(parser, node);
13532 parser_lex(parser);
13533 node = (
pm_node_t *) parse_pattern_rest(parser);
13534 leading_rest =
true;
13540 node = parse_pattern_primitives(parser, diag_id);
13546 if (pm_symbol_node_label_p(node)) {
13548 return (
pm_node_t *) parse_pattern_hash(parser, (
pm_node_t *) pm_assoc_node_create(parser, node, &
operator, NULL));
13556 pm_node_list_append(&nodes, node);
13563 pm_node_list_append(&nodes, node);
13568 node = (
pm_node_t *) parse_pattern_rest(parser);
13573 if (trailing_rest) {
13574 pm_parser_err_previous(parser, PM_ERR_PATTERN_REST);
13577 trailing_rest =
true;
13579 node = parse_pattern_primitives(parser, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA);
13582 pm_node_list_append(&nodes, node);
13590 node = (
pm_node_t *) pm_find_pattern_node_create(parser, &nodes);
13592 node = (
pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes);
13596 }
else if (leading_rest) {
13599 node = (
pm_node_t *) pm_array_pattern_node_rest_create(parser, node);
13611parse_negative_numeric(
pm_node_t *node) {
13626 assert(
false &&
"unreachable");
13635parse_strings_empty_content(
const uint8_t *location) {
13646 bool concating =
false;
13647 bool state_is_arg_labeled = lex_state_p(parser, PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED);
13655 assert(lex_mode->
mode == PM_LEX_STRING);
13659 parser_lex(parser);
13681 }
else if (!lex_interpolation) {
13688 content = not_provided(parser);
13709 pm_token_t delimiters = not_provided(parser);
13710 pm_node_t *part = (
pm_node_t *) pm_string_node_create_unescaped(parser, &delimiters, &content, &delimiters, &unescaped);
13711 pm_node_list_append(&parts, part);
13714 part = (
pm_node_t *) pm_string_node_create_current_string(parser, &delimiters, &parser->
current, &delimiters);
13715 pm_node_list_append(&parts, part);
13716 parser_lex(parser);
13720 node = (
pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->
previous);
13722 node = (
pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->
previous, &unescaped);
13724 pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_TERM);
13725 node = (
pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->
current, &unescaped);
13728 node = (
pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->
previous, &unescaped);
13737 parser_lex(parser);
13740 node = (
pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->
current, &unescaped);
13741 pm_node_flag_set(node, parse_unescaped_encoding(parser));
13744 node = (
pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->
previous, &unescaped);
13749 pm_token_t string_opening = not_provided(parser);
13750 pm_token_t string_closing = not_provided(parser);
13752 pm_node_t *part = (
pm_node_t *) pm_string_node_create_unescaped(parser, &string_opening, &parser->
previous, &string_closing, &unescaped);
13753 pm_node_flag_set(part, parse_unescaped_encoding(parser));
13754 pm_node_list_append(&parts, part);
13757 if ((part = parse_string_part(parser)) != NULL) {
13758 pm_node_list_append(&parts, part);
13763 node = (
pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->
previous);
13765 pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
13766 node = (
pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->
current);
13769 node = (
pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->
previous);
13780 if ((part = parse_string_part(parser)) != NULL) {
13781 pm_node_list_append(&parts, part);
13786 node = (
pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->
previous);
13788 pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
13789 node = (
pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->
current);
13792 node = (
pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->
previous);
13796 if (current == NULL) {
13812 pm_parser_err_node(parser, node, PM_ERR_STRING_CONCATENATION);
13822 pm_interpolated_string_node_append(container, current);
13837parse_expression_prefix(
pm_parser_t *parser, pm_binding_power_t binding_power,
bool accepts_command_call) {
13838 switch (parser->
current.type) {
13840 parser_lex(parser);
13843 pm_accepts_block_stack_push(parser,
true);
13844 bool parsed_bare_hash =
false;
13853 if (pm_array_node_size(array) != 0) {
13869 if (pm_parser_local_depth(parser, &parser->
previous) == -1) {
13870 pm_parser_err_token(parser, &
operator, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
13873 expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR);
13876 element = (
pm_node_t *) pm_splat_node_create(parser, &
operator, expression);
13878 if (parsed_bare_hash) {
13879 pm_parser_err_current(parser, PM_ERR_EXPRESSION_BARE_HASH);
13886 parse_assocs(parser, (
pm_node_t *) hash);
13889 parsed_bare_hash =
true;
13891 element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_ARRAY_EXPRESSION);
13894 if (parsed_bare_hash) {
13895 pm_parser_err_previous(parser, PM_ERR_EXPRESSION_BARE_HASH);
13904 operator = not_provided(parser);
13907 pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_HASH_VALUE);
13908 pm_node_t *assoc = (
pm_node_t *) pm_assoc_node_create(parser, element, &
operator, value);
13909 pm_keyword_hash_node_elements_append(hash, assoc);
13913 parse_assocs(parser, (
pm_node_t *) hash);
13916 parsed_bare_hash =
true;
13920 pm_array_node_elements_append(array, element);
13926 pm_array_node_close_set(array, &parser->
previous);
13927 pm_accepts_block_stack_pop(parser);
13934 parser_lex(parser);
13941 return (
pm_node_t *) pm_parentheses_node_create(parser, &opening, NULL, &parser->
previous);
13946 pm_accepts_block_stack_push(parser,
true);
13948 pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT,
true, PM_ERR_CANNOT_PARSE_EXPRESSION);
13949 context_pop(parser);
13955 if (terminator_found) {
13964 lex_state_set(parser, PM_LEX_STATE_ENDARG);
13966 parser_lex(parser);
13967 pm_accepts_block_stack_pop(parser);
13978 multi_target = pm_multi_target_node_create(parser);
13979 pm_multi_target_node_targets_append(parser, multi_target, statement);
13982 pm_location_t lparen_loc = PM_LOCATION_TOKEN_VALUE(&opening);
13991 if (binding_power == PM_BINDING_POWER_STATEMENT) {
13992 return parse_targets_validate(parser, (
pm_node_t *) multi_target, PM_BINDING_POWER_INDEX);
13997 return parse_target_validate(parser, (
pm_node_t *) multi_target);
14004 pm_statements_node_body_append(statements, statement);
14014 pm_statements_node_body_append(statements, statement);
14018 if (!terminator_found) {
14019 pm_parser_err(parser, parser->
current.start, parser->
current.start, PM_ERR_EXPECT_EOL_AFTER_STATEMENT);
14024 pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT,
true, PM_ERR_CANNOT_PARSE_EXPRESSION);
14025 pm_statements_node_body_append(statements, node);
14048 pm_parser_err(parser, parser->
current.start, parser->
current.start, PM_ERR_EXPECT_EOL_AFTER_STATEMENT);
14052 context_pop(parser);
14053 pm_accepts_block_stack_pop(parser);
14059 pm_accepts_block_stack_push(parser,
true);
14060 parser_lex(parser);
14064 parse_assocs(parser, (
pm_node_t *) node);
14068 pm_accepts_block_stack_pop(parser);
14070 pm_hash_node_closing_loc_set(node, &parser->
previous);
14075 parser_lex(parser);
14086 pm_node_t *node = (
pm_node_t *) pm_string_node_create_current_string(parser, &opening, &content, &closing);
14087 pm_node_flag_set(node, parse_unescaped_encoding(parser));
14092 return parse_strings(parser, node);
14098 parser_lex(parser);
14101 if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
14102 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14108 parser_lex(parser);
14119 parse_arguments_list(parser, &arguments,
true, accepts_command_call);
14120 return (
pm_node_t *) pm_call_node_fcall_create(parser, &constant, &arguments);
14125 if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser,
PM_TOKEN_COMMA)) {
14128 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14134 parser_lex(parser);
14140 pm_node_t *node = (
pm_node_t *)pm_constant_path_node_create(parser, NULL, &delimiter, constant);
14142 if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser,
PM_TOKEN_COMMA)) {
14143 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14151 parser_lex(parser);
14153 pm_node_t *right = parse_expression(parser, pm_binding_powers[
operator.type].left,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
14154 return (
pm_node_t *) pm_range_node_create(parser, NULL, &
operator, right);
14157 parser_lex(parser);
14160 parser_lex(parser);
14161 return (
pm_node_t *) pm_float_node_imaginary_create(parser, &parser->
previous);
14163 parser_lex(parser);
14166 parser_lex(parser);
14167 return (
pm_node_t *) pm_float_node_rational_imaginary_create(parser, &parser->
previous);
14169 parser_lex(parser);
14172 if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
14173 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14179 parser_lex(parser);
14182 if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
14183 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14189 parser_lex(parser);
14192 if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
14193 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14200 parser_lex(parser);
14202 pm_node_t *node = parse_variable_call(parser);
14212 if (parse_arguments_list(parser, &arguments,
true, accepts_command_call)) {
14222 if (arguments.
block != NULL) {
14243 parse_arguments_list(parser, &arguments,
true, accepts_command_call);
14245 pm_call_node_t *fcall = pm_call_node_fcall_create(parser, &identifier, &arguments);
14246 pm_node_destroy(parser, node);
14251 if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser,
PM_TOKEN_COMMA)) {
14252 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14261 assert(lex_mode->
mode == PM_LEX_HEREDOC);
14265 parser_lex(parser);
14274 lex_mode_pop(parser);
14278 if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
14285 }
else if ((part = parse_string_part(parser)) == NULL) {
14295 pm_node_flag_set(part, parse_unescaped_encoding(parser));
14298 cast->
opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
14302 if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
14308 if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (
size_t) -1) && (common_whitespace != 0)) {
14309 parse_heredoc_dedent_string(&cast->
unescaped, common_whitespace);
14313 lex_mode_pop(parser);
14320 pm_node_list_append(&parts, part);
14323 if ((part = parse_string_part(parser)) != NULL) {
14324 pm_node_list_append(&parts, part);
14332 if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
14334 cast->
parts = parts;
14336 lex_mode_pop(parser);
14339 pm_interpolated_xstring_node_closing_set(cast, &parser->
previous);
14345 lex_mode_pop(parser);
14348 pm_interpolated_string_node_closing_set(cast, &parser->
previous);
14355 if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (
size_t) -1) && (common_whitespace != 0)) {
14357 if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
14363 parse_heredoc_dedent(parser, nodes, common_whitespace);
14368 return parse_strings(parser, node);
14374 parser_lex(parser);
14377 if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
14378 node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
14385 parser_lex(parser);
14390 parser_lex(parser);
14391 return (
pm_node_t *) pm_integer_node_imaginary_create(parser, base, &parser->
previous);
14395 parser_lex(parser);
14396 return (
pm_node_t *) pm_integer_node_rational_create(parser, base, &parser->
previous);
14400 parser_lex(parser);
14401 return (
pm_node_t *) pm_integer_node_rational_imaginary_create(parser, base, &parser->
previous);
14404 parser_lex(parser);
14405 return (
pm_node_t *) pm_source_encoding_node_create(parser, &parser->
previous);
14407 parser_lex(parser);
14410 parser_lex(parser);
14413 if (binding_power != PM_BINDING_POWER_STATEMENT) {
14414 pm_parser_err_current(parser, PM_ERR_STATEMENT_ALIAS);
14417 parser_lex(parser);
14420 pm_node_t *new_name = parse_alias_argument(parser,
true);
14421 pm_node_t *old_name = parse_alias_argument(parser,
false);
14429 pm_parser_err_node(parser, old_name, PM_ERR_ALIAS_ARGUMENT);
14432 pm_parser_err_node(parser, old_name, PM_ERR_ALIAS_ARGUMENT);
14435 return (
pm_node_t *) pm_alias_global_variable_node_create(parser, &keyword, new_name, old_name);
14440 pm_parser_err_node(parser, old_name, PM_ERR_ALIAS_ARGUMENT);
14445 return (
pm_node_t *) pm_alias_method_node_create(parser, &keyword, new_name, old_name);
14449 parser_lex(parser);
14458 }
else if (!token_begins_expression_p(parser->
current.type)) {
14461 predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION,
true, PM_ERR_CASE_EXPRESSION_AFTER_CASE);
14466 pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
14467 return (
pm_node_t *) pm_case_node_create(parser, &case_keyword, predicate, &parser->
previous);
14472 pm_token_t end_keyword = not_provided(parser);
14476 pm_case_node_t *case_node = pm_case_node_create(parser, &case_keyword, predicate, &end_keyword);
14483 pm_when_node_t *when_node = pm_when_node_create(parser, &when_keyword);
14488 pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
14490 pm_splat_node_t *splat_node = pm_splat_node_create(parser, &
operator, expression);
14491 pm_when_node_conditions_append(when_node, (
pm_node_t *) splat_node);
14495 pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN);
14496 pm_when_node_conditions_append(when_node, condition);
14510 if (statements != NULL) {
14511 pm_when_node_statements_set(when_node, statements);
14515 pm_case_node_condition_append(case_node, (
pm_node_t *) when_node);
14521 pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
14526 pm_case_match_node_t *case_node = pm_case_match_node_create(parser, &case_keyword, predicate, &end_keyword);
14530 if (predicate == NULL) {
14531 pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MATCH_MISSING_PREDICATE);
14540 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
14542 parser_lex(parser);
14545 pm_node_t *pattern = parse_pattern(parser,
true, PM_ERR_PATTERN_EXPRESSION_AFTER_IN);
14552 pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
true, PM_ERR_CONDITIONAL_IF_PREDICATE);
14553 pattern = (
pm_node_t *) pm_if_node_modifier_create(parser, pattern, &keyword, predicate);
14556 pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED,
true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
14557 pattern = (
pm_node_t *) pm_unless_node_modifier_create(parser, pattern, &keyword, predicate);
14568 then_keyword = not_provided(parser);
14586 pm_node_t *condition = (
pm_node_t *) pm_in_node_create(parser, pattern, statements, &in_keyword, &then_keyword);
14587 pm_case_match_node_condition_append(case_node, condition);
14593 pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
14605 else_node = pm_else_node_create(parser, &else_keyword, parse_statements(parser,
PM_CONTEXT_ELSE), &parser->
current);
14607 else_node = pm_else_node_create(parser, &else_keyword, NULL, &parser->
current);
14611 pm_case_node_consequent_set((
pm_case_node_t *) node, else_node);
14627 parser_lex(parser);
14634 pm_accepts_block_stack_push(parser,
true);
14636 pm_accepts_block_stack_pop(parser);
14640 pm_begin_node_t *begin_node = pm_begin_node_create(parser, &begin_keyword, begin_statements);
14641 parse_rescues(parser, begin_node,
false);
14645 pm_begin_node_end_keyword_set(begin_node, &parser->
previous);
14654 if (binding_power != PM_BINDING_POWER_STATEMENT) {
14655 pm_parser_err_current(parser, PM_ERR_STATEMENT_PREEXE_BEGIN);
14658 parser_lex(parser);
14668 pm_parser_err_token(parser, &keyword, PM_ERR_BEGIN_UPCASE_TOPLEVEL);
14670 return (
pm_node_t *) pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->
previous);
14675 parser_lex(parser);
14681 token_begins_expression_p(parser->
current.type) ||
14684 pm_binding_power_t binding_power = pm_binding_powers[parser->
current.type].left;
14686 if (binding_power == PM_BINDING_POWER_UNSET || binding_power >= PM_BINDING_POWER_RANGE) {
14687 parse_arguments(parser, &arguments,
false,
PM_TOKEN_EOF);
14691 switch (keyword.
type) {
14701 pm_parser_err_current(parser, PM_ERR_RETURN_INVALID);
14706 assert(
false &&
"unreachable");
14711 parser_lex(parser);
14715 parse_arguments_list(parser, &arguments,
true, accepts_command_call);
14722 return (
pm_node_t *) pm_forwarding_super_node_create(parser, &keyword, &arguments);
14725 return (
pm_node_t *) pm_super_node_create(parser, &keyword, &arguments);
14728 parser_lex(parser);
14732 parse_arguments_list(parser, &arguments,
false, accepts_command_call);
14737 parser_lex(parser);
14739 pm_do_loop_stack_push(parser,
false);
14743 pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_NOT,
true, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS);
14747 pm_parser_scope_push(parser,
true);
14752 pm_accepts_block_stack_push(parser,
true);
14754 pm_accepts_block_stack_pop(parser);
14765 pm_parser_scope_pop(parser);
14767 pm_do_loop_stack_pop(parser);
14768 return (
pm_node_t *) pm_singleton_class_node_create(parser, &locals, &class_keyword, &
operator, expression, statements, &parser->
previous);
14771 pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX,
false, PM_ERR_CLASS_NAME);
14774 pm_parser_err_token(parser, &name, PM_ERR_CLASS_NAME);
14781 inheritance_operator = parser->
current;
14782 lex_state_set(parser, PM_LEX_STATE_BEG);
14785 parser_lex(parser);
14787 superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION,
true, PM_ERR_CLASS_SUPERCLASS);
14789 inheritance_operator = not_provided(parser);
14795 pm_parser_scope_push(parser,
true);
14804 pm_accepts_block_stack_push(parser,
true);
14806 pm_accepts_block_stack_pop(parser);
14816 if (context_def_p(parser)) {
14817 pm_parser_err_token(parser, &class_keyword, PM_ERR_CLASS_IN_METHOD);
14821 pm_parser_scope_pop(parser);
14823 pm_do_loop_stack_pop(parser);
14826 pm_parser_err_node(parser, constant_path, PM_ERR_CLASS_NAME);
14829 return (
pm_node_t *) pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, &inheritance_operator, superclass, statements, &parser->
previous);
14841 parser_lex(parser);
14844 switch (parser->
current.type) {
14845 case PM_CASE_OPERATOR:
14846 pm_parser_scope_push(parser,
true);
14848 lex_state_set(parser, PM_LEX_STATE_ENDFN);
14849 parser_lex(parser);
14853 parser_lex(parser);
14856 receiver = parse_variable_call(parser);
14858 pm_parser_scope_push(parser,
true);
14860 lex_state_set(parser, PM_LEX_STATE_FNAME);
14861 parser_lex(parser);
14864 name = parse_method_definition_name(parser);
14867 pm_parser_scope_push(parser,
true);
14885 pm_parser_scope_push(parser,
true);
14887 parser_lex(parser);
14891 lex_state_set(parser, PM_LEX_STATE_FNAME);
14892 parser_lex(parser);
14895 switch (identifier.
type) {
14897 receiver = (
pm_node_t *) pm_constant_read_node_create(parser, &identifier);
14900 receiver = (
pm_node_t *) pm_instance_variable_read_node_create(parser, &identifier);
14903 receiver = (
pm_node_t *) pm_class_variable_read_node_create(parser, &identifier);
14906 receiver = (
pm_node_t *) pm_global_variable_read_node_create(parser, &identifier);
14909 receiver = (
pm_node_t *) pm_nil_node_create(parser, &identifier);
14912 receiver = (
pm_node_t *) pm_self_node_create(parser, &identifier);
14915 receiver = (
pm_node_t *) pm_true_node_create(parser, &identifier);
14918 receiver = (
pm_node_t *)pm_false_node_create(parser, &identifier);
14921 receiver = (
pm_node_t *) pm_source_file_node_create(parser, &identifier);
14924 receiver = (
pm_node_t *) pm_source_line_node_create(parser, &identifier);
14927 receiver = (
pm_node_t *) pm_source_encoding_node_create(parser, &identifier);
14933 name = parse_method_definition_name(parser);
14943 context_pop(parser);
14944 parser_lex(parser);
14947 pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT,
true, PM_ERR_DEF_RECEIVER);
14952 lex_state_set(parser, PM_LEX_STATE_FNAME);
14956 receiver = (
pm_node_t *) pm_parentheses_node_create(parser, &lparen, expression, &rparen);
14958 pm_parser_scope_push(parser,
true);
14963 name = parse_method_definition_name(parser);
14967 pm_parser_scope_push(parser,
true);
14969 name = parse_method_definition_name(parser);
14976 pm_parser_err_previous(parser, PM_ERR_DEF_NAME);
14983 switch (parser->
current.type) {
14985 parser_lex(parser);
14991 params = parse_parameters(parser, PM_BINDING_POWER_DEFINED,
true,
false,
true);
14994 lex_state_set(parser, PM_LEX_STATE_BEG);
15001 case PM_CASE_PARAMETER: {
15005 lex_state_set(parser, parser->
lex_state | PM_LEX_STATE_LABEL);
15008 lparen = not_provided(parser);
15009 rparen = not_provided(parser);
15010 params = parse_parameters(parser, PM_BINDING_POWER_DEFINED,
false,
false,
true);
15014 lparen = not_provided(parser);
15015 rparen = not_provided(parser);
15023 context_pop(parser);
15029 if (token_is_setter_name(&name)) {
15030 pm_parser_err_token(parser, &name, PM_ERR_DEF_ENDLESS_SETTER);
15035 pm_do_loop_stack_push(parser,
false);
15036 statements = (
pm_node_t *) pm_statements_node_create(parser);
15038 pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, binding_power < PM_BINDING_POWER_COMPOSITION, PM_ERR_DEF_ENDLESS);
15042 pm_node_t *value = parse_expression(parser, binding_power,
false, PM_ERR_RESCUE_MODIFIER_VALUE);
15048 pm_do_loop_stack_pop(parser);
15049 context_pop(parser);
15050 end_keyword = not_provided(parser);
15052 equal = not_provided(parser);
15055 lex_state_set(parser, PM_LEX_STATE_BEG);
15062 pm_accepts_block_stack_push(parser,
true);
15063 pm_do_loop_stack_push(parser,
false);
15066 pm_accepts_block_stack_push(parser,
true);
15068 pm_accepts_block_stack_pop(parser);
15076 pm_accepts_block_stack_pop(parser);
15077 pm_do_loop_stack_pop(parser);
15084 pm_parser_scope_pop(parser);
15086 return (
pm_node_t *) pm_def_node_create(
15103 parser_lex(parser);
15112 expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION,
true, PM_ERR_DEFINED_EXPRESSION);
15115 rparen = not_provided(parser);
15122 lparen = not_provided(parser);
15123 rparen = not_provided(parser);
15124 expression = parse_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_DEFINED_EXPRESSION);
15127 return (
pm_node_t *) pm_defined_node_create(
15132 &PM_LOCATION_TOKEN_VALUE(&keyword)
15136 if (binding_power != PM_BINDING_POWER_STATEMENT) {
15137 pm_parser_err_current(parser, PM_ERR_STATEMENT_POSTEXE_END);
15140 parser_lex(parser);
15143 if (context_def_p(parser)) {
15144 pm_parser_warn_token(parser, &keyword, PM_WARN_END_IN_METHOD);
15152 return (
pm_node_t *) pm_post_execution_node_create(parser, &keyword, &opening, statements, &parser->
previous);
15155 parser_lex(parser);
15158 parser_lex(parser);
15169 if (token_begins_expression_p(parser->
current.type)) {
15170 name = parse_expression(parser, PM_BINDING_POWER_INDEX,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
15173 index = (
pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
15174 }
else if (token_begins_expression_p(parser->
current.type)) {
15175 index = parse_expression(parser, PM_BINDING_POWER_INDEX,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
15177 pm_parser_err_token(parser, &for_keyword, PM_ERR_FOR_INDEX);
15178 index = (
pm_node_t *) pm_missing_node_create(parser, for_keyword.
start, for_keyword.
end);
15183 index = parse_targets(parser, index, PM_BINDING_POWER_INDEX);
15185 index = parse_target(parser, index);
15188 context_pop(parser);
15189 pm_do_loop_stack_push(parser,
true);
15194 pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION,
true, PM_ERR_FOR_COLLECTION);
15195 pm_do_loop_stack_pop(parser);
15201 do_keyword = not_provided(parser);
15212 return (
pm_node_t *) pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->
previous);
15215 parser_lex(parser);
15218 if (binding_power != PM_BINDING_POWER_STATEMENT) {
15219 pm_parser_err_current(parser, PM_ERR_STATEMENT_UNDEF);
15222 parser_lex(parser);
15224 pm_node_t *name = parse_undef_argument(parser);
15227 pm_node_destroy(parser, name);
15229 pm_undef_node_append(undef, name);
15232 lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM);
15233 parser_lex(parser);
15234 name = parse_undef_argument(parser);
15237 pm_node_destroy(parser, name);
15241 pm_undef_node_append(undef, name);
15248 parser_lex(parser);
15262 receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION,
true, PM_ERR_NOT_EXPRESSION);
15263 pm_conditional_predicate(receiver);
15272 receiver = parse_expression(parser, PM_BINDING_POWER_NOT,
true, PM_ERR_NOT_EXPRESSION);
15273 pm_conditional_predicate(receiver);
15276 return (
pm_node_t *) pm_call_node_not_create(parser, receiver, &message, &arguments);
15279 parser_lex(parser);
15282 parser_lex(parser);
15285 pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX,
false, PM_ERR_MODULE_NAME);
15292 return (
pm_node_t *) pm_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing);
15301 constant_path = (
pm_node_t *) pm_constant_path_node_create(parser, constant_path, &double_colon, constant);
15309 pm_parser_err_token(parser, &name, PM_ERR_MODULE_NAME);
15314 pm_parser_scope_push(parser,
true);
15319 pm_accepts_block_stack_push(parser,
true);
15321 pm_accepts_block_stack_pop(parser);
15330 pm_parser_scope_pop(parser);
15335 if (context_def_p(parser)) {
15336 pm_parser_err_token(parser, &module_keyword, PM_ERR_MODULE_IN_METHOD);
15339 return (
pm_node_t *) pm_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->
previous);
15342 parser_lex(parser);
15345 parser_lex(parser);
15348 parser_lex(parser);
15351 parser_lex(parser);
15354 parser_lex(parser);
15357 pm_do_loop_stack_push(parser,
true);
15358 parser_lex(parser);
15361 pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION,
true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
15362 pm_do_loop_stack_pop(parser);
15368 pm_accepts_block_stack_push(parser,
true);
15370 pm_accepts_block_stack_pop(parser);
15375 return (
pm_node_t *) pm_until_node_create(parser, &keyword, &parser->
previous, predicate, statements, 0);
15378 pm_do_loop_stack_push(parser,
true);
15379 parser_lex(parser);
15382 pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION,
true, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
15383 pm_do_loop_stack_pop(parser);
15389 pm_accepts_block_stack_push(parser,
true);
15391 pm_accepts_block_stack_pop(parser);
15396 return (
pm_node_t *) pm_while_node_create(parser, &keyword, &parser->
previous, predicate, statements, 0);
15399 parser_lex(parser);
15410 pm_array_node_elements_append(array, (
pm_node_t *) pm_symbol_node_create_current_string(parser, &opening, &parser->
current, &closing));
15418 pm_parser_err_token(parser, &opening, PM_ERR_LIST_I_LOWER_TERM);
15423 pm_array_node_close_set(array, &closing);
15428 parser_lex(parser);
15437 switch (parser->
current.type) {
15439 if (current == NULL) {
15445 pm_array_node_elements_append(array, current);
15449 parser_lex(parser);
15456 if (current == NULL) {
15460 current = (
pm_node_t *) pm_symbol_node_create_current_string(parser, &opening, &parser->
current, &closing);
15461 parser_lex(parser);
15467 parser_lex(parser);
15475 parser_lex(parser);
15478 pm_interpolated_symbol_node_append(interpolated, current);
15479 pm_interpolated_symbol_node_append(interpolated,
string);
15482 assert(
false &&
"unreachable");
15488 bool start_location_set =
false;
15489 if (current == NULL) {
15495 current = (
pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
15505 pm_interpolated_symbol_node_append(interpolated, current);
15507 start_location_set =
true;
15514 pm_node_t *part = parse_string_part(parser);
15516 if (!start_location_set) {
15522 bool start_location_set =
false;
15523 if (current == NULL) {
15529 current = (
pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
15540 pm_interpolated_symbol_node_append(interpolated, current);
15542 start_location_set =
true;
15548 assert(
false &&
"unreachable");
15551 pm_node_t *part = parse_string_part(parser);
15553 if (!start_location_set) {
15560 parser_lex(parser);
15567 pm_array_node_elements_append(array, current);
15572 pm_parser_err_token(parser, &opening, PM_ERR_LIST_I_UPPER_TERM);
15577 pm_array_node_close_set(array, &closing);
15582 parser_lex(parser);
15598 pm_array_node_elements_append(array,
string);
15606 pm_parser_err_token(parser, &opening, PM_ERR_LIST_W_LOWER_TERM);
15612 pm_array_node_close_set(array, &closing);
15616 parser_lex(parser);
15625 switch (parser->
current.type) {
15631 if (current == NULL) {
15638 pm_array_node_elements_append(array, current);
15642 parser_lex(parser);
15650 pm_node_flag_set(
string, parse_unescaped_encoding(parser));
15651 parser_lex(parser);
15653 if (current == NULL) {
15670 pm_interpolated_string_node_append(interpolated, current);
15671 pm_interpolated_string_node_append(interpolated,
string);
15674 assert(
false &&
"unreachable");
15680 if (current == NULL) {
15687 current = (
pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
15696 pm_interpolated_string_node_append(interpolated, current);
15704 pm_node_t *part = parse_string_part(parser);
15709 if (current == NULL) {
15716 current = (
pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
15725 pm_interpolated_string_node_append(interpolated, current);
15732 assert(
false &&
"unreachable");
15735 pm_node_t *part = parse_string_part(parser);
15741 parser_lex(parser);
15748 pm_array_node_elements_append(array, current);
15753 pm_parser_err_token(parser, &opening, PM_ERR_LIST_W_UPPER_TERM);
15759 pm_array_node_close_set(array, &closing);
15764 parser_lex(parser);
15776 parser_lex(parser);
15777 return (
pm_node_t *) pm_regular_expression_node_create(parser, &opening, &content, &parser->
previous);
15789 parser_lex(parser);
15795 return (
pm_node_t *) pm_regular_expression_node_create_unescaped(parser, &opening, &content, &parser->
previous, &unescaped);
15800 node = pm_interpolated_regular_expression_node_create(parser, &opening);
15805 pm_interpolated_regular_expression_node_append(node, part);
15810 node = pm_interpolated_regular_expression_node_create(parser, &opening);
15817 if ((part = parse_string_part(parser)) != NULL) {
15818 pm_interpolated_regular_expression_node_append(node, part);
15824 pm_parser_err_token(parser, &opening, PM_ERR_REGEXP_TERM);
15829 pm_interpolated_regular_expression_node_closing_set(node, &closing);
15835 parser_lex(parser);
15852 parser_lex(parser);
15853 return (
pm_node_t *) pm_xstring_node_create(parser, &opening, &content, &parser->
previous);
15865 parser_lex(parser);
15868 pm_node_t *node = (
pm_node_t *) pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->
current, &unescaped);
15869 pm_node_flag_set(node, parse_unescaped_encoding(parser));
15870 parser_lex(parser);
15876 node = pm_interpolated_xstring_node_create(parser, &opening, &opening);
15882 pm_node_flag_set(part, parse_unescaped_encoding(parser));
15884 pm_interpolated_xstring_node_append(node, part);
15889 node = pm_interpolated_xstring_node_create(parser, &opening, &opening);
15894 if ((part = parse_string_part(parser)) != NULL) {
15895 pm_interpolated_xstring_node_append(node, part);
15901 pm_parser_err_token(parser, &opening, PM_ERR_XSTRING_TERM);
15906 pm_interpolated_xstring_node_closing_set(node, &closing);
15911 parser_lex(parser);
15916 if (binding_power != PM_BINDING_POWER_STATEMENT) {
15923 if (token_begins_expression_p(parser->
current.type)) {
15924 name = parse_expression(parser, PM_BINDING_POWER_INDEX,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
15930 return parse_targets_validate(parser, splat, PM_BINDING_POWER_INDEX);
15932 return parse_target_validate(parser, splat);
15936 parser_lex(parser);
15939 pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->
previous.
type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER_BANG);
15940 pm_call_node_t *node = pm_call_node_unary_create(parser, &
operator, receiver,
"!");
15942 pm_conditional_predicate(receiver);
15946 parser_lex(parser);
15949 pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->
previous.
type].right,
false, PM_ERR_UNARY_RECEIVER_TILDE);
15950 pm_call_node_t *node = pm_call_node_unary_create(parser, &
operator, receiver,
"~");
15955 parser_lex(parser);
15958 pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->
previous.
type].right,
false, PM_ERR_UNARY_RECEIVER_MINUS);
15959 pm_call_node_t *node = pm_call_node_unary_create(parser, &
operator, receiver,
"-@");
15964 parser_lex(parser);
15967 pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->
previous.
type].right,
false, PM_ERR_UNARY_RECEIVER_MINUS);
15971 pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.
type].right,
false, PM_ERR_EXPECT_ARGUMENT);
15972 node = (
pm_node_t *) pm_call_node_binary_create(parser, node, &exponent_operator, exponent);
15973 node = (
pm_node_t *) pm_call_node_unary_create(parser, &
operator, node,
"-@");
15980 parse_negative_numeric(node);
15983 node = (
pm_node_t *) pm_call_node_unary_create(parser, &
operator, node,
"-@");
15994 pm_accepts_block_stack_push(parser,
true);
15995 parser_lex(parser);
15998 pm_parser_scope_push(parser,
false);
16001 switch (parser->
current.type) {
16005 parser_lex(parser);
16008 block_parameters = pm_block_parameters_node_create(parser, NULL, &opening);
16010 block_parameters = parse_block_parameters(parser,
false, &opening,
true);
16016 pm_block_parameters_node_closing_set(block_parameters, &parser->
previous);
16019 case PM_CASE_PARAMETER: {
16021 pm_accepts_block_stack_push(parser,
false);
16023 block_parameters = parse_block_parameters(parser,
false, &opening,
true);
16024 pm_accepts_block_stack_pop(parser);
16028 block_parameters = NULL;
16033 uint32_t locals_body_index = 0;
16035 if (block_parameters) {
16055 pm_accepts_block_stack_push(parser,
true);
16057 pm_accepts_block_stack_pop(parser);
16071 if (parameters == NULL && (maximum > 0)) {
16073 locals_body_index = maximum;
16077 pm_parser_scope_pop(parser);
16078 pm_accepts_block_stack_pop(parser);
16079 return (
pm_node_t *) pm_lambda_node_create(parser, &locals, locals_body_index, &
operator, &opening, &parser->
previous, parameters, body);
16082 parser_lex(parser);
16085 pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->
previous.
type].right,
false, PM_ERR_UNARY_RECEIVER_PLUS);
16086 pm_call_node_t *node = pm_call_node_unary_create(parser, &
operator, receiver,
"+@");
16091 return parse_strings(parser, NULL);
16094 parser_lex(parser);
16096 return parse_symbol(parser, &lex_mode, PM_LEX_STATE_END);
16099 if (context_recoverable(parser, &parser->
current)) {
16108parse_assignment_value(
pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power,
bool accepts_command_call,
pm_diagnostic_id_t diag_id) {
16109 pm_node_t *value = parse_value_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id);
16114 parser_lex(parser);
16115 pm_node_t *right = parse_expression(parser, binding_power,
false, PM_ERR_RESCUE_MODIFIER_VALUE);
16117 return (
pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
16125parse_assignment_values(
pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power,
bool accepts_command_call,
pm_diagnostic_id_t diag_id) {
16126 pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id);
16128 bool is_single_value =
true;
16130 is_single_value =
false;
16134 pm_array_node_elements_append(array, value);
16138 pm_node_t *element = parse_starred_expression(parser, binding_power,
false, PM_ERR_ARRAY_ELEMENT);
16139 pm_array_node_elements_append(array, element);
16147 parser_lex(parser);
16148 pm_node_t *right = parse_expression(parser, binding_power,
false, PM_ERR_RESCUE_MODIFIER_VALUE);
16150 return (
pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
16166 pm_parser_err_token(parser,
operator, PM_ERR_OPERATOR_WRITE_ARGUMENTS);
16171 if (call_node->
block != NULL) {
16172 pm_parser_err_token(parser,
operator, PM_ERR_OPERATOR_WRITE_BLOCK);
16174 call_node->
block = NULL;
16179name_is_identifier(
pm_parser_t *parser,
const uint8_t *source,
size_t length) {
16184 size_t width = char_is_identifier_start(parser, source);
16189 uint8_t *cursor = ((uint8_t *)source) + width;
16190 while (cursor < source + length && (width = char_is_identifier(parser, cursor))) {
16194 return cursor == source + length;
16206 if (pm_regexp_named_capture_group_names(pm_string_source(content), pm_string_length(content), &named_captures, parser->
encoding_changed, parser->
encoding) && (named_captures.length > 0)) {
16212 for (
size_t index = 0; index < named_captures.length; index++) {
16213 pm_string_t *
string = &named_captures.strings[index];
16215 const uint8_t *source = pm_string_source(
string);
16216 size_t length = pm_string_length(
string);
16223 if (!name_is_identifier(parser, source, length))
continue;
16225 if (content->
type == PM_STRING_SHARED) {
16228 location = (
pm_location_t) { .start = source, .end = source + length };
16229 name = pm_parser_constant_id_location(parser, location.
start, location.
end);
16230 pm_refute_numbered_parameter(parser, source, source + length);
16236 void *memory = malloc(length);
16237 if (memory == NULL) abort();
16239 memcpy(memory, source, length);
16242 name = pm_parser_constant_id_owned(parser, (
const uint8_t *) memory, length);
16244 if (pm_token_is_numbered_parameter(source, source + length)) {
16246 PM_PARSER_ERR_LOCATION_FORMAT(parser, location, PM_ERR_PARAMETER_NUMBERED_RESERVED, location->
start);
16253 if (pm_constant_id_list_includes(&names, name))
continue;
16254 pm_constant_id_list_append(&names, name);
16258 if (match == NULL) match = pm_match_write_node_create(parser, call);
16262 if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) {
16263 pm_parser_local_add(parser, name);
16268 pm_node_t *target = (
pm_node_t *) pm_local_variable_target_node_create_values(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth);
16269 pm_node_list_append(&match->targets, target);
16273 if (match != NULL) {
16279 pm_constant_id_list_free(&names);
16284 pm_string_list_free(&named_captures);
16289parse_expression_infix(
pm_parser_t *parser,
pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power,
bool accepts_command_call) {
16292 switch (token.type) {
16301 if (pm_call_node_variable_call_p(call_node)) {
16306 case PM_CASE_WRITABLE: {
16307 parser_lex(parser);
16308 pm_node_t *value = parse_assignment_values(parser, previous_binding_power,
PM_NODE_TYPE_P(node,
PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
16309 return parse_write(parser, node, &token, value);
16313 pm_multi_target_node_targets_append(parser, multi_target, node);
16315 parser_lex(parser);
16316 pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
16317 return parse_write(parser, (
pm_node_t *) multi_target, &token, value);
16320 parser_lex(parser);
16325 pm_parser_err_token(parser, &token, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
16333 pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_READONLY);
16336 parser_lex(parser);
16338 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16339 pm_node_t *result = (
pm_node_t *) pm_global_variable_and_write_node_create(parser, node, &token, value);
16341 pm_node_destroy(parser, node);
16345 parser_lex(parser);
16347 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16350 pm_node_destroy(parser, node);
16354 parser_lex(parser);
16356 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16360 parser_lex(parser);
16362 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16365 pm_node_destroy(parser, node);
16369 parser_lex(parser);
16371 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16374 pm_node_destroy(parser, node);
16379 parser_lex(parser);
16381 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16384 pm_node_destroy(parser, node);
16388 parser_lex(parser);
16394 if (pm_call_node_variable_call_p(cast)) {
16396 pm_refute_numbered_parameter(parser, message_loc->
start, message_loc->
end);
16399 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16400 pm_node_t *result = (
pm_node_t *) pm_local_variable_and_write_node_create(parser, (
pm_node_t *) cast, &token, value, constant_id, 0);
16402 pm_node_destroy(parser, (
pm_node_t *) cast);
16409 if (pm_call_node_index_p(cast)) {
16410 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16411 return (
pm_node_t *) pm_index_and_write_node_create(parser, cast, &token, value);
16415 if (pm_call_node_writable_p(cast)) {
16416 parse_write_name(parser, &cast->name);
16418 pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_UNEXPECTED);
16421 parse_call_operator_write(parser, cast, &token);
16422 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16423 return (
pm_node_t *) pm_call_and_write_node_create(parser, cast, &token, value);
16426 parser_lex(parser);
16427 pm_parser_err_token(parser, &token, PM_ERR_AMPAMPEQ_MULTI_ASSIGN);
16431 parser_lex(parser);
16436 pm_parser_err_token(parser, &token, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
16444 pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_READONLY);
16447 parser_lex(parser);
16449 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16450 pm_node_t *result = (
pm_node_t *) pm_global_variable_or_write_node_create(parser, node, &token, value);
16452 pm_node_destroy(parser, node);
16456 parser_lex(parser);
16458 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16461 pm_node_destroy(parser, node);
16465 parser_lex(parser);
16467 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16471 parser_lex(parser);
16473 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16476 pm_node_destroy(parser, node);
16480 parser_lex(parser);
16482 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16485 pm_node_destroy(parser, node);
16490 parser_lex(parser);
16492 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16495 pm_node_destroy(parser, node);
16499 parser_lex(parser);
16505 if (pm_call_node_variable_call_p(cast)) {
16507 pm_refute_numbered_parameter(parser, message_loc->
start, message_loc->
end);
16510 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16511 pm_node_t *result = (
pm_node_t *) pm_local_variable_or_write_node_create(parser, (
pm_node_t *) cast, &token, value, constant_id, 0);
16513 pm_node_destroy(parser, (
pm_node_t *) cast);
16520 if (pm_call_node_index_p(cast)) {
16521 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16522 return (
pm_node_t *) pm_index_or_write_node_create(parser, cast, &token, value);
16526 if (pm_call_node_writable_p(cast)) {
16527 parse_write_name(parser, &cast->name);
16529 pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_UNEXPECTED);
16532 parse_call_operator_write(parser, cast, &token);
16533 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16534 return (
pm_node_t *) pm_call_or_write_node_create(parser, cast, &token, value);
16537 parser_lex(parser);
16538 pm_parser_err_token(parser, &token, PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN);
16542 parser_lex(parser);
16547 pm_parser_err_token(parser, &token, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
16565 pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_READONLY);
16568 parser_lex(parser);
16570 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16571 pm_node_t *result = (
pm_node_t *) pm_global_variable_operator_write_node_create(parser, node, &token, value);
16573 pm_node_destroy(parser, node);
16577 parser_lex(parser);
16579 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16582 pm_node_destroy(parser, node);
16586 parser_lex(parser);
16588 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16592 parser_lex(parser);
16594 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16597 pm_node_destroy(parser, node);
16601 parser_lex(parser);
16603 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16606 pm_node_destroy(parser, node);
16611 parser_lex(parser);
16613 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16614 pm_node_t *result = (
pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->
name, cast->
depth);
16616 pm_node_destroy(parser, node);
16620 parser_lex(parser);
16626 if (pm_call_node_variable_call_p(cast)) {
16628 pm_refute_numbered_parameter(parser, message_loc->
start, message_loc->
end);
16631 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16632 pm_node_t *result = (
pm_node_t *) pm_local_variable_operator_write_node_create(parser, (
pm_node_t *) cast, &token, value, constant_id, 0);
16634 pm_node_destroy(parser, (
pm_node_t *) cast);
16641 if (pm_call_node_index_p(cast)) {
16642 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16643 return (
pm_node_t *) pm_index_operator_write_node_create(parser, cast, &token, value);
16647 if (pm_call_node_writable_p(cast)) {
16648 parse_write_name(parser, &cast->name);
16650 pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_UNEXPECTED);
16653 parse_call_operator_write(parser, cast, &token);
16654 pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16655 return (
pm_node_t *) pm_call_operator_write_node_create(parser, cast, &token, value);
16658 parser_lex(parser);
16659 pm_parser_err_token(parser, &token, PM_ERR_OPERATOR_MULTI_ASSIGN);
16663 parser_lex(parser);
16668 pm_parser_err_previous(parser, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16674 parser_lex(parser);
16677 return (
pm_node_t *) pm_and_node_create(parser, node, &token, right);
16681 parser_lex(parser);
16684 return (
pm_node_t *) pm_or_node_create(parser, node, &token, right);
16694 parser_lex(parser);
16695 pm_node_t *argument = parse_expression(parser, binding_power,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16698 pm_call_node_t *call = pm_call_node_binary_create(parser, node, &token, argument);
16711 bool interpolated =
false;
16712 size_t total_length = 0;
16714 for (
size_t index = 0; index < parts->
size; index++) {
16718 total_length += pm_string_length(&((
pm_string_node_t *) part)->unescaped);
16720 interpolated =
true;
16725 if (!interpolated && total_length > 0) {
16726 void *memory = malloc(total_length);
16727 if (!memory) abort();
16729 uint8_t *cursor = memory;
16730 for (
size_t index = 0; index < parts->
size; index++) {
16732 size_t length = pm_string_length(unescaped);
16734 memcpy(cursor, pm_string_source(unescaped), length);
16739 pm_string_owned_init(&owned, (uint8_t *) memory, total_length);
16741 result = parse_regular_expression_named_captures(parser, &owned, call);
16742 pm_string_free(&owned);
16748 result = parse_regular_expression_named_captures(parser, content, call);
16778 parser_lex(parser);
16780 pm_node_t *argument = parse_expression(parser, binding_power,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16781 return (
pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument);
16785 parser_lex(parser);
16791 parse_arguments_list(parser, &arguments,
true,
false);
16792 return (
pm_node_t *) pm_call_node_shorthand_create(parser, node, &
operator, &arguments);
16797 switch (parser->
current.type) {
16798 case PM_CASE_OPERATOR:
16799 case PM_CASE_KEYWORD:
16803 parser_lex(parser);
16808 pm_parser_err_current(parser, PM_ERR_DEF_NAME);
16813 parse_arguments_list(parser, &arguments,
true, accepts_command_call);
16814 pm_call_node_t *call = pm_call_node_call_create(parser, node, &
operator, &message, &arguments);
16817 (previous_binding_power == PM_BINDING_POWER_STATEMENT) &&
16822 return parse_targets_validate(parser, (
pm_node_t *) call, PM_BINDING_POWER_INDEX);
16829 parser_lex(parser);
16832 if (token_begins_expression_p(parser->
current.type)) {
16833 right = parse_expression(parser, binding_power,
false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
16836 return (
pm_node_t *) pm_range_node_create(parser, node, &token, right);
16840 parser_lex(parser);
16842 pm_node_t *predicate = parse_value_expression(parser, binding_power,
true, PM_ERR_CONDITIONAL_IF_PREDICATE);
16843 return (
pm_node_t *) pm_if_node_modifier_create(parser, node, &keyword, predicate);
16847 parser_lex(parser);
16849 pm_node_t *predicate = parse_value_expression(parser, binding_power,
true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
16850 return (
pm_node_t *) pm_unless_node_modifier_create(parser, node, &keyword, predicate);
16853 parser_lex(parser);
16855 pm_statements_node_body_append(statements, node);
16857 pm_node_t *predicate = parse_value_expression(parser, binding_power,
true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
16861 parser_lex(parser);
16863 pm_statements_node_body_append(statements, node);
16865 pm_node_t *predicate = parse_value_expression(parser, binding_power,
true, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
16870 parser_lex(parser);
16871 pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_TERNARY_EXPRESSION_TRUE);
16883 return (
pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
16890 pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED,
false, PM_ERR_TERNARY_EXPRESSION_FALSE);
16892 return (
pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
16895 parser_lex(parser);
16898 switch (parser->
current.type) {
16900 parser_lex(parser);
16916 parse_arguments_list(parser, &arguments,
true, accepts_command_call);
16917 path = (
pm_node_t *) pm_call_node_call_create(parser, node, &delimiter, &message, &arguments);
16921 path = (
pm_node_t *)pm_constant_path_node_create(parser, node, &delimiter, child);
16925 if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
16926 return parse_targets_validate(parser, path, PM_BINDING_POWER_INDEX);
16931 case PM_CASE_OPERATOR:
16932 case PM_CASE_KEYWORD:
16935 parser_lex(parser);
16941 parse_arguments_list(parser, &arguments,
true, accepts_command_call);
16942 pm_call_node_t *call = pm_call_node_call_create(parser, node, &delimiter, &message, &arguments);
16945 if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
16946 return parse_targets_validate(parser, (
pm_node_t *) call, PM_BINDING_POWER_INDEX);
16955 parse_arguments_list(parser, &arguments,
true,
false);
16957 return (
pm_node_t *) pm_call_node_shorthand_create(parser, node, &delimiter, &arguments);
16960 pm_parser_err_token(parser, &delimiter, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
16962 return (
pm_node_t *)pm_constant_path_node_create(parser, node, &delimiter, child);
16967 parser_lex(parser);
16969 pm_node_t *value = parse_expression(parser, binding_power,
true, PM_ERR_RESCUE_MODIFIER_VALUE);
16971 return (
pm_node_t *) pm_rescue_modifier_node_create(parser, node, &token, value);
16974 parser_lex(parser);
16980 pm_accepts_block_stack_push(parser,
true);
16982 pm_accepts_block_stack_pop(parser);
16990 if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser,
PM_TOKEN_COMMA)) {
16991 pm_call_node_t *aref = pm_call_node_aref_create(parser, node, &arguments);
16992 return parse_targets_validate(parser, (
pm_node_t *) aref, PM_BINDING_POWER_INDEX);
17000 block = parse_block(parser);
17001 pm_arguments_validate_block(parser, &arguments, block);
17003 block = parse_block(parser);
17006 if (block != NULL) {
17007 if (arguments.
block != NULL) {
17008 pm_parser_err_node(parser, (
pm_node_t *) block, PM_ERR_ARGUMENT_AFTER_BLOCK);
17010 arguments.
arguments = pm_arguments_node_create(parser);
17012 pm_arguments_node_arguments_append(arguments.
arguments, arguments.
block);
17018 return (
pm_node_t *) pm_call_node_aref_create(parser, node, &arguments);
17026 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
17028 parser_lex(parser);
17030 pm_node_t *pattern = parse_pattern(parser,
true, PM_ERR_PATTERN_EXPRESSION_AFTER_IN);
17033 return (
pm_node_t *) pm_match_predicate_node_create(parser, node, pattern, &
operator);
17041 lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
17043 parser_lex(parser);
17045 pm_node_t *pattern = parse_pattern(parser,
true, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET);
17048 return (
pm_node_t *) pm_match_required_node_create(parser, node, pattern, &
operator);
17051 assert(
false &&
"unreachable");
17067 pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call);
17074 pm_parser_err(parser, recovery.
end, recovery.
end, diag_id);
17083 if (pm_binding_powers[parser->
current.type].left > PM_BINDING_POWER_MODIFIER_RESCUE) {
17092 if ((((
pm_range_node_t *) node)->left == NULL) && pm_binding_powers[parser->
current.type].left >= PM_BINDING_POWER_RANGE) {
17104 current_binding_powers = pm_binding_powers[parser->
current.type],
17105 binding_power <= current_binding_powers.
left &&
17106 current_binding_powers.
binary
17108 node = parse_expression_infix(parser, node, binding_power, current_binding_powers.
right, accepts_command_call);
17109 if (current_binding_powers.
nonassoc) {
17111 pm_binding_power_t left = endless_range_p ? PM_BINDING_POWER_TERM : current_binding_powers.
left;
17113 left <= pm_binding_powers[parser->
current.type].left ||
17122 if (accepts_command_call) {
17131 switch (node->
type) {
17146 cast->
block == NULL &&
17159 accepts_command_call =
false;
17167 accepts_command_call =
false;
17179 parser_lex(parser);
17183 statements = pm_statements_node_create(parser);
17186 pm_parser_scope_pop(parser);
17191 if (pm_statements_node_body_length(statements) == 0) {
17192 pm_statements_node_location_set(statements, parser->
start, parser->
start);
17195 return (
pm_node_t *) pm_program_node_create(parser, &locals, statements);
17207 assert(source != NULL);
17210 .lex_state = PM_LEX_STATE_BEG,
17211 .enclosure_nesting = 0,
17212 .lambda_enclosure_nesting = -1,
17213 .brace_nesting = 0,
17214 .do_loop_stack = 0,
17215 .accepts_block_stack = 0,
17218 .stack = {{ .mode = PM_LEX_DEFAULT }},
17222 .end = source + size,
17223 .previous = { .type =
PM_TOKEN_EOF, .start = source, .end = source },
17224 .current = { .type =
PM_TOKEN_EOF, .start = source, .end = source },
17225 .next_start = NULL,
17226 .heredoc_end = NULL,
17227 .comment_list = { 0 },
17228 .magic_comment_list = { 0 },
17229 .warning_list = { 0 },
17230 .error_list = { 0 },
17231 .current_scope = NULL,
17232 .current_context = NULL,
17234 .encoding_changed_callback = NULL,
17235 .encoding_comment_start = source,
17236 .lex_callback = NULL,
17237 .filepath_string = { 0 },
17238 .constant_pool = { 0 },
17239 .newline_list = { 0 },
17243 .explicit_encoding = NULL,
17244 .command_start =
true,
17245 .recovering =
false,
17246 .encoding_changed =
false,
17247 .pattern_matching_newlines =
false,
17248 .in_keyword_arg =
false,
17249 .current_param_name = 0,
17250 .semantic_token_seen =
false,
17251 .frozen_string_literal =
false,
17252 .suppress_warnings =
false
17269 uint32_t constant_size = ((uint32_t) size) / 95;
17270 pm_constant_pool_init(&parser->
constant_pool, constant_size < 4 ? 4 : constant_size);
17275 size_t newline_size = size / 22;
17276 pm_newline_list_init(&parser->
newline_list, source, newline_size < 4 ? 4 : newline_size);
17279 if (options != NULL) {
17287 size_t encoding_length = pm_string_length(&options->
encoding);
17288 if (encoding_length > 0) {
17289 const uint8_t *encoding_source = pm_string_source(&options->
encoding);
17290 parser_lex_magic_comment_encoding_value(parser, encoding_source, encoding_source + encoding_length);
17304 for (
size_t scope_index = 0; scope_index < options->
scopes_count; scope_index++) {
17306 pm_parser_scope_push(parser, scope_index == 0);
17308 for (
size_t local_index = 0; local_index < scope->
locals_count; local_index++) {
17309 const pm_string_t *local = pm_options_scope_local_get(scope, local_index);
17311 const uint8_t *source = pm_string_source(local);
17312 size_t length = pm_string_length(local);
17314 uint8_t *allocated = malloc(length);
17315 if (allocated == NULL)
continue;
17317 memcpy((
void *) allocated, source, length);
17318 pm_parser_local_add_owned(parser, allocated, length);
17323 pm_accepts_block_stack_push(parser,
true);
17326 if (size >= 3 && source[0] == 0xef && source[1] == 0xbb && source[2] == 0xbf) {
17333 if (peek(parser) ==
'#' && peek_offset(parser, 1) ==
'!') {
17334 const uint8_t *encoding_comment_start = next_newline(source, (ptrdiff_t) size);
17335 if (encoding_comment_start) {
17357 for (node = list->
head; node != NULL; node = next) {
17369pm_magic_comment_list_free(
pm_list_t *list) {
17372 for (node = list->
head; node != NULL; node = next) {
17386 pm_diagnostic_list_free(&parser->
error_list);
17399 pm_parser_scope_pop(parser);
17403 lex_mode_pop(parser);
17412 return parse_program(parser);
17417 pm_buffer_append_string(buffer,
"PRISM", 5);
17429 pm_serialize_header(buffer);
17431 pm_buffer_append_byte(buffer,
'\0');
17439pm_serialize_parse(
pm_buffer_t *buffer,
const uint8_t *source,
size_t size,
const char *data) {
17441 pm_options_read(&options, data);
17444 pm_parser_init(&parser, source, size, &options);
17448 pm_serialize_header(buffer);
17450 pm_buffer_append_byte(buffer,
'\0');
17452 pm_node_destroy(&parser, node);
17453 pm_parser_free(&parser);
17454 pm_options_free(&options);
17461pm_serialize_parse_comments(
pm_buffer_t *buffer,
const uint8_t *source,
size_t size,
const char *data) {
17463 pm_options_read(&options, data);
17466 pm_parser_init(&parser, source, size, &options);
17469 pm_serialize_header(buffer);
17471 pm_buffer_append_varsint(buffer, parser.
start_line);
17474 pm_node_destroy(&parser, node);
17475 pm_parser_free(&parser);
17476 pm_options_free(&options);
17479#undef PM_CASE_KEYWORD
17480#undef PM_CASE_OPERATOR
17481#undef PM_CASE_WRITABLE
17482#undef PM_STRING_EMPTY
17483#undef PM_LOCATION_NODE_BASE_VALUE
17484#undef PM_LOCATION_NODE_VALUE
17485#undef PM_LOCATION_NULL_VALUE
17486#undef PM_LOCATION_TOKEN_VALUE
struct pm_block_parameter_node pm_block_parameter_node_t
BlockParameterNode.
struct pm_call_target_node pm_call_target_node_t
CallTargetNode.
struct pm_else_node pm_else_node_t
ElseNode.
struct pm_assoc_node pm_assoc_node_t
AssocNode.
struct pm_undef_node pm_undef_node_t
UndefNode.
struct pm_class_variable_and_write_node pm_class_variable_and_write_node_t
ClassVariableAndWriteNode.
struct pm_index_and_write_node pm_index_and_write_node_t
IndexAndWriteNode.
struct pm_index_target_node pm_index_target_node_t
IndexTargetNode.
struct pm_local_variable_target_node pm_local_variable_target_node_t
LocalVariableTargetNode.
struct pm_constant_path_or_write_node pm_constant_path_or_write_node_t
ConstantPathOrWriteNode.
struct pm_missing_node pm_missing_node_t
MissingNode.
struct pm_embedded_statements_node pm_embedded_statements_node_t
EmbeddedStatementsNode.
struct pm_block_node pm_block_node_t
BlockNode.
struct pm_hash_pattern_node pm_hash_pattern_node_t
HashPatternNode.
struct pm_optional_parameter_node pm_optional_parameter_node_t
OptionalParameterNode.
struct pm_x_string_node pm_x_string_node_t
XStringNode.
struct pm_forwarding_super_node pm_forwarding_super_node_t
ForwardingSuperNode.
struct pm_self_node pm_self_node_t
SelfNode.
struct pm_numbered_reference_read_node pm_numbered_reference_read_node_t
NumberedReferenceReadNode.
struct pm_embedded_variable_node pm_embedded_variable_node_t
EmbeddedVariableNode.
struct pm_class_variable_write_node pm_class_variable_write_node_t
ClassVariableWriteNode.
struct pm_interpolated_string_node pm_interpolated_string_node_t
InterpolatedStringNode.
struct pm_class_variable_or_write_node pm_class_variable_or_write_node_t
ClassVariableOrWriteNode.
struct pm_optional_keyword_parameter_node pm_optional_keyword_parameter_node_t
OptionalKeywordParameterNode.
struct pm_call_or_write_node pm_call_or_write_node_t
CallOrWriteNode.
struct pm_call_node pm_call_node_t
CallNode.
struct pm_class_variable_read_node pm_class_variable_read_node_t
ClassVariableReadNode.
struct pm_match_required_node pm_match_required_node_t
MatchRequiredNode.
struct pm_constant_and_write_node pm_constant_and_write_node_t
ConstantAndWriteNode.
struct pm_constant_path_operator_write_node pm_constant_path_operator_write_node_t
ConstantPathOperatorWriteNode.
struct pm_implicit_rest_node pm_implicit_rest_node_t
ImplicitRestNode.
@ PM_RANGE_FLAGS_EXCLUDE_END
... operator
struct pm_local_variable_or_write_node pm_local_variable_or_write_node_t
LocalVariableOrWriteNode.
struct pm_local_variable_read_node pm_local_variable_read_node_t
LocalVariableReadNode.
struct pm_global_variable_and_write_node pm_global_variable_and_write_node_t
GlobalVariableAndWriteNode.
struct pm_arguments_node pm_arguments_node_t
ArgumentsNode.
@ PM_DEFINED_NODE
DefinedNode.
@ PM_PRE_EXECUTION_NODE
PreExecutionNode.
@ PM_RETRY_NODE
RetryNode.
@ PM_CONSTANT_PATH_WRITE_NODE
ConstantPathWriteNode.
@ PM_INDEX_AND_WRITE_NODE
IndexAndWriteNode.
@ PM_SOURCE_LINE_NODE
SourceLineNode.
@ PM_UNLESS_NODE
UnlessNode.
@ PM_EMBEDDED_VARIABLE_NODE
EmbeddedVariableNode.
@ PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE
GlobalVariableOperatorWriteNode.
@ PM_GLOBAL_VARIABLE_READ_NODE
GlobalVariableReadNode.
@ PM_RATIONAL_NODE
RationalNode.
@ PM_YIELD_NODE
YieldNode.
@ PM_LOCAL_VARIABLE_AND_WRITE_NODE
LocalVariableAndWriteNode.
@ PM_CONSTANT_AND_WRITE_NODE
ConstantAndWriteNode.
@ PM_CLASS_NODE
ClassNode.
@ PM_FIND_PATTERN_NODE
FindPatternNode.
@ PM_CALL_OPERATOR_WRITE_NODE
CallOperatorWriteNode.
@ PM_MATCH_WRITE_NODE
MatchWriteNode.
@ PM_ARRAY_NODE
ArrayNode.
@ PM_CONSTANT_PATH_TARGET_NODE
ConstantPathTargetNode.
@ PM_PROGRAM_NODE
ProgramNode.
@ PM_MULTI_WRITE_NODE
MultiWriteNode.
@ PM_IMPLICIT_NODE
ImplicitNode.
@ PM_ARGUMENTS_NODE
ArgumentsNode.
@ PM_FORWARDING_SUPER_NODE
ForwardingSuperNode.
@ PM_WHILE_NODE
WhileNode.
@ PM_INTERPOLATED_STRING_NODE
InterpolatedStringNode.
@ PM_FALSE_NODE
FalseNode.
@ PM_FORWARDING_PARAMETER_NODE
ForwardingParameterNode.
@ PM_BLOCK_LOCAL_VARIABLE_NODE
BlockLocalVariableNode.
@ PM_UNTIL_NODE
UntilNode.
@ PM_MATCH_PREDICATE_NODE
MatchPredicateNode.
@ PM_X_STRING_NODE
XStringNode.
@ PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE
LocalVariableOperatorWriteNode.
@ PM_LOCAL_VARIABLE_OR_WRITE_NODE
LocalVariableOrWriteNode.
@ PM_INSTANCE_VARIABLE_AND_WRITE_NODE
InstanceVariableAndWriteNode.
@ PM_GLOBAL_VARIABLE_TARGET_NODE
GlobalVariableTargetNode.
@ PM_CONSTANT_TARGET_NODE
ConstantTargetNode.
@ PM_CONSTANT_PATH_AND_WRITE_NODE
ConstantPathAndWriteNode.
@ PM_BLOCK_PARAMETER_NODE
BlockParameterNode.
@ PM_CAPTURE_PATTERN_NODE
CapturePatternNode.
@ PM_SOURCE_FILE_NODE
SourceFileNode.
@ PM_NO_KEYWORDS_PARAMETER_NODE
NoKeywordsParameterNode.
@ PM_CONSTANT_PATH_OPERATOR_WRITE_NODE
ConstantPathOperatorWriteNode.
@ PM_MULTI_TARGET_NODE
MultiTargetNode.
@ PM_SPLAT_NODE
SplatNode.
@ PM_LAMBDA_NODE
LambdaNode.
@ PM_CLASS_VARIABLE_READ_NODE
ClassVariableReadNode.
@ PM_REQUIRED_KEYWORD_PARAMETER_NODE
RequiredKeywordParameterNode.
@ PM_CALL_TARGET_NODE
CallTargetNode.
@ PM_INTERPOLATED_MATCH_LAST_LINE_NODE
InterpolatedMatchLastLineNode.
@ PM_NUMBERED_PARAMETERS_NODE
NumberedParametersNode.
@ PM_SYMBOL_NODE
SymbolNode.
@ PM_RESCUE_MODIFIER_NODE
RescueModifierNode.
@ PM_ALIAS_METHOD_NODE
AliasMethodNode.
@ PM_MATCH_REQUIRED_NODE
MatchRequiredNode.
@ PM_FORWARDING_ARGUMENTS_NODE
ForwardingArgumentsNode.
@ PM_BACK_REFERENCE_READ_NODE
BackReferenceReadNode.
@ PM_BLOCK_ARGUMENT_NODE
BlockArgumentNode.
@ PM_MISSING_NODE
MissingNode.
@ PM_IMPLICIT_REST_NODE
ImplicitRestNode.
@ PM_ASSOC_SPLAT_NODE
AssocSplatNode.
@ PM_CLASS_VARIABLE_AND_WRITE_NODE
ClassVariableAndWriteNode.
@ PM_RANGE_NODE
RangeNode.
@ PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE
InstanceVariableOperatorWriteNode.
@ PM_LOCAL_VARIABLE_READ_NODE
LocalVariableReadNode.
@ PM_INSTANCE_VARIABLE_OR_WRITE_NODE
InstanceVariableOrWriteNode.
@ PM_REGULAR_EXPRESSION_NODE
RegularExpressionNode.
@ PM_CLASS_VARIABLE_OR_WRITE_NODE
ClassVariableOrWriteNode.
@ PM_BLOCK_PARAMETERS_NODE
BlockParametersNode.
@ PM_CONSTANT_WRITE_NODE
ConstantWriteNode.
@ PM_HASH_PATTERN_NODE
HashPatternNode.
@ PM_INDEX_OPERATOR_WRITE_NODE
IndexOperatorWriteNode.
@ PM_UNDEF_NODE
UndefNode.
@ PM_ALTERNATION_PATTERN_NODE
AlternationPatternNode.
@ PM_ENSURE_NODE
EnsureNode.
@ PM_LOCAL_VARIABLE_WRITE_NODE
LocalVariableWriteNode.
@ PM_SINGLETON_CLASS_NODE
SingletonClassNode.
@ PM_KEYWORD_HASH_NODE
KeywordHashNode.
@ PM_PARENTHESES_NODE
ParenthesesNode.
@ PM_CLASS_VARIABLE_WRITE_NODE
ClassVariableWriteNode.
@ PM_POST_EXECUTION_NODE
PostExecutionNode.
@ PM_CONSTANT_OPERATOR_WRITE_NODE
ConstantOperatorWriteNode.
@ PM_RETURN_NODE
ReturnNode.
@ PM_MODULE_NODE
ModuleNode.
@ PM_ARRAY_PATTERN_NODE
ArrayPatternNode.
@ PM_SUPER_NODE
SuperNode.
@ PM_MATCH_LAST_LINE_NODE
MatchLastLineNode.
@ PM_CONSTANT_PATH_NODE
ConstantPathNode.
@ PM_INTERPOLATED_SYMBOL_NODE
InterpolatedSymbolNode.
@ PM_CALL_AND_WRITE_NODE
CallAndWriteNode.
@ PM_OPTIONAL_KEYWORD_PARAMETER_NODE
OptionalKeywordParameterNode.
@ PM_CLASS_VARIABLE_TARGET_NODE
ClassVariableTargetNode.
@ PM_CASE_MATCH_NODE
CaseMatchNode.
@ PM_BREAK_NODE
BreakNode.
@ PM_CALL_OR_WRITE_NODE
CallOrWriteNode.
@ PM_IMAGINARY_NODE
ImaginaryNode.
@ PM_CONSTANT_READ_NODE
ConstantReadNode.
@ PM_GLOBAL_VARIABLE_WRITE_NODE
GlobalVariableWriteNode.
@ PM_SOURCE_ENCODING_NODE
SourceEncodingNode.
@ PM_BEGIN_NODE
BeginNode.
@ PM_INTERPOLATED_X_STRING_NODE
InterpolatedXStringNode.
@ PM_INSTANCE_VARIABLE_READ_NODE
InstanceVariableReadNode.
@ PM_FLIP_FLOP_NODE
FlipFlopNode.
@ PM_PINNED_VARIABLE_NODE
PinnedVariableNode.
@ PM_REQUIRED_PARAMETER_NODE
RequiredParameterNode.
@ PM_INSTANCE_VARIABLE_WRITE_NODE
InstanceVariableWriteNode.
@ PM_INSTANCE_VARIABLE_TARGET_NODE
InstanceVariableTargetNode.
@ PM_GLOBAL_VARIABLE_AND_WRITE_NODE
GlobalVariableAndWriteNode.
@ PM_RESCUE_NODE
RescueNode.
@ PM_FLOAT_NODE
FloatNode.
@ PM_ASSOC_NODE
AssocNode.
@ PM_INTEGER_NODE
IntegerNode.
@ PM_LOCAL_VARIABLE_TARGET_NODE
LocalVariableTargetNode.
@ PM_STRING_NODE
StringNode.
@ PM_INDEX_OR_WRITE_NODE
IndexOrWriteNode.
@ PM_ALIAS_GLOBAL_VARIABLE_NODE
AliasGlobalVariableNode.
@ PM_PARAMETERS_NODE
ParametersNode.
@ PM_NUMBERED_REFERENCE_READ_NODE
NumberedReferenceReadNode.
@ PM_CONSTANT_PATH_OR_WRITE_NODE
ConstantPathOrWriteNode.
@ PM_GLOBAL_VARIABLE_OR_WRITE_NODE
GlobalVariableOrWriteNode.
@ PM_CONSTANT_OR_WRITE_NODE
ConstantOrWriteNode.
@ PM_STATEMENTS_NODE
StatementsNode.
@ PM_OPTIONAL_PARAMETER_NODE
OptionalParameterNode.
@ PM_PINNED_EXPRESSION_NODE
PinnedExpressionNode.
@ PM_BLOCK_NODE
BlockNode.
@ PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE
ClassVariableOperatorWriteNode.
@ PM_REST_PARAMETER_NODE
RestParameterNode.
@ PM_EMBEDDED_STATEMENTS_NODE
EmbeddedStatementsNode.
@ PM_INTERPOLATED_REGULAR_EXPRESSION_NODE
InterpolatedRegularExpressionNode.
@ PM_INDEX_TARGET_NODE
IndexTargetNode.
@ PM_KEYWORD_REST_PARAMETER_NODE
KeywordRestParameterNode.
struct pm_nil_node pm_nil_node_t
NilNode.
struct pm_begin_node pm_begin_node_t
BeginNode.
struct pm_statements_node pm_statements_node_t
StatementsNode.
struct pm_instance_variable_write_node pm_instance_variable_write_node_t
InstanceVariableWriteNode.
struct pm_false_node pm_false_node_t
FalseNode.
struct pm_keyword_hash_node pm_keyword_hash_node_t
KeywordHashNode.
struct pm_return_node pm_return_node_t
ReturnNode.
struct pm_constant_path_node pm_constant_path_node_t
ConstantPathNode.
struct pm_local_variable_write_node pm_local_variable_write_node_t
LocalVariableWriteNode.
@ PM_STRING_FLAGS_FROZEN
frozen by virtue of a frozen_string_literal comment
@ PM_STRING_FLAGS_FORCED_BINARY_ENCODING
internal bytes forced the encoding to binary
@ PM_STRING_FLAGS_FORCED_UTF8_ENCODING
internal bytes forced the encoding to UTF-8
struct pm_implicit_node pm_implicit_node_t
ImplicitNode.
struct pm_yield_node pm_yield_node_t
YieldNode.
@ PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT
if arguments contain keyword splat
struct pm_local_variable_and_write_node pm_local_variable_and_write_node_t
LocalVariableAndWriteNode.
struct pm_parameters_node pm_parameters_node_t
ParametersNode.
struct pm_lambda_node pm_lambda_node_t
LambdaNode.
#define PM_NODE_FLAG_P(node, flag)
Return true if the given flag is set on the given node.
struct pm_module_node pm_module_node_t
ModuleNode.
struct pm_case_node pm_case_node_t
CaseNode.
struct pm_in_node pm_in_node_t
InNode.
struct pm_if_node pm_if_node_t
IfNode.
struct pm_constant_path_write_node pm_constant_path_write_node_t
ConstantPathWriteNode.
struct pm_pre_execution_node pm_pre_execution_node_t
PreExecutionNode.
struct pm_rescue_modifier_node pm_rescue_modifier_node_t
RescueModifierNode.
struct pm_splat_node pm_splat_node_t
SplatNode.
struct pm_match_write_node pm_match_write_node_t
MatchWriteNode.
struct pm_multi_write_node pm_multi_write_node_t
MultiWriteNode.
struct pm_local_variable_operator_write_node pm_local_variable_operator_write_node_t
LocalVariableOperatorWriteNode.
struct pm_block_argument_node pm_block_argument_node_t
BlockArgumentNode.
struct pm_interpolated_x_string_node pm_interpolated_x_string_node_t
InterpolatedXStringNode.
struct pm_constant_write_node pm_constant_write_node_t
ConstantWriteNode.
struct pm_flip_flop_node pm_flip_flop_node_t
FlipFlopNode.
struct pm_required_keyword_parameter_node pm_required_keyword_parameter_node_t
RequiredKeywordParameterNode.
#define PM_NODE_TYPE_P(node, type)
Return true if the type of the given node matches the given type.
#define PM_NODE_TYPE(node)
Cast the type to an enum to allow the compiler to provide exhaustiveness checking.
struct pm_no_keywords_parameter_node pm_no_keywords_parameter_node_t
NoKeywordsParameterNode.
struct pm_alias_global_variable_node pm_alias_global_variable_node_t
AliasGlobalVariableNode.
struct pm_post_execution_node pm_post_execution_node_t
PostExecutionNode.
@ PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT
if array contains splat nodes
struct pm_alias_method_node pm_alias_method_node_t
AliasMethodNode.
struct pm_keyword_rest_parameter_node pm_keyword_rest_parameter_node_t
KeywordRestParameterNode.
struct pm_global_variable_read_node pm_global_variable_read_node_t
GlobalVariableReadNode.
struct pm_back_reference_read_node pm_back_reference_read_node_t
BackReferenceReadNode.
struct pm_match_last_line_node pm_match_last_line_node_t
MatchLastLineNode.
struct pm_hash_node pm_hash_node_t
HashNode.
struct pm_block_local_variable_node pm_block_local_variable_node_t
BlockLocalVariableNode.
struct pm_multi_target_node pm_multi_target_node_t
MultiTargetNode.
@ PM_INTEGER_BASE_FLAGS_HEXADECIMAL
0x prefix
@ PM_INTEGER_BASE_FLAGS_OCTAL
0o or 0 prefix
@ PM_INTEGER_BASE_FLAGS_DECIMAL
0d or no prefix
@ PM_INTEGER_BASE_FLAGS_BINARY
0b prefix
struct pm_rational_node pm_rational_node_t
RationalNode.
struct pm_class_node pm_class_node_t
ClassNode.
struct pm_pinned_expression_node pm_pinned_expression_node_t
PinnedExpressionNode.
struct pm_constant_operator_write_node pm_constant_operator_write_node_t
ConstantOperatorWriteNode.
struct pm_ensure_node pm_ensure_node_t
EnsureNode.
struct pm_index_or_write_node pm_index_or_write_node_t
IndexOrWriteNode.
struct pm_forwarding_parameter_node pm_forwarding_parameter_node_t
ForwardingParameterNode.
struct pm_constant_or_write_node pm_constant_or_write_node_t
ConstantOrWriteNode.
struct pm_index_operator_write_node pm_index_operator_write_node_t
IndexOperatorWriteNode.
struct pm_when_node pm_when_node_t
WhenNode.
enum pm_token_type pm_token_type_t
This enum represents every type of token in the Ruby source.
struct pm_super_node pm_super_node_t
SuperNode.
struct pm_range_node pm_range_node_t
RangeNode.
struct pm_and_node pm_and_node_t
AndNode.
struct pm_constant_path_and_write_node pm_constant_path_and_write_node_t
ConstantPathAndWriteNode.
struct pm_rest_parameter_node pm_rest_parameter_node_t
RestParameterNode.
#define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS
When we're serializing to Java, we want to skip serializing the location fields as they won't be used...
struct pm_assoc_splat_node pm_assoc_splat_node_t
AssocSplatNode.
@ PM_CALL_NODE_FLAGS_SAFE_NAVIGATION
&.
@ PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE
a call that is an attribute write, so the value being written should be returned
@ PM_CALL_NODE_FLAGS_VARIABLE_CALL
a call that could have been a local variable
struct pm_constant_read_node pm_constant_read_node_t
ConstantReadNode.
struct pm_match_predicate_node pm_match_predicate_node_t
MatchPredicateNode.
struct pm_or_node pm_or_node_t
OrNode.
struct pm_case_match_node pm_case_match_node_t
CaseMatchNode.
struct pm_call_and_write_node pm_call_and_write_node_t
CallAndWriteNode.
struct pm_until_node pm_until_node_t
UntilNode.
struct pm_retry_node pm_retry_node_t
RetryNode.
struct pm_imaginary_node pm_imaginary_node_t
ImaginaryNode.
struct pm_array_pattern_node pm_array_pattern_node_t
ArrayPatternNode.
struct pm_redo_node pm_redo_node_t
RedoNode.
struct pm_source_encoding_node pm_source_encoding_node_t
SourceEncodingNode.
struct pm_true_node pm_true_node_t
TrueNode.
struct pm_break_node pm_break_node_t
BreakNode.
struct pm_integer_node pm_integer_node_t
IntegerNode.
struct pm_constant_path_target_node pm_constant_path_target_node_t
ConstantPathTargetNode.
struct pm_call_operator_write_node pm_call_operator_write_node_t
CallOperatorWriteNode.
struct pm_for_node pm_for_node_t
ForNode.
struct pm_global_variable_target_node pm_global_variable_target_node_t
GlobalVariableTargetNode.
struct pm_node_list pm_node_list_t
A list of nodes in the source, most often used for lists of children.
struct pm_required_parameter_node pm_required_parameter_node_t
RequiredParameterNode.
struct pm_symbol_node pm_symbol_node_t
SymbolNode.
struct pm_block_parameters_node pm_block_parameters_node_t
BlockParametersNode.
struct pm_alternation_pattern_node pm_alternation_pattern_node_t
AlternationPatternNode.
struct pm_parentheses_node pm_parentheses_node_t
ParenthesesNode.
@ PM_REGULAR_EXPRESSION_FLAGS_EUC_JP
e - forces the EUC-JP encoding
@ PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE
i - ignores the case of characters when matching
@ PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT
n - forces the ASCII-8BIT encoding
@ PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE
m - allows $ to match the end of lines within strings
@ PM_REGULAR_EXPRESSION_FLAGS_EXTENDED
x - ignores whitespace and allows comments in regular expressions
@ PM_REGULAR_EXPRESSION_FLAGS_ONCE
o - only interpolates values into the regular expression once
@ PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J
s - forces the Windows-31J encoding
@ PM_REGULAR_EXPRESSION_FLAGS_UTF_8
u - forces the UTF-8 encoding
struct pm_forwarding_arguments_node pm_forwarding_arguments_node_t
ForwardingArgumentsNode.
struct pm_instance_variable_read_node pm_instance_variable_read_node_t
InstanceVariableReadNode.
struct pm_constant_target_node pm_constant_target_node_t
ConstantTargetNode.
struct pm_node pm_node_t
This is the base structure that represents a node in the syntax tree.
struct pm_defined_node pm_defined_node_t
DefinedNode.
struct pm_interpolated_symbol_node pm_interpolated_symbol_node_t
InterpolatedSymbolNode.
struct pm_class_variable_target_node pm_class_variable_target_node_t
ClassVariableTargetNode.
struct pm_def_node pm_def_node_t
DefNode.
struct pm_singleton_class_node pm_singleton_class_node_t
SingletonClassNode.
uint16_t pm_node_flags_t
These are the flags embedded in the node struct.
struct pm_capture_pattern_node pm_capture_pattern_node_t
CapturePatternNode.
struct pm_source_file_node pm_source_file_node_t
SourceFileNode.
struct pm_regular_expression_node pm_regular_expression_node_t
RegularExpressionNode.
@ PM_TOKEN_DOT_DOT_DOT
the ... range operator or forwarding parameter
@ PM_TOKEN_IGNORED_NEWLINE
an ignored newline
@ PM_TOKEN_KEYWORD___FILE__
FILE
@ PM_TOKEN_KEYWORD_WHEN
when
@ PM_TOKEN_FLOAT
a floating point number
@ PM_TOKEN_UDOT_DOT
unary .
@ PM_TOKEN_AMPERSAND_DOT
&.
@ PM_TOKEN_NEWLINE
a newline character outside of other tokens
@ PM_TOKEN_NUMBERED_REFERENCE
a numbered reference to a capture group in the previous regular expression match
@ PM_TOKEN_KEYWORD_YIELD
yield
@ PM_TOKEN_KEYWORD_END
end
@ PM_TOKEN_KEYWORD_UNTIL_MODIFIER
until in the modifier form
@ PM_TOKEN_EQUAL_EQUAL_EQUAL
===
@ PM_TOKEN_INTEGER_RATIONAL
an integer with a rational suffix
@ PM_TOKEN_KEYWORD___ENCODING__
ENCODING
@ PM_TOKEN_REGEXP_END
the end of a regular expression
@ PM_TOKEN_KEYWORD_UNTIL
until
@ PM_TOKEN_MAXIMUM
The maximum token value.
@ PM_TOKEN_INTEGER
an integer (any base)
@ PM_TOKEN_UMINUS_NUM
-@ for a number
@ PM_TOKEN_KEYWORD_UNLESS_MODIFIER
unless in the modifier form
@ PM_TOKEN_INTEGER_RATIONAL_IMAGINARY
an integer with a rational and imaginary suffix
@ PM_TOKEN_FLOAT_RATIONAL_IMAGINARY
a floating pointer number with a rational and imaginary suffix
@ PM_TOKEN_BRACKET_LEFT_RIGHT
[]
@ PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL
&&=
@ PM_TOKEN_KEYWORD_CLASS
class
@ PM_TOKEN_KEYWORD_BEGIN
begin
@ PM_TOKEN_NOT_PROVIDED
a token that was not present but it is okay
@ PM_TOKEN_USTAR_STAR
unary **
@ PM_TOKEN_GREATER_GREATER_EQUAL
@ PM_TOKEN_PERCENT_EQUAL
%=
@ PM_TOKEN_KEYWORD_NOT
not
@ PM_TOKEN_BRACKET_LEFT_ARRAY
[ for the beginning of an array
@ PM_TOKEN_HEREDOC_END
the end of a heredoc
@ PM_TOKEN_HEREDOC_START
the start of a heredoc
@ PM_TOKEN_KEYWORD_DEFINED
defined?
@ PM_TOKEN_UCOLON_COLON
unary ::
@ PM_TOKEN_LABEL_END
the end of a label
@ PM_TOKEN_EQUAL_GREATER
=>
@ PM_TOKEN_KEYWORD_UNLESS
unless
@ PM_TOKEN_KEYWORD_ENSURE
ensure
@ PM_TOKEN_AMPERSAND_EQUAL
&=
@ PM_TOKEN_FLOAT_IMAGINARY
a floating pointer number with an imaginary suffix
@ PM_TOKEN_KEYWORD_BEGIN_UPCASE
BEGIN.
@ PM_TOKEN_LESS_EQUAL_GREATER
<=>
@ PM_TOKEN_KEYWORD_RESCUE_MODIFIER
rescue in the modifier form
@ PM_TOKEN_MISSING
a token that was expected but not found
@ PM_TOKEN_MINUS_GREATER
->
@ PM_TOKEN_KEYWORD_FALSE
false
@ PM_TOKEN_PIPE_PIPE_EQUAL
||=
@ PM_TOKEN_EMBEXPR_BEGIN
#{
@ PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES
( for a parentheses node
@ PM_TOKEN_EMBDOC_END
=end
@ PM_TOKEN_KEYWORD_ELSE
else
@ PM_TOKEN_BACK_REFERENCE
a back reference
@ PM_TOKEN_EOF
final token in the file
@ PM_TOKEN_KEYWORD_NIL
nil
@ PM_TOKEN_PERCENT_UPPER_W
W
@ PM_TOKEN_KEYWORD_RETURN
return
@ PM_TOKEN_CLASS_VARIABLE
a class variable
@ PM_TOKEN_PARENTHESIS_LEFT
(
@ PM_TOKEN_PARENTHESIS_RIGHT
)
@ PM_TOKEN_KEYWORD_RESCUE
rescue
@ PM_TOKEN_INSTANCE_VARIABLE
an instance variable
@ PM_TOKEN_BRACKET_LEFT_RIGHT_EQUAL
[]=
@ PM_TOKEN_UAMPERSAND
unary &
@ PM_TOKEN_CONSTANT
a constant
@ PM_TOKEN_IDENTIFIER
an identifier
@ PM_TOKEN_EMBDOC_BEGIN
=begin
@ PM_TOKEN_KEYWORD_AND
and
@ PM_TOKEN_KEYWORD_BREAK
break
@ PM_TOKEN_PERCENT_LOWER_W
w
@ PM_TOKEN_SYMBOL_BEGIN
the beginning of a symbol
@ PM_TOKEN_METHOD_NAME
a method name
@ PM_TOKEN_KEYWORD_CASE
case
@ PM_TOKEN_WORDS_SEP
a separator between words in a list
@ PM_TOKEN_FLOAT_RATIONAL
a floating pointer number with a rational suffix
@ PM_TOKEN_LESS_LESS_EQUAL
<<=
@ PM_TOKEN_EMBDOC_LINE
a line inside of embedded documentation
@ PM_TOKEN_KEYWORD_SUPER
super
@ PM_TOKEN_KEYWORD_REDO
redo
@ PM_TOKEN_KEYWORD_END_UPCASE
END.
@ PM_TOKEN_KEYWORD___LINE__
LINE
@ PM_TOKEN_STRING_END
the end of a string
@ PM_TOKEN_STRING_CONTENT
the contents of a string
@ PM_TOKEN_GREATER_GREATER
@ PM_TOKEN_PERCENT_LOWER_X
x
@ PM_TOKEN_KEYWORD_SELF
self
@ PM_TOKEN_PERCENT_LOWER_I
i
@ PM_TOKEN_KEYWORD_ALIAS
alias
@ PM_TOKEN_GLOBAL_VARIABLE
a global variable
@ PM_TOKEN_KEYWORD_IF_MODIFIER
if in the modifier form
@ PM_TOKEN_KEYWORD_RETRY
retry
@ PM_TOKEN_KEYWORD_UNDEF
undef
@ PM_TOKEN_BRACKET_RIGHT
]
@ PM_TOKEN_KEYWORD_FOR
for
@ PM_TOKEN_KEYWORD_THEN
then
@ PM_TOKEN_QUESTION_MARK
?
@ PM_TOKEN___END__
marker for the point in the file at which the parser should stop
@ PM_TOKEN_KEYWORD_WHILE
while
@ PM_TOKEN_KEYWORD_DEF
def
@ PM_TOKEN_UDOT_DOT_DOT
unary ... operator
@ PM_TOKEN_KEYWORD_WHILE_MODIFIER
while in the modifier form
@ PM_TOKEN_KEYWORD_TRUE
true
@ PM_TOKEN_REGEXP_BEGIN
the beginning of a regular expression
@ PM_TOKEN_PERCENT_UPPER_I
I
@ PM_TOKEN_KEYWORD_DO_LOOP
do keyword for a predicate in a while, until, or for loop
@ PM_TOKEN_KEYWORD_MODULE
module
@ PM_TOKEN_KEYWORD_NEXT
next
@ PM_TOKEN_INTEGER_IMAGINARY
an integer with an imaginary suffix
@ PM_TOKEN_STAR_STAR_EQUAL
**=
@ PM_TOKEN_CHARACTER_LITERAL
a character literal
@ PM_TOKEN_AMPERSAND_AMPERSAND
&&
@ PM_TOKEN_GREATER_EQUAL
>=
@ PM_TOKEN_COMMENT
a comment
@ PM_TOKEN_KEYWORD_ELSIF
elsif
@ PM_TOKEN_STRING_BEGIN
the beginning of a string
struct pm_global_variable_or_write_node pm_global_variable_or_write_node_t
GlobalVariableOrWriteNode.
struct pm_rescue_node pm_rescue_node_t
RescueNode.
struct pm_array_node pm_array_node_t
ArrayNode.
struct pm_while_node pm_while_node_t
WhileNode.
struct pm_global_variable_write_node pm_global_variable_write_node_t
GlobalVariableWriteNode.
struct pm_instance_variable_or_write_node pm_instance_variable_or_write_node_t
InstanceVariableOrWriteNode.
struct pm_source_line_node pm_source_line_node_t
SourceLineNode.
@ PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING
internal bytes forced the encoding to UTF-8
struct pm_interpolated_match_last_line_node pm_interpolated_match_last_line_node_t
InterpolatedMatchLastLineNode.
struct pm_numbered_parameters_node pm_numbered_parameters_node_t
NumberedParametersNode.
struct pm_class_variable_operator_write_node pm_class_variable_operator_write_node_t
ClassVariableOperatorWriteNode.
struct pm_next_node pm_next_node_t
NextNode.
struct pm_unless_node pm_unless_node_t
UnlessNode.
struct pm_interpolated_regular_expression_node pm_interpolated_regular_expression_node_t
InterpolatedRegularExpressionNode.
struct pm_instance_variable_target_node pm_instance_variable_target_node_t
InstanceVariableTargetNode.
struct pm_string_node pm_string_node_t
StringNode.
struct pm_float_node pm_float_node_t
FloatNode.
struct pm_global_variable_operator_write_node pm_global_variable_operator_write_node_t
GlobalVariableOperatorWriteNode.
struct pm_instance_variable_operator_write_node pm_instance_variable_operator_write_node_t
InstanceVariableOperatorWriteNode.
@ PM_LOOP_FLAGS_BEGIN_MODIFIER
a loop after a begin statement, so the body is executed first before the condition
struct pm_pinned_variable_node pm_pinned_variable_node_t
PinnedVariableNode.
struct pm_instance_variable_and_write_node pm_instance_variable_and_write_node_t
InstanceVariableAndWriteNode.
struct pm_program_node pm_program_node_t
ProgramNode.
struct pm_find_pattern_node pm_find_pattern_node_t
FindPatternNode.
pm_diagnostic_id_t
The diagnostic IDs of all of the diagnostics, used to communicate the types of errors between the par...
VALUE type(ANYARGS)
ANYARGS-ed function type.
struct pm_options_scope pm_options_scope_t
A scope of locals surrounding the code that is being parsed.
pm_heredoc_indent_t
The type of indentation that a heredoc uses.
struct pm_context_node pm_context_node_t
This is a node in a linked list of contexts.
#define PM_LEX_STACK_SIZE
We pre-allocate a certain number of lex states in order to avoid having to call malloc too many times...
struct pm_parser pm_parser_t
The parser used to parse Ruby source.
struct pm_lex_mode pm_lex_mode_t
When lexing Ruby source, the lexer has a small amount of state to tell which kind of token it is curr...
struct pm_comment pm_comment_t
This is a node in the linked list of comments that we've found while parsing.
pm_lex_state_t
This enum combines the various bits from the above enum into individual values that represent the var...
struct pm_scope pm_scope_t
This struct represents a node in a linked list of scopes.
pm_heredoc_quote_t
The type of quote that a heredoc uses.
void(* pm_encoding_changed_callback_t)(pm_parser_t *parser)
When the encoding that is being used to parse the source is changed by prism, we provide the ability ...
pm_context_t
While parsing, we keep track of a stack of contexts.
@ PM_CONTEXT_ELSIF
an elsif clause
@ PM_CONTEXT_ENSURE_DEF
an ensure statement within a method definition
@ PM_CONTEXT_ELSE
an else clause
@ PM_CONTEXT_FOR_INDEX
a for loop's index
@ PM_CONTEXT_CASE_WHEN
a case when statements
@ PM_CONTEXT_MODULE
a module declaration
@ PM_CONTEXT_DEF_PARAMS
a method definition's parameters
@ PM_CONTEXT_CASE_IN
a case in statements
@ PM_CONTEXT_SCLASS
a singleton class definition
@ PM_CONTEXT_UNLESS
an unless statement
@ PM_CONTEXT_POSTEXE
an END block
@ PM_CONTEXT_IF
an if statement
@ PM_CONTEXT_RESCUE_DEF
a rescue statement within a method definition
@ PM_CONTEXT_RESCUE
a rescue statement
@ PM_CONTEXT_LAMBDA_BRACES
a lambda expression with braces
@ PM_CONTEXT_PARENS
a parenthesized expression
@ PM_CONTEXT_BLOCK_BRACES
expressions in block arguments using braces
@ PM_CONTEXT_PREEXE
a BEGIN block
@ PM_CONTEXT_RESCUE_ELSE
a rescue else statement
@ PM_CONTEXT_UNTIL
an until statement
@ PM_CONTEXT_FOR
a for loop
@ PM_CONTEXT_PREDICATE
a predicate inside an if/elsif/unless statement
@ PM_CONTEXT_RESCUE_ELSE_DEF
a rescue else statement within a method definition
@ PM_CONTEXT_DEFAULT_PARAMS
a method definition's default parameter
@ PM_CONTEXT_CLASS
a class declaration
@ PM_CONTEXT_MAIN
the top level context
@ PM_CONTEXT_LAMBDA_DO_END
a lambda expression with do..end
@ PM_CONTEXT_BEGIN
a begin statement
@ PM_CONTEXT_ENSURE
an ensure statement
@ PM_CONTEXT_EMBEXPR
an interpolated expression
@ PM_CONTEXT_DEF
a method definition
@ PM_CONTEXT_BLOCK_KEYWORDS
expressions in block arguments using do..end
@ PM_CONTEXT_WHILE
a while statement
#define PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS
Temporary alias for the PM_NODE_FLAG_STATIC_KEYS flag.
pm_comment_type_t
This is the type of a comment that we've found while parsing.
uint32_t pm_constant_id_t
A constant id is a unique identifier for a constant in the constant pool.
struct pm_list_node pm_list_node_t
This struct represents an abstract linked list that provides common functionality.
#define PM_STRING_EMPTY
Defines an empty string.
#define PRISM_ATTRIBUTE_UNUSED
GCC will warn if you specify a function or parameter that is unused at runtime.
#define PM_STATIC_ASSERT(line, condition, message)
We want to be able to use static assertions, but they weren't standardized until C11.
#define PRISM_EXPORTED_FUNCTION
By default, we compile with -fvisibility=hidden.
#define PM_ENCODING_US_ASCII_ENTRY
This is the US-ASCII encoding.
#define PM_ENCODING_UTF_8_ENTRY
This is the default UTF-8 encoding.
#define PRISM_ENCODING_ALPHABETIC_BIT
All of the lookup tables use the first bit of each embedded byte to indicate whether the codepoint is...
#define PRISM_ENCODING_ALPHANUMERIC_BIT
All of the lookup tables use the second bit of each embedded byte to indicate whether the codepoint i...
#define PRISM_VERSION
The version of the Prism library as a constant string.
#define PRISM_VERSION_PATCH
The patch version of the Prism library as an int.
#define PRISM_VERSION_MINOR
The minor version of the Prism library as an int.
#define PRISM_VERSION_MAJOR
The major version of the Prism library as an int.
The main header file for the prism parser.
void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer)
Serialize the encoding, metadata, nodes, and constant pool.
void pm_serialize_encoding(const pm_encoding_t *encoding, pm_buffer_t *buffer)
Serialize the name of the encoding to the buffer.
PRISM_EXPORTED_FUNCTION const char * pm_token_type_to_str(pm_token_type_t token_type)
Returns a string representation of the given token type.
void pm_serialize_comment_list(pm_parser_t *parser, pm_list_t *list, pm_buffer_t *buffer)
Serialize the given list of comments to the given buffer.
#define errno
Ractor-aware version of errno.
struct pm_node * left
AndNode#left.
struct pm_node * right
AndNode#right.
pm_node_t base
The embedded base node.
struct pm_node_list arguments
ArgumentsNode#arguments.
This is a special out parameter to the parse_arguments_list function that includes opening and closin...
pm_node_t * block
The optional block attached to the call.
pm_location_t opening_loc
The optional location of the opening parenthesis or bracket.
pm_arguments_node_t * arguments
The lazily-allocated optional arguments node.
pm_location_t closing_loc
The optional location of the closing parenthesis or bracket.
pm_node_t base
The embedded base node.
pm_location_t closing_loc
ArrayNode#closing_loc.
struct pm_node_list elements
ArrayNode#elements.
pm_location_t opening_loc
ArrayNode#opening_loc.
struct pm_node_list requireds
ArrayPatternNode#requireds.
struct pm_node * rest
ArrayPatternNode#rest.
struct pm_node * constant
ArrayPatternNode#constant.
pm_location_t opening_loc
ArrayPatternNode#opening_loc.
pm_node_t base
The embedded base node.
pm_location_t closing_loc
ArrayPatternNode#closing_loc.
struct pm_node_list posts
ArrayPatternNode#posts.
pm_node_t base
The embedded base node.
struct pm_node * value
AssocNode#value.
struct pm_node * key
AssocNode#key.
struct pm_ensure_node * ensure_clause
BeginNode#ensure_clause.
struct pm_rescue_node * rescue_clause
BeginNode#rescue_clause.
struct pm_statements_node * statements
BeginNode#statements.
pm_node_t base
The embedded base node.
pm_location_t end_keyword_loc
BeginNode#end_keyword_loc.
pm_location_t begin_keyword_loc
BeginNode#begin_keyword_loc.
struct pm_else_node * else_clause
BeginNode#else_clause.
This struct represents a set of binding powers used for a given token.
bool binary
Whether or not this token can be used as a binary operator.
pm_binding_power_t left
The left binding power.
bool nonassoc
Whether or not this token can be used as non-associative binary operator.
pm_binding_power_t right
The right binding power.
pm_node_t base
The embedded base node.
pm_node_t base
The embedded base node.
pm_node_t base
The embedded base node.
struct pm_node_list locals
BlockParametersNode#locals.
pm_location_t closing_loc
BlockParametersNode#closing_loc.
A pm_buffer_t is a simple memory buffer that stores data in a contiguous block of memory.
size_t length
The length of the buffer in bytes.
char * value
A pointer to the start of the buffer.
pm_constant_id_t read_name
CallAndWriteNode#read_name.
pm_constant_id_t write_name
CallAndWriteNode#write_name.
pm_location_t opening_loc
CallNode#opening_loc.
pm_location_t closing_loc
CallNode#closing_loc.
struct pm_node * receiver
CallNode#receiver.
pm_constant_id_t name
CallNode::name.
pm_node_t base
The embedded base node.
pm_location_t call_operator_loc
CallNode#call_operator_loc.
pm_location_t message_loc
CallNode#message_loc.
struct pm_arguments_node * arguments
CallNode#arguments.
struct pm_node * block
CallNode#block.
pm_constant_id_t read_name
CallOperatorWriteNode#read_name.
pm_constant_id_t write_name
CallOperatorWriteNode#write_name.
pm_constant_id_t write_name
CallOrWriteNode#write_name.
pm_constant_id_t read_name
CallOrWriteNode#read_name.
pm_location_t end_keyword_loc
CaseMatchNode#end_keyword_loc.
struct pm_node_list conditions
CaseMatchNode#conditions.
struct pm_else_node * consequent
CaseMatchNode#consequent.
pm_node_t base
The embedded base node.
struct pm_else_node * consequent
CaseNode#consequent.
struct pm_node_list conditions
CaseNode#conditions.
pm_node_t base
The embedded base node.
pm_location_t end_keyword_loc
CaseNode#end_keyword_loc.
pm_node_t base
The embedded base node.
pm_constant_id_t name
ClassVariableReadNode#name.
size_t size
The number of constant ids in the list.
pm_node_t base
The embedded base node.
pm_node_t base
The embedded base node.
pm_constant_id_t name
ConstantReadNode#name.
A constant in the pool which effectively stores a string.
size_t length
The length of the string.
const uint8_t * start
A pointer to the start of the string.
pm_context_t context
The context that this node represents.
struct pm_context_node * prev
A pointer to the previous context in the linked list.
struct pm_statements_node * statements
ElseNode#statements.
pm_node_t base
The embedded base node.
pm_location_t end_keyword_loc
ElseNode#end_keyword_loc.
size_t(* alpha_char)(const uint8_t *b, ptrdiff_t n)
Return the number of bytes that the next character takes if it is valid in the encoding and is alphab...
size_t(* char_width)(const uint8_t *b, ptrdiff_t n)
Return the number of bytes that the next character takes if it is valid in the encoding.
bool(* isupper_char)(const uint8_t *b, ptrdiff_t n)
Return true if the next character is valid in the encoding and is an uppercase character.
const char * name
The name of the encoding.
size_t(* alnum_char)(const uint8_t *b, ptrdiff_t n)
Return the number of bytes that the next character takes if it is valid in the encoding and is alphan...
pm_node_t base
The embedded base node.
struct pm_node * constant
FindPatternNode#constant.
pm_location_t opening_loc
FindPatternNode#opening_loc.
pm_node_t base
The embedded base node.
struct pm_node_list requireds
FindPatternNode#requireds.
pm_location_t closing_loc
FindPatternNode#closing_loc.
struct pm_node_list elements
HashPatternNode#elements.
pm_location_t opening_loc
HashPatternNode#opening_loc.
pm_node_t base
The embedded base node.
pm_location_t closing_loc
HashPatternNode#closing_loc.
struct pm_node * constant
HashPatternNode#constant.
struct pm_node * consequent
IfNode#consequent.
pm_location_t end_keyword_loc
IfNode#end_keyword_loc.
struct pm_statements_node * statements
IfNode#statements.
pm_node_t base
The embedded base node.
pm_constant_id_t name
InstanceVariableReadNode#name.
pm_node_t base
The embedded base node.
struct pm_node_list parts
InterpolatedRegularExpressionNode#parts.
pm_node_t base
The embedded base node.
pm_location_t closing_loc
InterpolatedRegularExpressionNode#closing_loc.
pm_node_t base
The embedded base node.
pm_location_t closing_loc
InterpolatedStringNode#closing_loc.
pm_location_t opening_loc
InterpolatedStringNode#opening_loc.
struct pm_node_list parts
InterpolatedStringNode#parts.
struct pm_node_list parts
InterpolatedSymbolNode#parts.
pm_location_t opening_loc
InterpolatedSymbolNode#opening_loc.
pm_node_t base
The embedded base node.
pm_location_t opening_loc
InterpolatedXStringNode#opening_loc.
pm_location_t closing_loc
InterpolatedXStringNode#closing_loc.
pm_node_t base
The embedded base node.
struct pm_node_list parts
InterpolatedXStringNode#parts.
void(* callback)(void *data, pm_parser_t *parser, pm_token_t *token)
This is the callback that is called when a token is lexed.
void * data
This opaque pointer is used to provide whatever information the user deemed necessary to the callback...
uint8_t terminator
This is the terminator of the list literal.
const uint8_t * ident_start
A pointer to the start of the heredoc identifier.
size_t nesting
This keeps track of the nesting level of the list.
bool interpolation
Whether or not interpolation is allowed in this list.
pm_heredoc_indent_t indent
The type of indentation that the heredoc uses.
uint8_t incrementor
When lexing a list, it takes into account balancing the terminator if the terminator is one of (),...
struct pm_lex_mode * prev
The previous lex state so that it knows how to pop.
pm_heredoc_quote_t quote
The type of quote that the heredoc uses.
union pm_lex_mode::@303336126360075302344075121136356113360170030306 as
The data associated with this type of lex mode.
bool label_allowed
Whether or not at the end of the string we should allow a :, which would indicate this was a dynamic ...
const uint8_t * next_start
This is the pointer to the character where lexing should resume once the heredoc has been completely ...
size_t ident_length
The length of the heredoc identifier.
size_t common_whitespace
This is used to track the amount of common whitespace on each line so that we know how much to dedent...
uint8_t breakpoints[11]
This is the character set that should be used to delimit the tokens within the list.
enum pm_lex_mode::@204051102252353332352362146052355003264223055126 mode
The type of this lex mode.
struct pm_list_node * next
A pointer to the next node in the list.
This represents the overall linked list.
pm_list_node_t * head
A pointer to the head of the list.
uint32_t depth
LocalVariableReadNode#depth.
pm_constant_id_t name
LocalVariableReadNode#name.
This represents a range of bytes in the source string to which a node or token corresponds.
const uint8_t * start
A pointer to the start location of the range in the source.
const uint8_t * end
A pointer to the end location of the range in the source.
pm_node_t base
The embedded base node.
pm_location_t lparen_loc
MultiTargetNode#lparen_loc.
struct pm_node_list lefts
MultiTargetNode#lefts.
struct pm_node * rest
MultiTargetNode#rest.
pm_location_t rparen_loc
MultiTargetNode#rparen_loc.
struct pm_node_list rights
MultiTargetNode#rights.
size_t size
The number of nodes in the list.
struct pm_node ** nodes
The nodes in the list.
pm_node_type_t type
This represents the type of the node.
pm_node_flags_t flags
This represents any flags on the node.
pm_location_t location
This is the location of the node in the source.
size_t locals_count
The number of locals in the scope.
The options that can be passed to the parser.
size_t scopes_count
The number of scopes surrounding the code that is being parsed.
bool suppress_warnings
Whether or not we should suppress warnings.
pm_string_t encoding
The name of the encoding that the source file is in.
bool frozen_string_literal
Whether or not the frozen string literal option has been set.
int32_t line
The line within the file that the parse starts on.
pm_string_t filepath
The name of the file that is currently being parsed.
struct pm_node * left
OrNode#left.
struct pm_node * right
OrNode#right.
struct pm_node * rest
ParametersNode#rest.
struct pm_node_list requireds
ParametersNode#requireds.
struct pm_block_parameter_node * block
ParametersNode#block.
struct pm_node_list optionals
ParametersNode#optionals.
struct pm_node_list posts
ParametersNode#posts.
pm_node_t base
The embedded base node.
struct pm_node * keyword_rest
ParametersNode#keyword_rest.
struct pm_node_list keywords
ParametersNode#keywords.
struct pm_node * body
ParenthesesNode#body.
const pm_encoding_t * explicit_encoding
When a string-like expression is being lexed, any byte or escape sequence that resolves to a value wh...
pm_lex_state_t lex_state
The current state of the lexer.
const pm_encoding_t * encoding
The encoding functions for the current file is attached to the parser as it's parsing so that it can ...
bool pattern_matching_newlines
This flag indicates that we are currently parsing a pattern matching expression and impacts that calc...
const uint8_t * end
The pointer to the end of the source.
bool recovering
Whether or not we're currently recovering from a syntax error.
pm_node_flags_t integer_base
We want to add a flag to integer nodes that indicates their base.
pm_constant_pool_t constant_pool
This constant pool keeps all of the constants defined throughout the file so that we can reference th...
bool in_keyword_arg
This flag indicates that we are currently parsing a keyword argument.
bool suppress_warnings
Whether or not we should emit warnings.
const uint8_t * next_start
This is a special field set on the parser when we need the parser to jump to a specific location when...
pm_string_t filepath_string
This is the path of the file being parsed.
pm_list_t magic_comment_list
The list of magic comments that have been found while parsing.
int lambda_enclosure_nesting
Used to temporarily track the nesting of enclosures to determine if a { is the beginning of a lambda ...
pm_lex_callback_t * lex_callback
This is an optional callback that can be attached to the parser that will be called whenever a new to...
pm_token_t previous
The previous token we were considering.
pm_string_t current_string
This string is used to pass information from the lexer to the parser.
bool encoding_changed
Whether or not the encoding has been changed by a magic comment.
pm_location_t data_loc
The optional location of the END keyword and its contents.
pm_context_node_t * current_context
The current parsing context.
pm_constant_id_t current_param_name
The current parameter name id on parsing its default value.
const uint8_t * start
The pointer to the start of the source.
int enclosure_nesting
Tracks the current nesting of (), [], and {}.
pm_list_t error_list
The list of errors that have been found while parsing.
const uint8_t * encoding_comment_start
This pointer indicates where a comment must start if it is to be considered an encoding comment.
pm_lex_mode_t stack[PM_LEX_STACK_SIZE]
The stack of lexer modes.
pm_list_t warning_list
The list of warnings that have been found while parsing.
const uint8_t * heredoc_end
This field indicates the end of a heredoc whose identifier was found on the current line.
int brace_nesting
Used to track the nesting of braces to ensure we get the correct value when we are interpolating bloc...
pm_encoding_changed_callback_t encoding_changed_callback
When the encoding that is being used to parse the source is changed by prism, we provide the ability ...
int32_t start_line
The line number at the start of the parse.
pm_lex_mode_t * current
The current mode of the lexer.
struct pm_parser::@236040131255244317313236162207277265316171136011 lex_modes
A stack of lex modes.
pm_list_t comment_list
The list of comments that have been found while parsing.
size_t index
The current index into the lexer mode stack.
pm_scope_t * current_scope
The current local scope.
bool command_start
Whether or not we're at the beginning of a command.
bool frozen_string_literal
Whether or not we have found a frozen_string_literal magic comment with a true value.
pm_newline_list_t newline_list
This is the list of newline offsets in the source file.
bool semantic_token_seen
Whether or not the parser has seen a token that has semantic meaning (i.e., a token that is not a com...
struct pm_node * right
RangeNode#right.
struct pm_node * left
RangeNode#left.
struct pm_rescue_node * consequent
RescueNode#consequent.
pm_location_t operator_loc
RescueNode#operator_loc.
struct pm_node * reference
RescueNode#reference.
struct pm_node_list exceptions
RescueNode#exceptions.
struct pm_statements_node * statements
RescueNode#statements.
pm_node_t base
The embedded base node.
struct pm_scope * previous
A pointer to the previous scope in the linked list.
pm_constant_id_list_t locals
The IDs of the locals in the given scope.
bool explicit_params
A boolean indicating whether or not this scope has explicit parameters.
bool closed
A boolean indicating whether or not this scope can see into its parent.
uint8_t numbered_parameters
An integer indicating the number of numbered parameters on this scope.
struct pm_node * expression
SplatNode#expression.
struct pm_node_list body
StatementsNode#body.
pm_node_t base
The embedded base node.
pm_node_t base
The embedded base node.
pm_string_t unescaped
StringNode#unescaped.
pm_location_t content_loc
StringNode#content_loc.
pm_location_t closing_loc
StringNode#closing_loc.
pm_location_t opening_loc
StringNode#opening_loc.
A generic string type that can have various ownership semantics.
const uint8_t * source
A pointer to the start of the string.
size_t length
The length of the string in bytes of memory.
enum pm_string_t::@346265266332060241255337121126133217326336224105 type
The type of the string.
pm_location_t opening_loc
SymbolNode#opening_loc.
pm_location_t value_loc
SymbolNode#value_loc.
pm_location_t closing_loc
SymbolNode#closing_loc.
pm_string_t unescaped
SymbolNode#unescaped.
pm_node_t base
The embedded base node.
When we're lexing certain types (strings, symbols, lists, etc.) we have string content associated wit...
pm_buffer_t buffer
The buffer that we're using to keep track of the string content.
const uint8_t * cursor
The cursor into the source string that points to how far we have currently copied into the buffer.
This struct represents a token in the Ruby source.
const uint8_t * end
A pointer to the end location of the token in the source.
const uint8_t * start
A pointer to the start location of the token in the source.
pm_token_type_t type
The type of the token.
pm_node_t base
The embedded base node.
struct pm_node_list names
UndefNode#names.
struct pm_else_node * consequent
UnlessNode#consequent.
pm_location_t end_keyword_loc
UnlessNode#end_keyword_loc.
pm_node_t base
The embedded base node.
struct pm_statements_node * statements
UnlessNode#statements.
struct pm_statements_node * statements
WhenNode#statements.
pm_node_t base
The embedded base node.
struct pm_node_list conditions
WhenNode#conditions.