Skip to content

Commit

Permalink
Merge pull request #1370 from ruby/nth-ref
Browse files Browse the repository at this point in the history
Add a value to numbered references
  • Loading branch information
kddnewton authored Aug 30, 2023
2 parents 57c5a6e + 5d9b048 commit 2d37407
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 4 deletions.
3 changes: 3 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,9 @@ nodes:
^^^^^
end
- name: NumberedReferenceReadNode
fields:
- name: number
type: uint32
comment: |
Represents reading a numbered reference to a capture in the previous match.
Expand Down
1 change: 1 addition & 0 deletions include/yarp.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "yarp/version.h"

#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
Expand Down
35 changes: 34 additions & 1 deletion src/yarp.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,38 @@ yp_scope_node_init(yp_node_t *node, yp_scope_node_t *scope) {
/* Node creation functions */
/******************************************************************************/

// Parse the decimal number represented by the range of bytes. returns
// UINT32_MAX if the number fails to parse. This function assumes that the range
// of bytes has already been validated to contain only decimal digits.
static uint32_t
parse_decimal_number(yp_parser_t *parser, const uint8_t *start, const uint8_t *end) {
ptrdiff_t diff = end - start;
assert(diff > 0 && ((unsigned long) diff < SIZE_MAX));
size_t length = (size_t) diff;

char *digits = calloc(length + 1, sizeof(char));
memcpy(digits, start, length);
digits[length] = '\0';

char *endptr;
errno = 0;
unsigned long value = strtoul(digits, &endptr, 10);

if ((digits == endptr) || (*endptr != '\0') || (errno == ERANGE)) {
yp_diagnostic_list_append(&parser->error_list, start, end, "invalid decimal number");
value = UINT32_MAX;
}

free(digits);

if (value > UINT32_MAX) {
yp_diagnostic_list_append(&parser->error_list, start, end, "invalid decimal number");
value = UINT32_MAX;
}

return (uint32_t) value;
}

// Parse out the options for a regular expression.
static inline yp_node_flags_t
yp_regular_expression_flags_create(const yp_token_t *closing) {
Expand Down Expand Up @@ -3289,7 +3321,8 @@ yp_numbered_reference_read_node_create(yp_parser_t *parser, const yp_token_t *na
{
.type = YP_NODE_NUMBERED_REFERENCE_READ_NODE,
.location = YP_LOCATION_TOKEN_VALUE(name),
}
},
.number = parse_decimal_number(parser, name->start + 1, name->end)
};

return node;
Expand Down
2 changes: 1 addition & 1 deletion test/yarp/snapshots/unparser/corpus/literal/dstr.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test/yarp/snapshots/unparser/corpus/literal/variables.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test/yarp/snapshots/whitequark/nth_ref.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2d37407

Please sign in to comment.